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 "kita_misc.h"
13 #include <QtCore/QRegExp>
14 #include <QtGui/QFont>
18 #include "boarddatabase.h"
19 #include "datmanager.h"
20 #include "kita-utf16.h"
25 static int m_prevConvMode;
26 static QString m_prevConvUrl;
27 static QString m_prevConvNewUrl;
28 static QString m_prevConvRefstr;
30 /* for ParseMachiBBSOneLine */
31 static QString m_machiSubject;
32 static QString m_machiLine;
34 /*------------------------------------------------------------*/
35 /*------------------------------------------------------------*/
37 /* conversion of URL */
39 KUrl Kita::getDatUrl(const KUrl& url , QString& refstr)
41 return convertUrl(URLMODE_DAT, url, refstr);
44 KUrl Kita::getDatUrl(const KUrl& url)
47 return convertUrl(URLMODE_DAT, url, refstr);
50 QString getThreadUrl(const KUrl& url, QString& refstr)
52 return convertUrl(URLMODE_THREAD, url, refstr);
55 QString Kita::getThreadUrl(const KUrl& url)
58 return convertUrl(URLMODE_THREAD, url, refstr);
61 QString Kita::getWriteUrl(const KUrl& m_datUrl)
63 BoardDatabase db(m_datUrl);
64 int m_bbstype = db.type();
67 /* set path of bbs.cgi */
71 QString cgipath = db.boardRoot()
72 + "/bbs/write.cgi/" + db.boardId() + '/';
74 cgipath += DatManager(m_datUrl).threadId() + '/';
81 case Board_MachiBBS: {
82 QString cgipath = db.boardRoot()
91 m_bbscgi = db.boardRoot() + "/test/bbs.cgi";
97 /* convert thread URL, and get reference.
98 If mode = URLMODE_DAT, output is URL of dat file.
99 If mode = URLMODE_THREAD, output is URL of read.cgi .
101 If url is NOT recorded, return QString().
106 url = http://pc5.2ch.net/linux/dat/1069738960.dat#20-30
108 return : http://pc5.2ch.net/linux/dat/1069738960.dat
114 url = http://pc5.2ch.net/linux/dat/1069738960.dat#20-30
116 return : http://pc5.2ch.net/test/read.cgi/linux/1069738960
122 url = http://pc5.2ch.net/test/read.cgi/linux/1069738960/-100
124 return : http://pc5.2ch.net/linux/dat/1069738960.dat
128 QString Kita::convertUrl(
131 int mode, /* if 0, output is dat URL. If 1, output is thread URL */
139 if (url.isEmpty()) return QString();
142 if (m_prevConvMode == mode && m_prevConvUrl == url.prettyUrl()) {
144 refstr = m_prevConvRefstr;
145 return m_prevConvNewUrl;
148 /* Is board recorded ? */
149 BoardDatabase db(url);
150 BoardData* bdata = db.getBoardData();
151 if (bdata == 0) return QString();
153 QString urlstr = url.prettyUrl();
155 /* get thread & reference */
159 if (urlstr.contains("/dat/")) {
161 /* url = (hostname)/(rootPath)/(bbsPath)/dat/(thread_ID).(ext)#(refBase) */
162 thread = url.fileName().remove(bdata->ext());
164 } else if (urlstr.contains(bdata->delimiter())) {
167 switch (bdata->type()) {
170 /* ex.) If url = http://kanto.machi.to/bbs/read.pl?BBS=kana&KEY=1096716679 ,
171 then, thread = 1096716679 */
173 thread = url.queryItem("KEY");
177 /* url = (hostname)/(rootPath)/(delimiter)/(bbsPath)/(thread_ID)/(refBase) */
179 tmpstr = urlstr.section(bdata->delimiter() + bdata->bbsPath(), 1, 1);
180 thread = tmpstr.section('/', 1, 1);
181 refBase = tmpstr.section('/', 2, 2);
186 if (thread.isEmpty()) return QString();
188 if (!refBase.isEmpty()) {
190 if (refBase.at(0) == '-') refstr = '1' + refBase;
191 else refstr = refBase;
196 if (mode == URLMODE_DAT) newUrl = bdata->basePath() + "dat/" + thread + bdata->ext();
198 newUrl = bdata->cgiBasePath();
200 switch (bdata->type()) {
203 newUrl += "&KEY=" + thread;
213 m_prevConvMode = mode;
214 m_prevConvUrl = url.prettyUrl();
215 m_prevConvNewUrl = newUrl;
216 m_prevConvRefstr = refstr;
224 * http://pc5.2ch.net/linux/dat/1089905503.dat
225 * -> http://pc5.2ch.net/test/offlaw.cgi?bbs=linux&key=1089905503
227 QString Kita::datToOfflaw(const KUrl& datUrl)
229 /* TODO: not tested. */
231 QString root = url.host();
233 QStringList list = url.fileName().split('.');
234 if (list.size() != 2) {
237 QString datName = list[ 0 ];
240 if (url.fileName() != "dat") {
245 QString board = url.fileName();
247 return QString("http://%1/test/offlaw.cgi?raw=0.0&bbs=%2&key=%3").arg(root).arg(board).arg(datName);
251 /*------------------------------------------------------------*/
252 /*------------------------------------------------------------*/
256 uint Kita::datToSince(const KUrl& datUrl)
258 return KUrl(datUrl).fileName().section('.', 0, 0).toInt();
263 /* convert strings to positive number. */
264 /* if cdat is not number, return -1. */
266 /* For example, if cdat = "1234", then
267 ret = 1234. If cdat = "abcd", then
269 int Kita::stringToPositiveNum(const QChar *cdat, const unsigned int length)
273 for (unsigned int i = 0 ; i < length ; i++) {
275 unsigned short c = cdat[ i ].unicode();
277 if ((c < UTF16_0 || c > UTF16_9) && (c < '0' || c > '9')) return -1;
280 if (c >= UTF16_0) ret += c - UTF16_0;
289 /*------------------------------------------------------------*/
290 /*------------------------------------------------------------*/
292 /* internal parsing functions */
294 QStringList Kita::parseSearchQuery(const QString& input)
296 QStringList tmp = input.split(' ');
297 QStringList ret_list;
298 QRegExp truncSpace("\\s*$");
299 QStringList::iterator it = tmp.begin();
300 for (; it != tmp.end(); ++it)
301 ret_list += (*it).remove(truncSpace);
309 /* init parser. Don't forget to call this before parsing. */
310 void Kita::InitParseMachiBBS()
312 m_machiSubject.clear();
316 QString Kita::ParseMachiBBSOneLine(const QString& inputLine, int& nextNum)
319 m_machiLine += inputLine;
331 QRegExp title_regexp("<title>(.*)</title>");
333 // pattern 1 (tokyo,kanagawa,...)
334 QRegExp regexp ("<dt>(\\d*) .*<font color=\"#......\"><b> (.*) </b></font> .* (..../../..).* (..:..:..) ID:([^<]*)<br><dd>(.*)");
335 QRegExp regexp2("<dt>(\\d*) .*<a href=\"mailto:(.*)\"><b> (.*) </B></a> .* (..../../..).* (..:..:..) ID:([^<]*)<br><dd>(.*)");
337 // pattern 2 (hokkaido,...)
338 QRegExp regexp3("<dt>(\\d*) .*<font color=\"#......\"><b> (.*) </b></font> .* (..../../..).* (..:..:..) ID:([^<]*) <font size=.>\\[ ([^ ]*) \\]</font><br><dd>(.*)");
339 QRegExp regexp4("<dt>(\\d*) .*<a href=\"mailto:(.*)\"><b> (.*) </B></a> .* (..../../..).* (..:..:..) ID:([^<]*) <font size=.>\\[ ([^ ]*) \\]</font><br><dd>(.*)");
342 QRegExp regexp5("<dt>(\\d*) .*<br><dd>.*");
345 if (regexp.indexIn(m_machiLine) != -1) {
347 num = regexp.cap(1).toInt();
348 name = regexp.cap(2);
349 date = regexp.cap(3);
350 time = regexp.cap(4);
352 message = regexp.cap(6);
354 } else if (regexp2.indexIn(m_machiLine) != -1) {
356 num = regexp2.cap(1).toInt();
357 mail = regexp2.cap(2);
358 name = regexp2.cap(3);
359 date = regexp2.cap(4);
360 time = regexp2.cap(5);
362 message = regexp2.cap(7);
364 } else if (regexp3.indexIn(m_machiLine) != -1) {
366 num = regexp3.cap(1).toInt();
367 name = regexp3.cap(2);
368 date = regexp3.cap(3);
369 time = regexp3.cap(4);
371 host = regexp3.cap(6);
372 message = regexp3.cap(7);
374 } else if (regexp4.indexIn(m_machiLine) != -1) {
376 num = regexp4.cap(1).toInt();
377 mail = regexp4.cap(2);
378 name = regexp4.cap(3);
379 date = regexp4.cap(4);
380 time = regexp4.cap(5);
382 host = regexp4.cap(7);
383 message = regexp4.cap(8);
385 } else if (regexp5.indexIn(m_machiLine) != -1) { /* abone */
387 num = regexp5.cap(1).toInt();
389 if (num == nextNum) return "abone<><><>abone<>";
390 else return QString();
392 } else if (title_regexp.indexIn(m_machiLine) != -1) { /* get title */
394 m_machiSubject = title_regexp.cap(1);
398 else return QString();
400 if (num >= nextNum) {
402 if (num != 1) m_machiSubject.clear();
403 ret += name + "<><>" + date + ' ' + time + " ID:" + id;
404 if (!host.isEmpty()) ret += " HOST:" + host;
405 ret += "<>" + message + "<>" + m_machiSubject;
414 /*---------------------------------*/
418 QString Kita::ParseJBBSOneLine(const QString& line, int& nextNum)
421 QStringList list = line.split("<>");
422 if (list.size() != 7) return QString();
424 int num = list[ 0 ].toInt();
425 QString name = list[ 1 ];
426 QString mail = list[ 2 ];
427 QString date = list[ 3 ];
428 QString body = list[ 4 ];
429 QString subject = list[ 5 ];
430 QString id = list[ 6 ];
432 if (num < nextNum) return QString();
435 QRegExp rex("<[^<]*>");
439 rex = QRegExp("\\(.*\\)");
442 ret += name + "<>" + mail + "<>" + date + " ID:" + id + "<>" + body + "<>" + subject;
449 /*---------------------------------*/
451 /* for Flash CGI/Mini Thread */
453 QString Kita::ParseFlashCGIOneLine(const QString& line)
456 QStringList list = line.split("<>");
457 if (list.size() != 13) return QString();
459 QString name = list[ 0 ];
460 QString mail = list[ 1 ];
461 QString date = list[ 2 ];
462 QString body = list[ 3 ];
463 QString subject = list[ 4 ];
464 QString id = list[ 6 ];
465 QString host = list[ 7 ];
468 QRegExp rex("<[^<]*>");
471 ret += name + "<>" + mail + "<>" + date + " ID:" + id;
472 if (!host.isEmpty()) ret += " HOST:" + host;
473 ret += "<>" + body + "<>" + subject;
479 /*-------------------------------------------------*/
480 /*-------------------------------------------------*/
482 /* parsing functions */
484 /*-------------------------------------------------*/
485 /*-------------------------------------------------*/
487 QString Kita::getCategory(const QString& line)
489 QRegExp regexp("<BR><BR><B>(.*)</B><BR>");
490 if (regexp.indexIn(line) != -1) {
491 return regexp.cap(1);
497 bool Kita::isBoardUrl(const QString& url)
499 QRegExp url_2ch("http://.*\\.2ch\\.net/.*");
500 QRegExp url_bbspink("http://.*\\.bbspink\\.com/.*");
501 QRegExp url_www_2ch("http://www\\.2ch\\.net/.*");
502 QRegExp url_machibbs("http://.*\\.machi\\.to/.*");
504 if (url.isEmpty()) return false;
506 if (url_2ch.indexIn(url) == -1 && url_bbspink.indexIn(url) == -1
507 && url_machibbs.indexIn(url) == -1) return false;
508 if (url_www_2ch.indexIn(url) != -1) return false;
513 QString Kita::fontToString(const QFont& font)
515 return font.family() + ' ' + QString::number(font.pointSize());