1 /***************************************************************************
2 * Copyright (C) 2003 by Hideki Ikemoto *
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 ***************************************************************************/
16 #include <kio/slaveconfig.h>
17 #include <kio/jobclasses.h>
18 #include <kio/scheduler.h>
22 #include <qapplication.h>
26 #include "qcp932codec.h"
30 ThreadFactory* ThreadFactory::instance = 0;
32 Thread::Thread() : m_board( 0 )
36 Thread::Thread(const Board& board, const KURL& datURL, const QString threadName, int resNum)
37 : m_datURL(datURL), m_threadName(threadName), m_resNum(resNum)
39 Q_ASSERT( datURL.url().right( 3 ) == QString( "dat" ) );
41 m_datID = m_datURL.filename().section(".", 0, 0);
42 m_board = new Board( board.url(), board.name() );
43 m_boardID = m_board->id();
46 Thread::Thread(const Board* board, const KURL& datURL, const QString threadName, int resNum)
47 : m_datURL(datURL), m_threadName(threadName), m_resNum(resNum)
49 m_datID = m_datURL.filename().section(".", 0, 0);
50 m_board = new Board( board->url(), board->name() );
51 m_boardID = m_board->id();
54 Thread::Thread( const Thread& obj )
56 m_datURL = obj.m_datURL;
57 m_datID = obj.m_datID;
58 m_boardID = obj.m_boardID;
59 m_threadName = obj.m_threadName;
60 m_resNum = obj.m_resNum;
61 m_board = new Board( obj.m_board->url(), obj.m_board->name() );
69 Thread& Thread::operator=( const Thread& obj )
71 m_datURL = obj.m_datURL;
72 m_datID = obj.m_datID;
73 m_boardID = obj.m_boardID;
74 m_threadName = obj.m_threadName;
75 m_resNum = obj.m_resNum;
76 m_board = new Board( obj.m_board->url(), obj.m_board->name() );
81 const KURL& Thread::datURL() const
86 const KURL Thread::url() const
88 KURL url = KURL(m_datURL, "/test/read.cgi/");
89 url.addPath(m_boardID + "/");
90 url.addPath(m_datID + "/");
95 const QString& Thread::datID() const
100 int Thread::resNum() const
105 const QString& Thread::name() const
110 const QString& Thread::boardName() const
112 return m_board->name();
115 const KURL& Thread::boardUrl() const
117 return m_board->url();
120 const QString Thread::boardId() const
122 return m_board->id();
125 const QString Thread::toXmlFragment() const
129 ret += "<thread xmlns=\"http://kita.sourceforge.jp/ns/thread\">\n";
130 ret += QString("<daturl>%1</daturl>\n").arg( m_datURL.url() );
131 ret += QString("<name>%1</name>\n").arg( m_threadName );
132 ret += QString("<resnum>%1</resnum>\n").arg( m_resNum );
133 ret += m_board->toXmlFragment();
134 ret += "</thread>\n";
139 Thread Thread::fromXml( const QString& xml )
143 ThreadXmlParser parser;
144 QXmlSimpleReader reader;
145 QXmlInputSource source;
146 source.setData( xml );
147 reader.setContentHandler( &parser );
148 reader.parse( &source );
150 if( parser.isValid() ) {
151 thread = parser.getThread();
153 kdError() << "inValid" << endl;
161 kdDebug() << "Thread::test()" << endl;
162 Thread thread = Thread::fromXml( "<thread xmlns=\"http://kita.sourceforge.jp/ns/thread\">\n"
163 "<daturl>http://pc.2ch.net/linux/dat/1022744633.dat</daturl>\n"
164 "<name>2ch browser thread</name>\n"
165 "<resnum>700</resnum>\n"
166 "<board xmlns=\"http://kita.sourceforge.jp/ns/board\">\n"
167 "<url>http://pc.2ch.net/linux/</url>\n"
168 "<name>Linux</name>\n"
172 // TODO: ¤³¤³¤Ç»È¤ï¤ì¤Æ¤¤¤ëkdError¤Î»³¤Ï²¿¤È¤«¤·¤¿¤¤¡£
173 if( thread.datURL().url() != "http://pc.2ch.net/linux/dat/1022744633.dat" ) {
174 kdError() << "inValid: line=" << __LINE__ << endl;
176 if( thread.url().url() != "http://pc.2ch.net/test/read.cgi/linux/1022744633/" ) {
177 kdError() << "inValid: line=" << __LINE__ << endl;
179 if( thread.name() != "2ch browser thread" ) {
180 kdError() << "inValid: line=" << __LINE__ << endl;
182 if( thread.resNum() != 700 ) {
183 kdError() << "inValid: line=" << __LINE__ << endl;
185 if( thread.getBoard()->url().url() != "http://pc.2ch.net/linux/" ) {
186 kdError() << "inValid: line=" << __LINE__ << endl;
188 if( thread.getBoard()->name() != "Linux" ) {
189 kdError() << "inValid: line=" << __LINE__ << endl;
192 Thread thread2 = Thread::fromXml( thread.toXmlFragment() );
194 if( thread2.datURL().url() != "http://pc.2ch.net/linux/dat/1022744633.dat" ) {
195 kdError() << "inValid: line=" << __LINE__ << endl;
197 if( thread2.url().url() != "http://pc.2ch.net/test/read.cgi/linux/1022744633/" ) {
198 kdError() << "inValid: line=" << __LINE__ << endl;
200 if( thread2.name() != "2ch browser thread" ) {
201 kdError() << "inValid: line=" << __LINE__ << endl;
203 if( thread2.resNum() != 700 ) {
204 kdError() << "inValid: line=" << __LINE__ << endl;
206 if( thread2.getBoard()->url().url() != "http://pc.2ch.net/linux/" ) {
207 kdError() << "inValid: line=" << __LINE__ << endl;
209 if( thread2.getBoard()->name() != "Linux" ) {
210 kdError() << "inValid: line=" << __LINE__ << endl;
213 kdDebug() << thread.toXmlFragment() << endl;
215 thread = Thread::fromXml( "<thread xmlns=\"http://kita.sourceforge.jp/ns/thread\">\n"
216 " <daturl>http://pc.2ch.net/linux/dat/1022744633.dat</daturl>\n"
217 " <name>2ch browser thread</name>\n"
218 " <resnum>700</resnum>\n"
219 " <board xmlns=\"http://kita.sourceforge.jp/ns/board\">\n"
220 " <url>http://pc.2ch.net/linux/</url>\n"
221 " <name>Linux</name>\n"
225 if( thread.datURL().url() != "http://pc.2ch.net/linux/dat/1022744633.dat" ) {
226 kdError() << "inValid: line=" << __LINE__ << endl;
228 if( thread.url().url() != "http://pc.2ch.net/test/read.cgi/linux/1022744633/" ) {
229 kdError() << "inValid: line=" << __LINE__ << endl;
231 if( thread.name() != "2ch browser thread" ) {
232 kdError() << "inValid: line=" << __LINE__ << endl;
234 if( thread.resNum() != 700 ) {
235 kdError() << "inValid: line=" << __LINE__ << endl;
237 if( thread.getBoard()->url().url() != "http://pc.2ch.net/linux/" ) {
238 kdError() << "inValid: line=" << __LINE__ << endl;
240 if( thread.getBoard()->name() != "Linux" ) {
241 kdError() << "inValid: line=" << __LINE__ << endl;
247 bool ThreadXmlParser::startElement( const QString& namespaceURI, const QString& localName, const QString& qName, const QXmlAttributes& atts )
250 m_boardParser->startElement( namespaceURI, localName, qName, atts );
251 } else if( m_inThread ) {
252 if( localName == "daturl" ) {
253 } else if( localName == "name" ) {
254 } else if( localName == "resnum" ) {
255 } else if( localName == "board" ) {
257 m_boardParser = new BoardXmlParser();
258 m_boardParser->startElement( namespaceURI, localName, qName, atts );
264 if( localName == "thread" ) {
275 // TODO: <resnum>¤ÏFavorites¤Ç¤Ï»È¤ï¤Ê¤¤¤³¤È¤Ë¤Ê¤Ã¤¿¤Î¤Çºï½ü¤¹¤ëɬÍפ¢¤ê¡£
276 bool ThreadXmlParser::endElement( const QString& namespaceURI, const QString& localName, const QString& qName )
278 if( localName == "board" ) {
280 m_boardParser->endElement( namespaceURI, localName, qName );
281 Board board = m_boardParser->getBoard();
282 m_board = new Board( board.url(), board.name() );
284 delete m_boardParser;
288 } else if( m_inBoard ) {
289 m_boardParser->endElement( namespaceURI, localName, qName );
290 } else if( localName == "thread" ) {
292 m_thread = Kita::Thread( *m_board, KURL( m_datUrlStr ), m_threadName, m_resNum );
295 } else if( localName == "daturl" ) {
296 m_datUrlStr = m_characters;
297 } else if( localName == "name" ) {
298 m_threadName = m_characters;
299 } else if( localName == "resnum" ) {
300 m_resNum = m_characters.toInt();
308 bool ThreadXmlParser::characters( const QString& ch )
311 m_boardParser->characters( ch );
318 QString ThreadAccess::get()
320 if ( m_thread.datURL().protocol() != "k2ch" ) {
321 KIO::SlaveConfig::self()->setConfigData("http",
322 m_thread.datURL().host(),
324 QString( "Monazilla/1.00 (Kita/%1)" ).arg( VERSION ) );
327 KIO::TransferJob* job = KIO::get(m_thread.datURL(), true, true);
330 connect(job, SIGNAL(data(KIO::Job*, const QByteArray&)),
331 SLOT(slotReceiveThreadData(KIO::Job*, const QByteArray&)));
332 connect(job, SIGNAL(result(KIO::Job*)), SLOT(slotThreadResult(KIO::Job*)));
333 connect(job, SIGNAL(redirection(KIO::Job *, const KURL&) ), SLOT(slotRedirection(KIO::Job *, const KURL&) ) );
335 // use 'HTTP-Headers' metadata.
336 job->addMetaData("PropagateHttpHeader", "true");
341 return codec.toUnicode( m_threadData );
344 // from netaccess.cpp
345 void qt_enter_modal( QWidget* widget );
346 void qt_leave_modal( QWidget* widget );
348 void ThreadAccess::enter_loop()
350 QWidget dummy( 0, 0, WType_Dialog | WShowModal );
351 dummy.setFocusPolicy( QWidget::NoFocus );
352 qt_enter_modal(&dummy);
354 qt_leave_modal(&dummy);
357 void ThreadAccess::slotRedirection(KIO::Job *, const KURL & newURL)
359 kdDebug() << "Redirected to newURL: " << newURL.url() << endl;
360 m_thread = Kita::Thread( m_thread.getBoard(), newURL);
361 emit redirection( newURL.url() );
364 void ThreadAccess::slotReceiveThreadData( KIO::Job*, const QByteArray& data )
366 QCString cstr(data.data(), data.size()+1);
367 m_threadData.append(cstr);
370 void ThreadAccess::slotThreadResult(KIO::Job* job)
374 job->showErrorDialog();
376 m_header = job->queryMetaData("HTTP-Headers");
381 void ThreadAccess::killJob()
383 if( m_currentJob ) m_currentJob->kill();
386 int ThreadAccess::serverTime()
388 // parse HTTP headers
389 QStringList headerList = QStringList::split( "\n", m_header );
390 QRegExp regexp( "Date: (...), (..) (...) (....) (..:..:..) .*" );
391 QString dateStr = headerList.grep(regexp)[0];
392 if( regexp.search(dateStr) == -1 ) {
393 // invalid date format
394 return QDateTime::currentDateTime().toTime_t();
396 // I hate this format ;p
397 QString usLocalDateStr = regexp.cap(1) + " " + regexp.cap(3) + " " +
398 regexp.cap(2) + " " + regexp.cap(5) + " " +
401 // 1970/01/01 00:00:00 GMT
402 QDateTime zeroTime(QDate(1970, 1, 1), QTime(0, 0));
403 return zeroTime.secsTo(QDateTime::fromString(usLocalDateStr));
407 void ThreadFactory::insertThread( Thread& thread )
410 instance = new ThreadFactory();
413 Thread* new_thread = new Thread( thread.getBoard(), thread.datURL(), thread.name(), thread.resNum() );
414 instance->m_dict.insert( thread.datURL().url(), new_thread );
417 Thread* ThreadFactory::getThread( QString& datURL )
420 instance = new ThreadFactory();
423 return instance->m_dict[ datURL ];
426 #include "thread.moc"