Source Code (Use browser search to find items of interest.)

Class Index

kscd'CDDB (./kdemultimedia/kscd/cddb.h:45)

class CDDB:public QObject
{

    Q_OBJECT

	public:

    CDDB(char *hostname=0, unsigned short int port = 0, unsigned short int timeout = 60);
    ~CDDB();

    typedef enum { INIT=0, ERROR_INIT=1,
                   HELLO=2, ERROR_HELLO=3,
                   READY=4,
                   QUERY=5, ERROR_QUERY=6,
                   CDDB_READ=7,CDDB_READING=70,ERROR_CDDB_READ=8, 
                   CDDB_DONE=9, CDDB_TIMEDOUT=10,
                   INEX_READ=11,
                   REQUEST_SERVER_LIST=12, SERVER_LIST_WAIT=13, GETTING_SERVER_LIST=14,
                   HTTP_REQUEST=15, HTTP_HEADER=16,
		   PROTO=17, DO_NOTHING=127
    } CDDBState;
    
    typedef enum { REGULAR=100, SERVER_LIST_GET=101 } CDDBMode;

    typedef enum {CDDBP,CDDBHTTP,SMTP,UNKNOWN} transport;
    static transport decodeTransport(const char *);

    bool  isConnected() {return connected;};

    void getData(
	QString& data,
	QStrList& titlelist,
	QStrList& extlist, 
	QString& cat, 
	QStrList& discidlist,
	int& revision,
	QStrList& playlist
    );

    void  get_inexact_list(QStrList& inexact_list);
    void  query_exact(QString line);
    void  setPathList(QStrList& paths);
    bool  checkDir(unsigned long magicID, const QString& dir);
    bool  getValue(QString& key,QString& value, QString& data);
    void  serverList(QStrList& list);
    void  cddbgetServerList(QString& server);
    void  close_connection();

    static void  sighandler(int sig);
    static void  setalarm();
    static void  cddb_http_xlat(QString &s);

    void        queryCD(unsigned long magicID,QStrList& querylist);

    bool local_query(
	unsigned long magicID,
	QString&  data,
	QStrList& titlelist,
	QStrList& extlist,
	QString&  category,
	QStrList& discidlist,
	int& revision,
	QStrList& playlist
    );
    QString getCategoryFromPathName(const QString& pathname);

    static bool normalize_server_list_entry(QString &entry);

    void setHTTPProxy(QString host, unsigned short int port);
    void useHTTPProxy(bool flag);

    void setTimeout(unsigned short int timeout);
    unsigned short int getTimeout();

    bool    useHTTPProxy();
    QString getHTTPProxyHost();
    unsigned short int getHTTPProxyPort();
   
 protected:
    
    void 	do_state_machine();
    void 	parse_serverlist_entry();
    void        send_http_command(QString &command);
    bool        next_token();
    
    transport protocol;
        
 public slots:

    void	 cddb_connect(QString& server);
    void	 cddb_connect_internal();
    void         cddb_read(KSocket* sock);
    void         cddb_close(KSocket* sock);
    void         cddb_timed_out_slot();

 signals:

    void        cddb_done();
    void	cddb_timed_out();
    void 	cddb_failed();
    void 	cddb_ready();
    void        cddb_inexact_read();
    void 	cddb_no_info();
    void	get_server_list_done();
    void        get_server_list_failed();

 private:

    QString     domainname;
    QString     username;

    QStrList    inexact_list;
    QTimer 	starttimer;
    QTimer 	timeouttimer;
    QTimer      expecttimer;

    QString 	hostname;
    QStrList    pathlist;

    QString     proxyhost;
    unsigned short int proxyport;
    bool        use_http_proxy;
    QString     cgi;
   
    QString     respbuffer;
    QString     tempbuffer;
    QString     lastline;
    unsigned short int	timeout;
    unsigned short int port;
    bool    	connected;
    bool	readonly;
    KSocket	*sock;

    CDDBState	state;
    CDDBMode    mode;
    CDDBState   saved_state; // I was using stack here, but I guess it's overhead

    struct passwd* pw;     
    QString     category;
    QString	title;
    QStrList 	serverlist;
    unsigned long magicID;
    int         protocol_level;

};

kscd'CDDB::CDDB() (./kdemultimedia/kscd/cddb.cpp:57)

