1 /***************************************************************************
2 * Copyright (C) 2004 by Kita Developers *
3 * ikemo@users.sourceforge.jp *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
9 ***************************************************************************/
11 #include "boardmanager.h"
12 #include "qcp932codec.h"
13 #include "downloadmanager.h"
15 #include "favoritethreads.h"
16 #include "threadinfo.h"
17 #include "favoriteboards.h"
18 #include "datmanager.h"
19 #include "kita_misc.h"
21 #include <config.h> /* VERSION */
24 #include <kio/netaccess.h>
25 #include <kfilterdev.h>
26 #include <kio/slaveconfig.h>
27 #include <kdeversion.h>
32 #include <qdatetime.h>
33 #include <qeucjpcodec.h>
38 /*---------------------------------------------------------*/
42 BoardData::BoardData( const QString& boardName,
43 const QString& hostname,
44 const QString& rootPath,
45 const QString& delimiter,
46 const QString& bbsPath,
50 m_boardName = boardName;
51 m_rootPath = rootPath;
52 m_delimiter = delimiter;
57 /* set hostname and create URL of board */
58 setHostName( hostname );
60 /* create default key */
61 QStringList keyHosts = m_hostname;
62 createKeys( keyHosts );
64 /* reset SETTING.TXT */
65 setSettingLoaded( FALSE );
67 qDebug( "%s (type = %d)", ( const char * ) m_boardName.local8Bit(),m_type );
68 qDebug( "basePath: %s", m_basePath.ascii() );
69 qDebug( "cgiBasePath: %s", m_cgiBasePath.ascii() );
73 BoardData::~BoardData()
78 void BoardData::setHostName( const QString& hostName )
80 m_hostname = hostName;
82 /* m_basePath = (hostname)/(rootPath)/(bbsPath)/ */
83 m_basePath = m_hostname + m_rootPath + m_bbsPath + "/";
87 case Board_2ch: /* m_cgiBasePath = (hostname)/(rootPath)/(delimiter)/(bbsPath)/ */
89 m_cgiBasePath = m_hostname + m_rootPath + m_delimiter + m_bbsPath + "/";
92 case Board_MachiBBS: /* m_cgiBasePath = (hostname)/(rootPath)/(delimiter)?BBS=(bbsPath) */
93 m_cgiBasePath = m_hostname + m_rootPath + m_delimiter + "?BBS=" + m_bbsPath.mid( 1 );
99 /*---------------------------*/
103 const QString& BoardData::boardName() const
109 const QString& BoardData::hostName() const
115 const QString& BoardData::rootPath() const
121 const QString& BoardData::delimiter() const
127 const QString& BoardData::bbsPath() const
133 const QString& BoardData::ext() const
139 const int BoardData::type() const
145 const QString& BoardData::basePath() const
151 const QString& BoardData::cgiBasePath() const
153 return m_cgiBasePath;
157 /*---------------------------*/
161 const QString BoardData::settingURL() const
163 return m_basePath + "SETTING.TXT";
167 const bool BoardData::settingLoaded() const
169 return m_settingLoaded;
173 const QString& BoardData::defaultName() const
175 return m_defaultName;
179 const int BoardData::lineNum() const
185 const KURL& BoardData::titleImgURL() const
187 return m_titleImgURL;
191 void BoardData::setSettingLoaded( bool set )
193 m_settingLoaded = set;
195 m_defaultName == QString::null;
201 void BoardData::setDefaultName( const QString& newName )
203 m_defaultName = newName;
207 void BoardData::setLineNum( int newLine )
213 void BoardData::setTitleImgURL( const KURL& url )
219 /*---------------------------*/
222 /* create keys of DB */ /* public */
223 void BoardData::createKeys( const QStringList& keyHostList )
226 m_keyBasePathList.clear();
227 m_keyCgiBasePathList.clear();
228 m_keyHostList.clear();
230 m_keyHostList = keyHostList;
232 /* m_basePath = (hostname)/(rootPath)/(bbsPath)/ */
233 for( unsigned int i = 0; i < m_keyHostList.count(); ++i ){
234 if( m_keyHostList[i].length() > 0 )
235 m_keyBasePathList += m_keyHostList[i] + m_rootPath + m_bbsPath + "/";
240 case Board_2ch: /* m_cgiBasePath = (hostname)/(rootPath)/(delimiter)/(bbsPath)/ */
242 for( unsigned int i = 0; i < m_keyHostList.count(); ++i )
243 m_keyCgiBasePathList += m_keyHostList[i] + m_rootPath + m_delimiter + m_bbsPath + "/";
246 case Board_MachiBBS: /* m_cgiBasePath = (hostname)/(rootPath)/(delimiter)?BBS=(bbsPath) */
247 for( unsigned int i = 0; i < m_keyHostList.count(); ++i )
248 m_keyCgiBasePathList += m_keyHostList[i] + m_rootPath + m_delimiter
249 + "?BBS=" + m_bbsPath.mid( 1 );
255 const QStringList& BoardData::keyHostList() const
257 return m_keyHostList;
261 const QStringList& BoardData::keyBasePathList() const
263 return m_keyBasePathList;
267 const QStringList& BoardData::keyCgiBasePathList() const
269 return m_keyCgiBasePathList;
275 /*---------------------------------------------------------------*/
276 /*---------------------------------------------------------------*/
277 /*---------------------------------------------------------------*/
281 QCp932Codec* BoardManager::m_cp932Codec = NULL;
282 QEucJpCodec* BoardManager::m_eucJpCodec = NULL;
283 BoardDataList BoardManager::m_boardDataList;
284 BoardData* BoardManager::m_previousBoardData = NULL;
287 BoardManager::BoardManager()
293 BoardManager::~BoardManager()
298 /* (hostname)/(rootPath)/(bbsPath)/ */ /* public */ /* static */
299 const QString BoardManager::boardURL( const KURL& url )
301 BoardData* bdata = getBoardData( url );
302 if( bdata == NULL ) return QString::null;
304 return bdata->basePath();
307 /* public */ /* static */
308 const QStringList BoardManager::allBoardURLList()
313 for ( BoardDataList::Iterator it = m_boardDataList.begin(); it != m_boardDataList.end(); ++it )
314 urlList += (*it)->basePath();
319 /* (hostname)/(rootPath) */ /* public */ /* static */
320 const QString BoardManager::boardRoot( const KURL& url )
322 BoardData* bdata = getBoardData( url );
323 if( bdata == NULL ) return QString::null;
325 return bdata->hostName() + bdata->rootPath();
328 /* (bbspath) */ /* public */ /* static */
329 const QString BoardManager::boardPath( const KURL& url )
331 BoardData* bdata = getBoardData( url );
332 if( bdata == NULL ) return QString::null;
334 return bdata->bbsPath();
337 /* ID of board for writing */ /* public */ /* static */
338 const QString BoardManager::boardID( const KURL& url )
340 BoardData* bdata = getBoardData( url );
341 if( bdata == NULL ) return QString::null;
343 return bdata->bbsPath().mid( 1 ); /* remove "/" */
347 /* (hostname)/(rootPath)/(bbsPath)/subject.txt */ /* public */ /* static */
348 const QString BoardManager::subjectURL( const KURL& url )
350 BoardData* bdata = getBoardData( url );
351 if( bdata == NULL ) return QString::null;
353 return bdata->basePath() + "subject.txt";
357 /* public */ /* static */
358 const QString BoardManager::boardName( const KURL& url )
360 BoardData* bdata = getBoardData( url );
361 if( bdata == NULL ) return QString::null;
363 return bdata->boardName();
367 /* public */ /* static */
368 const int BoardManager::type( const KURL& url )
370 BoardData* bdata = getBoardData( url );
371 if( bdata == NULL ) return Board_Unknown;
373 return bdata->type();
377 /*---------------------------*/
381 /* get list of pointers of Thread classes. */
386 oldLogs: If TRUE, search cache and get list of pointer of old threads.
387 online: online or offline mode.
391 threadList: list of pointers of Thread classes.
392 oldLogList: list of pointers of old threads.
394 */ /* public */ /* static */
395 void BoardManager::getThreadList(
403 QPtrList< Thread >& threadList,
404 QPtrList< Thread >& oldLogList )
409 /* get all obtained threads list from cache */
410 if ( url.prettyURL() == "http://virtual/obtained/" ) {
412 QStringList bbslist = allBoardURLList();
414 /* search all cache dirs */
415 for ( QStringList::iterator it = bbslist.begin() ; it != bbslist.end(); ++it ) {
417 getCachedThreadList( ( *it ), threadList );
423 /*-------------------------*/
425 /* download subject.txt */
429 QString cacheDir = Cache::baseDir() + Cache::serverDir( url ) + Cache::boardDir( url );
430 if( !Kita::mkdir( cacheDir ) ) return;
432 KIO::SlaveConfig::self() ->setConfigData( "http",
435 QString( "Monazilla/1.00 (Kita/%1)" ).arg( VERSION ) );
436 QString subjectPath = Cache::getSubjectPath( url );
437 #if KDE_IS_VERSION( 3, 2, 0 )
438 KIO::NetAccess::download( subjectURL( url ), subjectPath, NULL );
440 KIO::NetAccess::download( subjectURL( url ), subjectPath );
443 /* download SETTING.TXT */
444 loadBBSSetting( url );
447 /* open and read subject.txt */
448 readSubjectTxt( url, threadList );
453 QPtrList< Thread > tmpList;
455 getCachedThreadList( url, tmpList );
457 for ( unsigned i = 0; i < tmpList.count(); i++ ) {
459 if( threadList.contains( tmpList.at( i ) ) == 0 ) oldLogList.append( tmpList.at( i ) );
466 /* read the cache dir & get the list of all threads. */ /* private */ /* static */
467 void BoardManager::getCachedThreadList( const KURL& url, QPtrList< Thread >& threadList )
469 QString cacheDir = Cache::baseDir() + Cache::serverDir( url ) + Cache::boardDir( url );
472 qDebug( "search: %s", cacheDir.ascii() );
474 /* get all file names */
475 QString ext = BoardManager::getBoardData( url )->ext();
476 QString boardURL = BoardManager::getBoardData( url )->basePath();
477 QStringList flist = d.entryList( "*" + ext );
479 for ( QStringList::iterator it = flist.begin(); it != flist.end(); ++it ) {
480 if ( ( *it ) == QString::null ) continue;
482 QString datURL = boardURL + "dat/" + ( *it );
484 QString subject = DatManager::threadName( datURL );
485 if ( subject == QString::null ) Kita::Thread::setName( datURL, "?" );
486 else Kita::Thread::setName( datURL, subject );
488 int readNum = KitaThreadInfo::readNum( datURL );
489 if ( KitaThreadInfo::resNum( datURL ) < readNum ) KitaThreadInfo::setResNum( datURL, readNum );
491 Kita::Thread* thread = Kita::Thread::getByURL( datURL );
492 threadList.append( thread );
494 // qDebug( "url: %s : %s", datURL.ascii(), ( const char * ) subject.local8Bit() );
500 /* open subject.txt and get list of Thread classes */ /* private */ /* static */
501 bool BoardManager::readSubjectTxt( const KURL& url, QPtrList< Thread >& threadList )
503 QString subjectPath = Cache::getSubjectPath( url );
504 QIODevice * device = KFilterDev::deviceForFile( subjectPath, "application/x-gzip" );
505 if( !device->open( IO_ReadOnly ) ) return FALSE;
507 QTextStream stream( device );
509 if ( BoardManager::type( url ) == Board_JBBS ) {
510 if ( !m_eucJpCodec ) m_eucJpCodec = new QEucJpCodec();
511 stream.setCodec( m_eucJpCodec );
513 if ( !m_cp932Codec ) m_cp932Codec = new QCp932Codec();
514 stream.setCodec( m_cp932Codec );
517 // parse subject.txt(only one format...)
518 // FIXME: need to refactoring
520 switch ( BoardManager::type( url ) ) {
522 regexp.setPattern( "(\\d+\\.dat)<>(.*)\\((\\d+)\\)" );
527 regexp.setPattern( "(\\d+\\.cgi),(.*)\\((\\d+)\\)" );
532 while ( ( line = stream.readLine() ) != QString::null ) {
533 int pos = regexp.search( line );
535 QString fname = regexp.cap( 1 );
536 QString subject = regexp.cap( 2 );
537 QString num = regexp.cap( 3 );
539 QString datURL = boardURL( url ) + "dat/" + fname;
540 Kita::Thread::setName( datURL, subject );
541 Kita::Thread* thread = Kita::Thread::getByURL( datURL );
542 KitaThreadInfo::setResNum( datURL, num.toInt() );
543 threadList.append( thread );
553 /*---------------------------*/
556 /* reset all BoardData */ /* public */ /* static */
557 void BoardManager::clearBoardData()
559 for ( BoardDataList::Iterator it = m_boardDataList.begin(); it != m_boardDataList.end(); ++it )
562 m_boardDataList.clear();
563 m_previousBoardData = NULL;
568 /* If the board is moved, return its old URL.
569 Otherwise, return QString::null. */ /* public */ /* static */
570 QString BoardManager::enrollBoard( const KURL& url, const QString& boardName )
572 // qDebug( "enroll %s %s", ( const char * ) boardName.local8Bit(),url.prettyURL().ascii());
579 int type = parseBoardURL( url, hostname, rootPath, delimiter, bbsPath, ext );
581 if( type == Board_Unknown ) return QString::null;
583 /* check if the board is enrolled or moved. */
584 for ( BoardDataList::Iterator it = m_boardDataList.begin(); it != m_boardDataList.end(); ++it ){
586 if( ( *it )->boardName() == boardName
587 && ( *it )->type() == type
588 && ( *it )->bbsPath() == bbsPath ){
590 if( ( *it )->hostName() == hostname
591 && ( *it )->rootPath() == rootPath ){ /* enrolled */
592 // qDebug( "enrolled" );
593 return QString::null;
596 // qDebug( "moved" );
597 return ( *it )->basePath();
602 /* enroll new board */
603 BoardData* bdata = new BoardData( boardName, hostname, rootPath, delimiter, bbsPath, ext, type );
604 m_boardDataList.append( bdata );
606 return QString::null;
610 /* private */ /* static */
611 int BoardManager::parseBoardURL( const KURL& url,
618 int type = Board_Unknown;
620 hostname = url.protocol() + "://" + url.host();
621 rootPath = QString::null;
622 delimiter = QString::null;
623 bbsPath = QString::null;
626 /* MACHI : http:// *.machi.to/(bbsPath)/ */
627 if( url.host().contains( "machi.to" ) ){
629 delimiter = "/bbs/read.pl";
630 bbsPath = url.filename();
632 type = Board_MachiBBS;
635 /* JBBS : http://jbbs.livedoor.jp/(bbsPath)/ */
636 else if( url.host().contains( "jbbs.livedoor.jp" ) ){
638 delimiter = "/bbs/read.cgi";
639 bbsPath = url.prettyURL().remove( hostname );
644 /* 2ch : http://(hostname)/(rootPath)/(bbsPath)/ */
647 delimiter = "/test/read.cgi";
648 bbsPath = url.filename();
649 rootPath = url.prettyURL().remove( hostname + "/" ).remove( bbsPath + "/" );
650 if( rootPath.length() == 0 ) rootPath = QString::null;
655 /* For example, if bbsPath = "linux/", then m_bbsPath = "/linux" */
656 const QRegExp exp( "/$" );
657 rootPath.remove( exp );
658 bbsPath.remove( exp );
659 if( rootPath != QString::null && rootPath.at( 0 ) != '/' ) rootPath = "/" + rootPath;
660 if( bbsPath != QString::null && bbsPath.at( 0 ) != '/' ) bbsPath = "/" + bbsPath;
663 qDebug( "host : %s", hostname.ascii() );
664 qDebug( "root : %s", rootPath.ascii() );
665 qDebug( "deli : %s", delimiter.ascii() );
666 qDebug( "bbs : %s", bbsPath.ascii() );
673 /* public */ /* static */
674 bool BoardManager::isEnrolled( const KURL& url )
676 if( getBoardData( url ) == NULL ) return FALSE;
681 /* public */ /* static */
682 BoardData* BoardManager::getBoardData( const KURL& url )
684 QString urlstr = url.prettyURL();
686 if( m_previousBoardData != NULL ){
687 int count = m_previousBoardData->keyBasePathList().count();
688 for( int i = 0; i < count ; ++i ){
689 if( urlstr.contains( m_previousBoardData->keyBasePathList()[i] )
690 || urlstr.contains( m_previousBoardData->keyCgiBasePathList()[i] ) ){
692 return m_previousBoardData;
697 for ( BoardDataList::Iterator it = m_boardDataList.begin(); it != m_boardDataList.end(); ++it ){
699 int count = (*it)->keyBasePathList().count();
700 for( int i = 0; i < count ; ++i ){
701 if( urlstr.contains( (*it)->keyBasePathList()[i] )
702 || urlstr.contains( (*it)->keyCgiBasePathList()[i] ) ){
704 m_previousBoardData = (*it);
715 /*--------------------------------*/
719 /* load the bbs history file ( BBSHISTORY ), and create keys of Data Base. */
720 /* Before calling this, enroll the board by enrollBoard(). */
722 ex) If the host of board moved like :
724 http:://aaa.com -> http://bbb.com -> http://ccc.com -> http://ddd.com
732 */ /* public */ /* static */
733 bool BoardManager::loadBBSHistory( const KURL& url )
735 BoardData* bdata = getBoardData( url );
736 if( bdata == NULL ) return FALSE;
738 QStringList keyHosts = bdata->hostName();
740 QFile file( Cache::getBBSHistoryPath( url ) );
741 if ( file.open( IO_ReadOnly ) ){
743 qDebug( "read BBSHISTRY : %s",Cache::getBBSHistoryPath( url ).ascii() );
745 QTextStream ts( &file );
750 line = ts.readLine();
751 qDebug("line: %s",line.ascii());
755 bdata->createKeys( keyHosts );
765 /* public */ /* static */
766 bool BoardManager::moveBoard( const KURL& fromURL, const KURL& toURL )
768 QString oldhost = fromURL.protocol() + "://" + fromURL.host();
769 QString newhost = toURL.protocol() + "://" + toURL.host();
771 const QRegExp exp( "/$" );
772 QString oldURL = fromURL.prettyURL();
773 QString newURL = toURL.prettyURL();
774 oldURL.remove( exp );
775 newURL.remove( exp );
779 qDebug( "moveBoard : %s -> %s", oldURL.ascii(), newURL.ascii() );
781 if( oldURL == newURL ) return FALSE;
783 /* Is oldURL enrolled? */
784 BoardData* bdata = getBoardData( oldURL );
787 /* Is newURL enrolled? */
788 bdata = getBoardData( newURL );
789 if( bdata == NULL ) return FALSE;
793 /*---------------------------*/
794 /* updata BoardData */
796 /* get the path of old cache */
797 bdata->setHostName( oldhost );
798 QStringList keyHosts = bdata->keyHostList();
799 keyHosts.remove( oldhost );
800 keyHosts.prepend( oldhost );
801 bdata->createKeys( keyHosts );
802 QString oldCachePath = Cache::baseDir() + Cache::serverDir( bdata->basePath() )
803 + Cache::boardDir( bdata->basePath() );
806 bdata->setHostName( newhost );
809 /* The order of keyHosts will be like this:
817 keyHosts = bdata->keyHostList();
818 keyHosts.remove( oldhost );
819 keyHosts.prepend( oldhost );
820 keyHosts.remove( newhost );
821 keyHosts.prepend( newhost );
822 bdata->createKeys( keyHosts );
825 /*---------------------------*/
830 /* mkdir new server dir */
831 QString newCachePath = Cache::baseDir() + Cache::serverDir( bdata->basePath() );
832 Kita::mkdir( newCachePath );
835 newCachePath += Cache::boardDir( bdata->basePath() );
836 if( qdir.exists ( newCachePath ) ){
837 QString bkupPath = newCachePath;
838 bkupPath.truncate( bkupPath.length() -1 ); /* remove '/' */
839 bkupPath += "." + QString().setNum( QDateTime::currentDateTime().toTime_t() );
840 qDebug( "mv %s\n -> %s", newCachePath.ascii(), bkupPath.ascii() );
841 qdir.rename( newCachePath, bkupPath );
845 qDebug( "old: %s", oldCachePath.ascii() );
846 if( qdir.exists( oldCachePath ) ){
847 qDebug( "move: %s\n-> %s", oldCachePath.ascii(), newCachePath.ascii() );
848 qdir.rename( oldCachePath, newCachePath );
850 else Kita::mkdir( newCachePath );
853 /*---------------------------*/
854 /* update BBSHISTRY */
856 QFile file( Cache::getBBSHistoryPath( bdata->basePath() ) );
857 if ( file.open( IO_WriteOnly ) ){
859 qDebug( "write BBSHISTRY : %s", Cache::getBBSHistoryPath( bdata->basePath() ).ascii() );
860 QTextStream ts( &file );
862 keyHosts.remove( newhost );
863 for ( QStringList::iterator it = keyHosts.begin() ; it != keyHosts.end(); ++it ) {
871 /*---------------------------*/
872 /* update other information */
873 FavoriteThreads::replace( oldURL, newURL );
874 Kita::Thread::replace( oldURL, newURL );
875 KitaThreadInfo::replace( oldURL, newURL );
876 Kita::FavoriteBoards::replace( oldURL, newURL );
878 qDebug("%s",bdata->basePath().ascii() );
879 qDebug("%s",bdata->cgiBasePath().ascii() );
880 int count = bdata->keyBasePathList().count();
881 for( int i = 0; i < count ; ++i ){
882 qDebug("key: %s",bdata->keyBasePathList()[i].ascii() );
883 qDebug("key: %s",bdata->keyCgiBasePathList()[i].ascii() );
890 /*--------------------------------*/
894 /* public */ /* static */
895 bool BoardManager::loadBBSSetting( const KURL& url, bool reload )
897 /* Is board enrolled ? */
898 BoardData* bdata = getBoardData( url );
899 if( bdata == NULL ) return FALSE;
900 if( bdata->type() != Board_2ch ) return FALSE;
902 KURL settingURL = bdata->settingURL();
903 QString path = Cache::getSettingPath( url );
906 if( DownloadManager::isLoadingNow( settingURL ) ) return FALSE;
909 if( bdata->settingLoaded() && !reload ) return TRUE;
911 /* reset names, linenum, etc. */
912 bdata->setSettingLoaded( FALSE );
914 qDebug("LOAD SETTING.TXT : %s",settingURL.prettyURL().ascii());
915 qDebug("path: %s",path.ascii());
917 /* download SETTING.TXT.*/
918 DownloadManager::download( settingURL, path );
919 bdata->setSettingLoaded( TRUE );
925 /* public */ /* static */
926 QString BoardManager::getBBSDefaultName( const KURL& url )
928 BoardData* bdata = openSettingTxt( url );
929 if( bdata == NULL ) return QString::null;
930 return bdata->defaultName();
934 /* public */ /* static */
935 int BoardManager::getBBSMaxLine( const KURL& url )
937 BoardData* bdata = openSettingTxt( url );
938 if( bdata == NULL ) return 0;
939 return bdata->lineNum();
942 /* public */ /* static */
943 const KURL BoardManager::titleImgURL( const KURL& url )
945 BoardData* bdata = openSettingTxt( url );
946 if( bdata == NULL ) return QString::null;
947 return bdata->titleImgURL();
950 /* open local SETTING.TXT, then get names, linenum, etc. */ /* private */ /* static */
951 BoardData* BoardManager::openSettingTxt( const KURL& url )
953 BoardData* bdata = getBoardData( url );
954 if( bdata == NULL ) return NULL;
955 if( !bdata->settingLoaded() ) return NULL;
956 if( DownloadManager::isLoadingNow( bdata->settingURL() ) ) return NULL;
957 if( bdata->defaultName() != QString::null ) return bdata;
959 qDebug( "read SETTING.TXT");
961 QFile file( Cache::getSettingPath( url ) );
962 if ( file.open( IO_ReadOnly ) ){
964 QTextStream ts( &file );
965 if( m_cp932Codec == NULL) m_cp932Codec = new QCp932Codec();
966 ts.setCodec( m_cp932Codec );
971 line = ts.readLine();
972 // qDebug("line: %s\n",(const char *)line.local8Bit());
975 QString key = "BBS_NONAME_NAME=";
976 if( line.find( key ) != -1 ) bdata->setDefaultName( line.remove( key ) );
979 key = "NANASI_NAME=";
980 if( line.find( key ) != -1 ) bdata->setDefaultName( line.remove( key ) );
983 key = "BBS_LINE_NUMBER=";
984 if( line.find( key ) != -1 ) bdata->setLineNum( line.remove( key ).toInt() * 2 );
987 key = "BBS_TITLE_PICTURE=";
988 if( line.find( key ) != -1 ){
989 QString path = line.remove( key );
990 KURL titleImgURL = KURL( bdata->basePath(), path );
991 bdata->setTitleImgURL( titleImgURL );
998 if( bdata->defaultName() == QString::null ) bdata->setDefaultName( "(default name)" );
1000 qDebug( "name: %s", (const char *)bdata->defaultName().local8Bit());
1001 qDebug( "line num: %d", bdata->lineNum() );