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 ***************************************************************************/
12 #include "kita_misc.h"
14 #include "boardmanager.h"
19 #include <kio/slaveconfig.h>
28 Access::Access( const KURL& datURL ) : m_datURL( datURL ), m_currentJob( 0 )
37 m_lastLine = QString::null;
38 m_bbstype = BoardManager::type( m_datURL );
39 m_header = "HTTP/1.1 200 "; /* dummy header */
41 m_threadData = QString::null;
44 /* read data from cache, then emit data to DatInfo. */ /* public */
45 void Access::getcache()
50 QString cachePath = Kita::Cache::getPath( m_datURL );
52 if ( cachePath != QString::null ) {
53 QFile file( cachePath );
54 if ( file.open( IO_ReadOnly ) ) {
55 orgData += file.readAll();
60 if( orgData == QString::null ) return;
61 m_dataSize = orgData.length();
66 case Board_MachiBBS: /* Machi BBS's data is already parsed as 2ch dat. */
69 QString tmpData = Kita::qcpToUnicode( orgData );
70 QStringList tmpList = QStringList::split( "\n", tmpData );
71 emit receiveData( tmpList );
76 emitDatLineList( orgData );
81 /* write data to cache */ /* protected */
82 void Access::writeCacheData()
84 if ( m_invalidDataReceived ) return ;
85 if ( m_threadData.length() == 0 ) return ;
87 m_dataSize += m_threadData.length();
89 QString cachePath = Kita::Cache::getPath( m_datURL );
90 if ( cachePath != QString::null ) {
91 FILE * fs = fopen( QFile::encodeName( cachePath ), "a" );
94 fwrite( m_threadData, m_threadData.length(), 1, fs );
97 m_threadData = QString::null; /* clear baffer */
102 /* update cache file */ /* public */
103 bool Access::getupdate( int readNum )
107 m_threadData = QString::null;
108 m_firstReceive = FALSE;
109 m_invalidDataReceived = FALSE;
110 m_lastLine = QString::null;
112 /* set URL of data */
117 getURL = Kita::getThreadURL( m_datURL );
118 if( m_readNum > 0 ) getURL += "&START=" + QString().setNum( m_readNum +1 );
119 Kita::InitParseMachiBBS();
123 getURL = Kita::getThreadURL( m_datURL );
124 getURL.replace( "read.cgi", "rawmode.cgi" ); /* adhoc... */
125 if( m_readNum > 0 ) getURL += "/" + QString().setNum( m_readNum +1 ) + "-";
129 getURL = m_datURL.prettyURL();
133 const QString useragent = QString( "Monazilla/1.00 (Kita/%1)" ).arg( VERSION );
134 KIO::SlaveConfig::self() ->setConfigData( "http",
135 KURL( getURL ).host(),
136 "UserAgent", useragent );
139 KIO::TransferJob* job = KIO::get( getURL, true, false );
142 connect( job, SIGNAL( data( KIO::Job*, const QByteArray& ) ),
143 SLOT( slotReceiveThreadData( KIO::Job*, const QByteArray& ) ) );
144 connect( job, SIGNAL( result( KIO::Job* ) ), SLOT( slotThreadResult( KIO::Job* ) ) );
146 // use 'HTTP-Headers' metadata.
147 job->addMetaData( "PropagateHttpHeader", "true" );
150 if ( m_bbstype != Board_MachiBBS
151 && m_bbstype != Board_JBBS
152 && m_dataSize > 0 ) {
153 m_firstReceive = TRUE; /* remove first char (i.e. \n). see also slotReceiveThreadData() */
154 job->addMetaData( "resume", QString::number( m_dataSize - 1 ) );
155 job->addMetaData( "AllowCompressedPage", "false" );
161 void Access::slotThreadResult( KIO::Job* job )
164 if ( job->error() ) {
165 job->showErrorDialog();
167 m_header = job->queryMetaData( "HTTP-Headers" );
174 void Access::slotReceiveThreadData( KIO::Job*, const QByteArray& data )
176 QString cstr( data );
178 if( m_bbstype == Board_MachiBBS
179 || m_bbstype == Board_JBBS ){
181 emitDatLineList( cstr );
185 /* check if received data is invalid ( or broken ). */
186 if ( ( m_dataSize > 0 && responseCode() != 206 )
187 || ( m_firstReceive && cstr[ 0 ] != '\n' )
188 || ( m_dataSize == 0 && responseCode() != 200 )
189 ) m_invalidDataReceived = TRUE;
191 if ( m_invalidDataReceived ) return ;
193 /* If this is the first call at resumption, remove LF(\n) at head. */
194 if ( m_firstReceive ) {
195 cstr = cstr.mid( 1 );
197 m_firstReceive = FALSE;
199 emitDatLineList( cstr );
203 /* convert data stream into 2ch dat.
204 and emit receiveData SIGNAL. */ /* private */
205 void Access::emitDatLineList( const QString& dataStream )
207 QStringList lineList;
208 QStringList datLineList;
209 if( dataStream == QString::null ) return;
211 bool endIsLF = FALSE;
212 if ( dataStream.at( dataStream.length() - 1 ) == '\n' ) endIsLF = TRUE;
214 /* split the stream */
215 m_lastLine += dataStream;
216 lineList = QStringList::split( "\n", m_lastLine );
217 m_lastLine = QString::null;
219 /* save the last line */
222 QStringList::iterator lastit = lineList.end();
224 if ( lastit != lineList.end() ) {
226 m_lastLine = ( *lastit );
227 lineList.remove( lastit );
233 /* convert lines into 2ch dat */
234 int count = lineList.count();
235 for ( int i = 0; i < count ; ++i ){
237 if ( lineList[ i ] != QString::null ) {
240 int nextNum = m_readNum +1;
246 line = Kita::ParseMachiBBSOneLine( lineList[ i ] , nextNum );
250 line = Kita::ParseJBBSOneLine( lineList[ i ] , nextNum );
254 line = Kita::ParseFlashCGIOneLine( lineList[ i ] );
258 line = lineList[ i ];
261 if( line == QString::null ) continue;
263 /* add abone lines */
264 const QString aboneStr = "abone<><><>abone<>";
265 while( nextNum > m_readNum +1 ){
266 datLineList += aboneStr;
267 m_threadData += aboneStr +"\n";
272 if( m_bbstype == Board_MachiBBS ) m_threadData += line + "\n";
273 else m_threadData += lineList[ i ] + "\n";
280 datLineList += Kita::ecuToUnicode( line );
284 datLineList += Kita::qcpToUnicode( line );
289 /* call DatInfo::slotReceiveData() */
290 emit receiveData( datLineList );
295 void Access::killJob()
297 if ( m_currentJob ) m_currentJob->kill();
300 void Access::stopJob()
302 if ( m_currentJob ) m_currentJob->kill( FALSE ); /* emit result signal */
305 int Access::serverTime()
307 if ( m_currentJob ) m_header = m_currentJob->queryMetaData( "HTTP-Headers" );
308 // parse HTTP headers
309 QStringList headerList = QStringList::split( "\n", m_header );
310 QRegExp regexp( "Date: (...), (..) (...) (....) (..:..:..) .*" );
311 QString dateStr = headerList.grep( regexp ) [ 0 ];
312 if ( regexp.search( dateStr ) == -1 ) {
313 // invalid date format
314 return QDateTime::currentDateTime().toTime_t();
316 // I hate this format ;p
317 QString usLocalDateStr = regexp.cap( 1 ) + " " + regexp.cap( 3 ) + " " +
318 regexp.cap( 2 ) + " " + regexp.cap( 5 ) + " " +
321 // 1970/01/01 00:00:00 GMT
322 QDateTime zeroTime( QDate( 1970, 1, 1 ), QTime( 0, 0 ) );
323 return zeroTime.secsTo( QDateTime::fromString( usLocalDateStr ) );
327 int Access::responseCode()
329 if ( m_currentJob ) m_header = m_currentJob->queryMetaData( "HTTP-Headers" );
330 // parse HTTP headers
331 QStringList headerList = QStringList::split( "\n", m_header );
332 QRegExp regexp( "HTTP/1\\.[01] ([0-9]+) .*" );
333 QString dateStr = headerList.grep( regexp ) [ 0 ];
334 if ( regexp.search( dateStr ) == -1 ) {
336 if ( m_bbstype == Board_JBBS ) return 200; /* adhoc... */
339 return regexp.cap( 1 ).toInt();
344 const int Access::dataSize() const
350 const bool Access::invalidDataReceived() const
352 return m_invalidDataReceived;
358 QString OfflawAccess::get()
360 QString getURL = Kita::datToOfflaw( m_datURL.url() );
361 KURL kgetURL( getURL );
362 kgetURL.addQueryItem( "sid", Account::getSessionID() );
365 m_invalidDataReceived = FALSE;
367 KIO::SlaveConfig::self() ->setConfigData( "http",
368 KURL( getURL ).host(),
370 QString( "Monazilla/1.00 (Kita/%1)" ).arg( VERSION ) );
372 KIO::TransferJob* job = KIO::get( kgetURL, true, false );
375 connect( job, SIGNAL( data( KIO::Job*, const QByteArray& ) ),
376 SLOT( slotReceiveThreadData( KIO::Job*, const QByteArray& ) ) );
377 connect( job, SIGNAL( result( KIO::Job* ) ), SLOT( slotThreadResult( KIO::Job* ) ) );
379 // use 'HTTP-Headers' metadata.
380 job->addMetaData( "PropagateHttpHeader", "true" );
382 return QString::null; /* dummy */
385 void OfflawAccess::slotThreadResult( KIO::Job* job )
388 if ( job->error() ) {
389 job->showErrorDialog();
391 m_header = job->queryMetaData( "HTTP-Headers" );
394 if ( !m_invalidDataReceived && m_threadData.length() ) {
401 void OfflawAccess::slotReceiveThreadData( KIO::Job*, const QByteArray& data )
403 QString cstr( data );
405 if ( ( m_dataSize > 0 && responseCode() != 206 )
406 || ( m_dataSize == 0 && responseCode() != 200 ) ) {
407 m_invalidDataReceived = TRUE;
410 if ( m_invalidDataReceived ) return ;
412 // "+OK ....../1024K\tLocation:temp/\n"
413 if ( m_threadData.isEmpty() && cstr[0] == '+' ) {
415 int index = cstr.find( '\n' );
416 cstr = cstr.mid( index + 1 );
418 emitDatLineList( cstr );
421 #include "access.moc"