CDDB::CDDB(char *host, unsigned short int _port, unsigned short int _timeout)
{
    hostname   = host;
    port       = _port;
    connected  = false;
    readonly   = false;
    timeout    = _timeout;
    tempbuffer = "";

    sock = 0L;
    state = INIT;

    use_http_proxy=false;
    protocol_level=1;
    // for direct connections assuming CDDB protocol level 1

    // get current user/host name
    struct utsname uts;

    uname(&uts);
    domainname = uts.nodename;
    
    
    if(domainname.isEmpty())
	domainname = "somemachine.nowhere.org";
      
    pw = getpwuid(getuid());
    if (pw)
	username = pw->pw_name;
    else
	username = "anonymous";
//printf("cddb info: host[%s] port[%d] connected[%d] readonly[%d] timeout[%d]\n", host, port, connected, readonly, timeout);
//printf("attemping to connect to cddb...\n");
//fflush(stdout);
    //Connect handlers
    QObject::connect(&starttimer,SIGNAL(timeout()),this,SLOT(cddb_connect_internal()));
    QObject::connect(&timeouttimer,SIGNAL(timeout()),this,SLOT(cddb_timed_out_slot()));

}


kscd'CDDB::~CDDB() (./kdemultimedia/kscd/cddb.cpp:97)

CDDB::~CDDB()
{
    if(sock)
      {
	delete sock;
	sock = 0L;
      }
    timeouttimer.stop();
    starttimer.stop();
} // ~CDDB

void

kscd'CDDB::setTimeout() (./kdemultimedia/kscd/cddb.cpp:109)

CDDB::setTimeout(unsigned short int _timeout)
{
  timeout = _timeout;
} // setTimeout

unsigned short int 

kscd'CDDB::getTimeout() (./kdemultimedia/kscd/cddb.cpp:115)

CDDB::getTimeout( void )
{
  return timeout;
} // getTimeout

void 

kscd'CDDB::sighandler() (./kdemultimedia/kscd/cddb.cpp:121)

CDDB::sighandler(int signum)
{
    signum = signum;
    
/*      if (signum == SIGALRM && connecting == true ){
      mykapp->processEvents();
      mykapp->flushX();
      signal( SIGALRM , CDDB::sighandler );
      setalarm();
*/      fprintf(stderr,"SIGALRM\n");
/*      }
    */

}


kscd'CDDB::setalarm() (./kdemultimedia/kscd/cddb.cpp:136)

void CDDB::setalarm()
{
    struct itimerval  val1;
    struct timeval  tval1;
    struct timeval  tval2;

    tval1.tv_sec = 0;
    tval1.tv_usec = 100000; // 0.1 secs
    tval2.tv_sec = 0;
    tval2.tv_usec = 100000;

    val1.it_interval = tval1;
    val1.it_value    = tval2;

    setitimer(ITIMER_REAL, &val1, 0);
} // setalarm

void 

kscd'CDDB::cddbgetServerList() (./kdemultimedia/kscd/cddb.cpp:154)

CDDB::cddbgetServerList(QString& _server)
{
    char ser   [CDDB_FIELD_BUFFER_LEN];
    char por   [CDDB_FIELD_BUFFER_LEN];
    char proto [CDDB_FIELD_BUFFER_LEN];
    char extra [CDDB_FIELD_BUFFER_LEN];
  
    sscanf(_server.data(),"%s %s %s %s",ser,proto,por,extra);
  
    hostname  = ser;
    port      = atoi(por);
    cgi       = extra;

    protocol=decodeTransport(proto);

    debug("GETTING SERVERLIST\n");

    mode = SERVER_LIST_GET;

    if(protocol==CDDBHTTP)
      {
	cddb_connect_internal();
	if(connected)
	  {
	    QString cmd="sites";
	    send_http_command(cmd);
	    if(use_http_proxy)
	      {
		saved_state=SERVER_LIST_WAIT;
		state=HTTP_REQUEST;
	      } else {
		state = SERVER_LIST_WAIT;
	      }
	  }
      } else {
	starttimer.start(100,TRUE);
      }
} // cddbgetServerList

void 

kscd'CDDB::cddb_connect() (./kdemultimedia/kscd/cddb.cpp:194)

CDDB::cddb_connect(QString& _server)
{
    char ser[CDDB_FIELD_BUFFER_LEN];
    char por[CDDB_FIELD_BUFFER_LEN];
    char proto[CDDB_FIELD_BUFFER_LEN];
    char extra[CDDB_FIELD_BUFFER_LEN];
  
    sscanf(_server.data(),"%s %s %s %s",ser,proto,por,extra);
  
    hostname  = ser;
    port      = atoi(por);
    cgi       = extra;
    protocol  = decodeTransport(proto);
  
    mode = REGULAR;
    if(protocol==CDDBP)
      {
	// --HERE--
	starttimer.start(100,TRUE);
      } else {
	emit cddb_ready();
      }
} // cddb_connect

void 

kscd'CDDB::cddb_connect_internal() (./kdemultimedia/kscd/cddb.cpp:219)

CDDB::cddb_connect_internal()
{
    starttimer.stop();
    timeouttimer.start(timeout*1000,TRUE);

    debug("timeout = %d\n", timeout*1000);

    if(sock) 
      {
	delete sock;
	sock = 0L;
      }

    // signal( SIGALRM , CDDB::sighandler );
    // setalarm();

    if(protocol==CDDBHTTP && use_http_proxy)
      {
	debug("CONNECTING TO %s:%d ....\n",proxyhost.data(),proxyport);
	sock = new KSocket(proxyhost.data(),proxyport);
	debug("SOCKET SET");
      } else {
	debug("CONNECTING TO %s:%d ....\n",hostname.data(),port);
	sock = new KSocket(hostname.data(),port);
	debug("SOCKET SET");
      }
    
    //signal( SIGALRM , SIG_DFL );

    if(sock == 0L || sock->socket() < 0)
      {
	timeouttimer.stop();
	
	debug("CONNECT FAILED\n");
	
	if(mode == REGULAR )
	    emit cddb_failed();      
	else // mode == SERVER_LIST_GET
	  emit get_server_list_failed();
	
	connected = false;
	return;    
      }
    
    connected = true;
    respbuffer = "";
    
    connect(sock,SIGNAL(readEvent(KSocket*)),this,SLOT(cddb_read(KSocket*)));
    connect(sock,SIGNAL(closeEvent(KSocket*)),this,SLOT(cddb_close(KSocket*)));
    sock->enableRead(true);
    
    if(protocol==CDDBHTTP)
      {
	protocol_level=3;
	state=READY;
      } else {
	protocol_level=1;
	state = INIT;
      }
    
    debug("CONNECTED\n");
} // cddb_connect_internal

void 

kscd'CDDB::send_http_command() (./kdemultimedia/kscd/cddb.cpp:283)

CDDB::send_http_command(QString &command)
{
    QString request;
    QString prt;
    QString prot;
    QString identification;
    
    prot.setNum(protocol_level);
    identification="&hello="+username+"+"+domainname+"+Kscd+"+KSCDVERSION+"&proto="+prot;

    prt.setNum(port);
    QString base  = "http://"+hostname+":"+prt;

    cddb_http_xlat(command);

    if(use_http_proxy)
	request="GET "+base+cgi+"?cmd="+command+identification+" HTTP/1.0\r\n\r\n";
    else
	request="GET "+cgi+"?cmd="+command+identification+"\r\n";
    
    debug("Sending HTTP request: %s",request.data());
    
    write(sock->socket(),request.data(),request.length());
    timeouttimer.stop();
    timeouttimer.start(timeout*1000,TRUE);
} // send_http_command

void 

kscd'CDDB::cddb_timed_out_slot() (./kdemultimedia/kscd/cddb.cpp:311)

CDDB::cddb_timed_out_slot()
{
    timeouttimer.stop();

    if(sock) 
	sock->enableRead(false);

    if( mode == REGULAR )
	emit cddb_timed_out();
    else // mode == SERVER_LIST_GET
	emit get_server_list_failed();

    state = CDDB_TIMEDOUT;
    debug("SOCKET CONNECTION TIMED OUT\n");
    cddb_close(sock);
} // cddb_timed_out_slot

// called externally if we want to close or interrupt the cddb connection
void 

kscd'CDDB::close_connection() (./kdemultimedia/kscd/cddb.cpp:330)

CDDB::close_connection()
{
    if(sock)
    {
	cddb_close(sock);
	sock = 0L;
    }
} // close_connection

void 

kscd'CDDB::cddb_close() (./kdemultimedia/kscd/cddb.cpp:340)

CDDB::cddb_close(KSocket *socket)
{
    timeouttimer.stop();
    disconnect(socket,SIGNAL(readEvent(KSocket*)),this,SLOT(cddb_read(KSocket*)));
    disconnect(socket,SIGNAL(closeEvent(KSocket*)),this,SLOT(cddb_close(KSocket*)));
    socket->enableRead(false);
    debug("SOCKET CONNECTION TERMINATED\n");
    connected = false;
    if(socket)
      {
	delete socket;
	socket = 0L;
	sock = 0L;
      }
} // cddb_close

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <kstddirs.h>
#include <kglobal.h>

void 

kscd'CDDB::cddb_read() (./kdemultimedia/kscd/cddb.cpp:363)

CDDB::cddb_read(KSocket *socket)
{
    int  n;
    char buffer[CDDB_READ_BUFFER_LEN];
    
    if(socket == 0L || socket->socket() < 0)
	return;

    memset(buffer,0,CDDB_READ_BUFFER_LEN);
    n = read(socket->socket(), buffer, CDDB_READ_BUFFER_LEN-1 );
    buffer[n] = '\0';
    tempbuffer += buffer;

//    debug("BUFFER: '%s'",buffer);

    while(next_token())
        do_state_machine();
} // cddb_read

bool 

kscd'CDDB::next_token() (./kdemultimedia/kscd/cddb.cpp:383)

CDDB::next_token()
{
    int newlinepos = tempbuffer.find('\n');
    if(newlinepos != -1)
      {
	lastline    = tempbuffer.left(newlinepos);
	tempbuffer  = tempbuffer.right(tempbuffer.length() - newlinepos -1);
	return true;
      } else {
	return false;
      }
} // next_token

void 

kscd'CDDB::queryCD() (./kdemultimedia/kscd/cddb.cpp:397)

CDDB::queryCD(unsigned long _magicID,QStrList& querylist)
{
//    if(state == DO_NOTHING)
//        return;
//    state = DO_NOTHING;
    if((sock == 0L || sock->socket() < 0) && protocol==CDDBP)
	return;

    QString str;
    title = "";
    category = "";
    magicID = _magicID;

    str = str.sprintf("cddb query %08lx %u ",magicID,querylist.count()-1);
    for(int i = 0; i <(int) querylist.count(); i++) 
      {
	str += querylist.at(i);
	str += " ";
      }

    if(protocol==CDDBHTTP)
      {
	cddb_connect_internal();
	if(connected)
	  {
	    QString param = str;
	    send_http_command(param);
	    if(use_http_proxy)
	      {
		saved_state = QUERY;
		state       = HTTP_REQUEST;
	      } else {
		state  = QUERY;
	      }
	  }
      } else {
	// CDDB
	timeouttimer.stop();
	timeouttimer.start(timeout*1000,TRUE);
	str += "\n";
	debug("strdata: %s\n", str.data());
	write(sock->socket(),str.data(),str.length());
        state  = QUERY;
      }
} // queryCD

void 

kscd'CDDB::query_exact() (./kdemultimedia/kscd/cddb.cpp:444)

CDDB::query_exact(QString line)
{
  int category_start = 0;
  int category_end 	 = 0;
  int magic_start 	 = 0;
  int magic_end 	 = 0;
  
  QString magicstr;
  
  category_start = line.find(" ",0,true) + 1;
  category_end = line.find(" ",category_start,true);
  category = line.mid(category_start,category_end-category_start);
  
  magic_start = category_end + 1;
  magic_end = line.find(" ",magic_start,true);
  magicstr = line.mid( magic_start, magic_end - magic_start);
  
  title = line.mid(magic_end + 1,line.length());
  
  QString readstring;
  if((sock == 0L || sock ->socket() < 0) && protocol==CDDBP)
    {
      debug("sock = 0L!!!\n");
      return;
    }
  
  if(protocol==CDDBHTTP)
    {
      cddb_connect_internal();
      if(connected)
	{
	  readstring.sprintf("cddb read %s %s",category.data(),magicstr.data());
	  send_http_command(readstring);
	}
    } else {
      // CDDB
      timeouttimer.stop();
      timeouttimer.start(timeout*1000,TRUE);
      //  readstring.sprintf("cddb read %s %lx \n",category.data(),magicID);
      readstring.sprintf("cddb read %s %s \n",category.data(),magicstr.data());
      write(sock->socket(),readstring.data(),readstring.length());
    }
  
  state = CDDB_READ;
  respbuffer = "";
  sock->enableRead(true);
} // query_exact


void 

kscd'CDDB::do_state_machine() (./kdemultimedia/kscd/cddb.cpp:494)

CDDB::do_state_machine()
{
    static int cddbfh = 0;
    int cddblinelen;


    debug("STATE MACHINE: State: %d Got: %s\n",(int)state,lastline.data());

    switch (state)
      {
      case HTTP_HEADER:
        
        if(lastline.stripWhiteSpace()==QString(""))
	  {
            state=saved_state;
	    debug("HTTP Header is done. Moving on.\n");
	  }
        break;
	
      case HTTP_REQUEST:
	//Parse responce and check numeric code.
	char proto [CDDB_FIELD_BUFFER_LEN];
	char code  [CDDB_FIELD_BUFFER_LEN];
	sscanf(lastline.data(),"%s %s",proto,code);
	if(strcmp(code,"200")==0)
	  {
            if(use_http_proxy)
	      {
                state=HTTP_HEADER;
                debug("HTTP request is OK. Reading HTTP header.\n");
	      } else {
                state=saved_state;
                debug("HTTP request is OK. Mooving on.\n");
	      }
	  } else {
	    debug("HTTP error: %s\n",lastline.data());
	    if(saved_state==SERVER_LIST_WAIT)
	      {
		emit get_server_list_failed();
	      }
	    state=CDDB_DONE; //TODO: some error state
	  }
	break;
	
      case INIT:
        debug("case INIT == true\n");
	if((lastline.left(3) == QString("201")) ||(lastline.left(3) == QString("200")) )
	  {
	    debug("next if == true\n");
	    QString hellostr;
	    
	    // cddb hello username hostname clientname version
	    hellostr = QString("cddb hello %1 %2 Kscd %3\n")
	      .arg(username)
	      .arg(domainname)
	      .arg(KSCDVERSION);
            debug("hellostr: %s\n", hellostr.data());
	    
	    Ret = write(sock->socket(),hellostr.data(),hellostr.length());
	    debug("write() returned: %d [%s]\n", Ret, strerror(errno));
	    state = HELLO;
	  } else {
	    state = ERROR_INIT;	
	    cddb_close(sock);
	    debug("ERROR_INIT\n");
	    emit cddb_failed();
	  }

	respbuffer = "";
	break;
	
      case HELLO:
	if(lastline.left(3) == QString("200"))
	  {
	    // Negotiate protocol level
	    state = PROTO;
	    // Let's try to request protocol level 3
	    // so we'll get list of servers with protocol.
	    write(sock->socket(),"proto 3\n",8); 
	  } else {
	    state = ERROR_HELLO;
	    cddb_close(sock);
	    debug("ERROR_HELLO\n");
	    emit cddb_failed();
	  }
	
	respbuffer = "";
	break;
	
      case PROTO:
	if(lastline.left(3) == QString("201"))
	  protocol_level=3;
	else
	  protocol_level=1;
	
	state = READY;
	if(mode == REGULAR)
	  {
	    emit cddb_ready();
	  } else {
	    write(sock->socket(),"sites\n",6);
	    state = SERVER_LIST_WAIT;
	  }
	break;
	
      case QUERY:
	if(lastline.left(3) == QString("200"))
	  {
	    query_exact(lastline);
	  } else {
	    if(lastline.left(3) == QString("211"))
	      {
		inexact_list.clear();
		state = INEX_READ;
	      } else {
		if(lastline.left(3) == QString("202"))
		  {
		    state = CDDB_DONE;
		    
		    cddb_close(sock);
		    emit cddb_no_info();
		  } else {
		    state = ERROR_QUERY;
		    cddb_close(sock);
		    debug("ERROR_QUERY\n");
		    emit cddb_failed();
		  }
	      }
	  }
	break;

      case INEX_READ:
	
	if(lastline.at(0) == '.')
	  {
	    state = CDDB_DONE;
	    timeouttimer.stop();
	    emit cddb_inexact_read();
	  } else {
 	    inexact_list.append(lastline.ascii());
	  }
	break;

      case CDDB_READING:
	if(lastline.at(0) == '.')
	  {
	    close(cddbfh);
	    cddbfh = 0;
            if(protocol!=CDDBHTTP)
	      write(sock->socket(),"quit\n",6);
            state = CDDB_DONE;
	    
	    cddb_close(sock);
	    emit cddb_done();
	  } else {
            if(!cddbfh)
	      {
		QString file;
		file.sprintf("%s/%08lx", category.ascii(), magicID);
		file = locate("cddb", file);
		
		debug("dir/file path: %s\n", file.ascii());
		cddbfh = open(file.ascii(), O_CREAT|O_WRONLY|O_TRUNC,
			      S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
	      }
            cddblinelen = lastline.length();
            write(cddbfh, lastline.data(), cddblinelen);
            write(cddbfh, "\n", strlen("\n"));
	    //            debug("line written: %d\n", cddblinelen);
            
            respbuffer.prepend("\n");
            respbuffer.prepend(lastline);
	  }
        break;

    case CDDB_READ:

	if(lastline.at(0) == '4')
	  {
	    state = ERROR_CDDB_READ;
	    debug("ERROR_CDDB_READ\n");
	    cddb_close(sock);
	    emit cddb_failed();
	  } else {
            respbuffer="";
            state = CDDB_READING;
	  }
	break;
	
      case SERVER_LIST_WAIT:

	if(lastline.left(3) == QString("210"))
	  {
            serverlist.clear();
            state=GETTING_SERVER_LIST;
	  } else {
            state=CDDB_DONE;
            emit get_server_list_failed();
	  }
        break;
	
      case GETTING_SERVER_LIST:
	if(lastline.at(0) == '.')
	  {
            debug("GOT SERVERLIST\n");
            if(protocol!=CDDBHTTP)
	      write(sock->socket(),"quit\n",6);
	    cddb_close(sock);
	    emit get_server_list_done();
	    state = CDDB_DONE;
	  } else {
	    parse_serverlist_entry();
	  }
	break;
	
      default:
	break;
      }
    lastline="";
} // do_state_machine


void 

kscd'CDDB::serverList() (./kdemultimedia/kscd/cddb.cpp:717)

CDDB::serverList(QStrList& list)
{
  list = serverlist;
}

void

kscd'CDDB::parse_serverlist_entry() (./kdemultimedia/kscd/cddb.cpp:723)

CDDB::parse_serverlist_entry()
{
    char serv  [CDDB_FIELD_BUFFER_LEN];
    char po    [CDDB_FIELD_BUFFER_LEN];
    char proto [CDDB_FIELD_BUFFER_LEN];
    char extra [CDDB_FIELD_BUFFER_LEN];
  
    QString tempstr;

    if(protocol_level<3)
      {
        sscanf(lastline.data(),"%s %s",serv,po);
        tempstr = tempstr.sprintf("%s cddbp %s -",serv,po);
        serverlist.append(tempstr.data());
      } else {
        sscanf(lastline.data(),"%s %s %s %s",serv,proto,po,extra);
        tempstr = tempstr.sprintf("%s %s %s %s",serv,proto,po,extra);
	//         transport tr=decodeTransport(proto);
	//         if(tr==CDDBP || tr==CDDBHTTP)
        serverlist.append(tempstr.data());
      }
} // parse_serverlist_entry

void 

kscd'CDDB::get_inexact_list() (./kdemultimedia/kscd/cddb.cpp:747)

CDDB::get_inexact_list(QStrList& p_inexact_list)
{
    p_inexact_list=inexact_list;
} // get_inexact_list

bool 

kscd'CDDB::local_query() (./kdemultimedia/kscd/cddb.cpp:753)

CDDB::local_query(
		  unsigned  long magicID,
		  QString&  data,
		  QStrList& titlelist,
		  QStrList& extlist,
		  QString&  _category,
		  QStrList& discidlist,
		  int&	 revision,
		  QStrList& playlist
		  )
{
  QStringList pathlist = KGlobal::dirs()->resourceDirs("cddb");
  
  if(pathlist.count() == 0)
    return false;
  
  QDir d;
  
  for(QStringList::ConstIterator it = pathlist.begin() ; it != pathlist.end(); it++)
    { 
      d.setPath(*it);
      d.setFilter( QDir::Dirs);
      d.setSorting( QDir::Size);
      
      QStringList list = d.entryList();
      QStringList::Iterator it2;    
      
      for(it2 = list.begin(); it2 != list.end(); it2++)
	{
	  if (*it2 != "." && *it2 != "..")
	    {
	      if(checkDir(magicID, *it + *it2))
		{
		  category = *it2;
		  
		  getData(data,titlelist,extlist,_category,discidlist,revision,playlist);
		  return true;
		}
	    }
	}
    }
  return false;
} // local_query

bool 

kscd'CDDB::checkDir() (./kdemultimedia/kscd/cddb.cpp:798)

CDDB::checkDir(unsigned long magicID, const QString& dir)
{
    QString mag;
    mag.sprintf("%s/%08lx",dir.ascii(),magicID);

    QFileInfo info(mag);
    if(!info.isReadable())
	return false;

    respbuffer = "";

    QFile file(mag.data());

    if( !file.open( IO_ReadOnly )) 
      {
	return false;
      }
    
    QTextStream t(&file);
    
    while ( !t.eof() ) 
      {
	QString s = t.readLine() + "\n";
	if(!t.eof())
	  respbuffer += s;
      }

    file.close();
    return true;
} // checkDir

// scan the relevant parts of the cddba database entry in the the provied structures
void 

kscd'CDDB::getData() (./kdemultimedia/kscd/cddb.cpp:831)

CDDB::getData(
	      QString& data,
	      QStrList& titles, 
	      QStrList& extlist,
	      QString& categ,
	      QStrList& discidlist, 
	      int& revision,
	      QStrList& playlist
	      )
{
  data = "";
  titles.clear();
  extlist.clear();
  discidlist.clear();
  categ      = category;
  data       = respbuffer;
    
  
    int pos1,pos2,pos3,pos4 = 0;

    int revtmp = data.find("Revision:",0,true);
    if(revtmp == -1)
      {
	revision = 1;
      } else {
	QString revstr;
	int revtmp2;
	revtmp2 = data.find("\n",revtmp,true);
	if(revtmp2 - revtmp - 9 >=0)
	  revstr = data.mid(revtmp +9,revtmp2 - revtmp -9);
	revstr.stripWhiteSpace();
	bool ok;
	revision = revstr.toInt(&ok);
	if(!ok)
	  revision = 1;
	debug("REVISION %d\n",revision);
      }
    
    // lets get all DISCID's in the data. Remeber there can be many DISCID's on
    // several lines separated by commas on each line
    //
    // DISCID= 47842934,4h48393,47839492
    // DISCID= 47fd2934,4h48343,47839492,43879074

    while((pos3 = data.find("DISCID=",pos4,true))!= -1)
      {
	pos1 = pos3;
	pos2 = data.find("\n",pos1,true);
	
	QString discidtemp;
	QString temp3;
	
	if( pos2 - pos1 -7 >= 0)
	  {
	    discidtemp = data.mid(pos1 + 7,pos2- pos1 -7);
	  } else {
	    debug("ANOMALY 1\n");
	  }

	debug("DISCDID %s\n",discidtemp.data());

	pos1 = 0;
	while((pos2 = discidtemp.find(",",pos1,true)) != -1)
	  {
	    if( pos2 - pos1 >= 0)
	      {
		temp3 = discidtemp.mid(pos1,pos2-pos1);
	      } else {
		debug("ANOMALY 2\n");
	      }
	    
	    temp3 = temp3.stripWhiteSpace();
	    
	    if(!temp3.isEmpty())
	      discidlist.append(temp3.data());
	    pos1 = pos2 + 1;
	  }

	temp3 = discidtemp.mid(pos1,discidtemp.length());
	temp3.stripWhiteSpace();
	
	if(!temp3.isEmpty())
	  {
	    discidlist.append(temp3.data());
	  }
	pos4 = pos3 + 1;
      }// end get DISCID's

    debug("FOUND %d DISCID's\n",discidlist.count());

  // Get the DTITLE

    QString value;
    QString key;
    key = "DTITLE=";

    getValue(key,value,data);
    titles.append(value.ascii());


    int counter = 0;
    key = key.sprintf("TTITLE%d=",counter);
    while(getValue(key,value,data))
      {
	titles.append(value.ascii());
	key = key.sprintf("TTITLE%d=",++counter);
      }
    
    key = "EXTD=";
    getValue(key,value,data);
    extlist.append(value.ascii());
    
    counter = 0;
    key = key.sprintf("EXTT%d=",counter);
    while(getValue(key,value,data))
      {
	extlist.append(value.ascii());
	key = key.sprintf("EXTT%d=",++counter);
      }
    
    key = "PLAYORDER=";
    getValue(key,value,data);
    cddb_playlist_decode(playlist, value);
}


kscd'CDDB::getCategoryFromPathName() (./kdemultimedia/kscd/cddb.cpp:956)

QString CDDB::getCategoryFromPathName(const QString& pathname){
  
    QString path = pathname;
    path = path.stripWhiteSpace();

    while(path.right(1).at(1) == '/'){
	path = path.left(path.length() - 1);
    }

    int pos = 0;
    pos  = path.findRev("/",-1,true);
    if(pos == -1)
	return path;
    else
	return path.mid(pos+1,path.length());

} // getData

bool 

kscd'CDDB::getValue() (./kdemultimedia/kscd/cddb.cpp:975)

CDDB::getValue(QString& key,QString& value, QString& data)
{

    bool found_one = false;
    int pos1 = 0;
    int pos2 = 0;

    value = "";

    while((  pos1 = data.find(key.data(),pos1,true)) != -1)
      {
	found_one = true;
	pos2 = data.find("\n",pos1,true);
	if( (pos2 - pos1 - (int)key.length()) >= 0)
	  {
	    value += data.mid(pos1 + key.length(), pos2 - pos1 - key.length());
	  } else {
	    debug("GET VALUE ANOMALY 1\n");
	  }
	pos1 = pos1 + 1;
      }

    if(value.isNull())
	value = "";

    cddb_decode(value);
    return found_one;
} // getValue

void 

kscd'CDDB::normalize_server_list_entry() (./kdemultimedia/kscd/cddb.cpp:1187)

CDDB::normalize_server_list_entry(QString &entry)
{
    char serv [CDDB_FIELD_BUFFER_LEN];
    char proto[CDDB_FIELD_BUFFER_LEN];
    char po   [CDDB_FIELD_BUFFER_LEN];
    char extra[CDDB_FIELD_BUFFER_LEN];
    
    if(sscanf(entry.data(),"%s %s %s %s",serv,proto,po,extra)==2) 
      {
	// old format
	sprintf(extra,"%s cddbp %s -",serv, proto);
	entry=extra;
	return true;
      } else {
	// Otherwise let us leave the item unchanged.
	return false;
      }
} // normalize_server_list_entry

void 

kscd'CDDB::setHTTPProxy() (./kdemultimedia/kscd/cddb.cpp:1207)

CDDB::setHTTPProxy(QString host, unsigned short int port)
{
  proxyhost=host;
  proxyport=port;
} // setHTTPProxy

void 

kscd'CDDB::useHTTPProxy() (./kdemultimedia/kscd/cddb.cpp:1214)

CDDB::useHTTPProxy(bool flag)
{
    use_http_proxy=flag;
} // useHTTPProxy(bool)

bool

kscd'CDDB::useHTTPProxy() (./kdemultimedia/kscd/cddb.cpp:1220)

CDDB::useHTTPProxy()
{
    return use_http_proxy;
} // useHTTPProxy

unsigned short 

kscd'CDDB::getHTTPProxyPort() (./kdemultimedia/kscd/cddb.cpp:1226)

int CDDB::getHTTPProxyPort()
{
    return proxyport;
} // getHTTPProxyPort

QString 

kscd'CDDB::getHTTPProxyHost() (./kdemultimedia/kscd/cddb.cpp:1232)

CDDB::getHTTPProxyHost()
{
    return proxyhost;
} // getHTTPProxyHost

CDDB::transport 
CDDB::decodeTransport(const char *proto)
{
    if(strcasecmp(proto,"cddbp")==0)
        return CDDBP;
    else
        if(strcasecmp(proto,"http")==0)
            return CDDBHTTP;
        else
            if(strcasecmp(proto,"smtp")==0)
                return SMTP;
            else
                return UNKNOWN;
} // decodeTransport

void 

kscd'CDDB::cddb_http_xlat() (./kdemultimedia/kscd/cddb.cpp:1253)

CDDB::cddb_http_xlat(QString &s)
{
    char q[6];

    if(s.isEmpty())
        return;

    unsigned int pos=0;
    while(pos < s.length()+1)
      {
        switch (s[pos].latin1()) 
	  {
	  case ' ':
            s[pos]='+';
            pos++;
            break;
	  case '?':
	  case '=':
	  case '+':
	  case '&':
	  case '%':
            (void) sprintf(q, "%%%02X", (char) s[pos].latin1());
            s.remove(pos,1);
            s.insert(pos+1,q);
            pos += 3;
            break;
	  default:
            pos++;
	  }
      }
} // cddb_http_xlat


void 

kscd'CDDB::setPathList() (./kdemultimedia/kscd/cddb.cpp:1287)

CDDB::setPathList(QStrList& _paths)
{
    pathlist = _paths; // automatically makes deep copies is _paths has deep copies
} // setPathList