OSDN Git Service

Use `record' instead of `enroll'
[kita/kita.git] / src / libkita / kita_misc.cpp
1 /***************************************************************************
2 *   Copyright (C) 2004 by Kita Developers                                 *
3 *   ikemo@users.sourceforge.jp                                            *
4 *                                                                         *
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 ***************************************************************************/
10
11 #include "kita_misc.h"
12
13 #include <QtCore/QRegExp>
14 #include <QtGui/QFont>
15
16 #include <kurl.h>
17
18 #include "boarddatabase.h"
19 #include "datmanager.h"
20 #include "kita-utf16.h"
21
22 using namespace Kita;
23
24 /* fro convertURL */
25 static int m_prevConvMode;
26 static QString m_prevConvUrl;
27 static QString m_prevConvNewUrl;
28 static QString m_prevConvRefstr;
29
30 /* for ParseMachiBBSOneLine */
31 static QString m_machiSubject;
32 static QString m_machiLine;
33
34 /*------------------------------------------------------------*/
35 /*------------------------------------------------------------*/
36
37 /* conversion of URL */
38
39 KUrl Kita::getDatUrl(const KUrl& url , QString& refstr)
40 {
41     return convertUrl(URLMODE_DAT, url, refstr);
42 }
43
44 KUrl Kita::getDatUrl(const KUrl& url)
45 {
46     QString refstr;
47     return convertUrl(URLMODE_DAT, url, refstr);
48 }
49
50 QString getThreadUrl(const KUrl& url, QString& refstr)
51 {
52     return convertUrl(URLMODE_THREAD, url, refstr);
53 }
54
55 QString Kita::getThreadUrl(const KUrl& url)
56 {
57     QString refstr;
58     return convertUrl(URLMODE_THREAD, url, refstr);
59 }
60
61 QString Kita::getWriteUrl(const KUrl& m_datUrl)
62 {
63     BoardDatabase db(m_datUrl);
64     int m_bbstype = db.type();
65     QString m_bbscgi;
66
67     /* set path of bbs.cgi */
68     switch (m_bbstype) {
69
70     case Board_JBBS: {
71             QString cgipath = db.boardRoot()
72                 + "/bbs/write.cgi/" + db.boardId() + '/';
73
74             cgipath += DatManager(m_datUrl).threadId() + '/';
75
76             m_bbscgi = cgipath;
77         }
78
79         break;
80
81     case Board_MachiBBS: {
82             QString cgipath = db.boardRoot()
83                               + "/bbs/write.cgi";
84             m_bbscgi = cgipath;
85         }
86
87         break;
88
89     default:
90
91         m_bbscgi = db.boardRoot() + "/test/bbs.cgi";
92     }
93
94     return m_bbscgi;
95 }
96
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 .
100  
101    If url is NOT recorded, return QString(). 
102    
103 (ex.1)
104  
105 mode = 0
106 url  = http://pc5.2ch.net/linux/dat/1069738960.dat#20-30
107 ->
108 return : http://pc5.2ch.net/linux/dat/1069738960.dat
109 retstr : 20-30
110  
111 (ex.2)
112  
113 mode = 1
114 url  = http://pc5.2ch.net/linux/dat/1069738960.dat#20-30
115 ->
116 return : http://pc5.2ch.net/test/read.cgi/linux/1069738960
117 retstr : 20-30
118  
119 (ex.3)
120  
121 mode = 0
122 url  = http://pc5.2ch.net/test/read.cgi/linux/1069738960/-100
123 ->
124 return : http://pc5.2ch.net/linux/dat/1069738960.dat
125 refstr : 1-100
126                                                             */
127
128 QString Kita::convertUrl(
129
130     /* input */
131     int mode,   /* if 0, output is dat URL. If 1, output is thread URL */
132     const KUrl& url ,
133
134     /* output */
135     QString& refstr)
136 {
137     refstr.clear();
138
139     if (url.isEmpty()) return QString();
140
141     /* cache */
142     if (m_prevConvMode == mode && m_prevConvUrl == url.prettyUrl()) {
143
144         refstr = m_prevConvRefstr;
145         return m_prevConvNewUrl;
146     }
147
148     /* Is board recorded ? */
149     BoardDatabase db(url);
150     BoardData* bdata = db.getBoardData();
151     if (bdata == 0) return QString();
152
153     QString urlstr = url.prettyUrl();
154
155     /* get thread & reference */
156     QString thread;
157     QString refBase;
158
159     if (urlstr.contains("/dat/")) {
160
161         /* url = (hostname)/(rootPath)/(bbsPath)/dat/(thread_ID).(ext)#(refBase)  */
162         thread = url.fileName().remove(bdata->ext());
163         refBase = url.ref();
164     } else if (urlstr.contains(bdata->delimiter())) {
165
166         QString tmpstr;
167         switch (bdata->type()) {
168
169             /* machi BBS */
170             /* ex.) If url = http://kanto.machi.to/bbs/read.pl?BBS=kana&KEY=1096716679 ,
171                then, thread = 1096716679                                */
172         case Board_MachiBBS:
173             thread = url.queryItem("KEY");
174             refBase.clear();
175             break;
176
177             /* url = (hostname)/(rootPath)/(delimiter)/(bbsPath)/(thread_ID)/(refBase) */
178         default:
179             tmpstr = urlstr.section(bdata->delimiter() + bdata->bbsPath(), 1, 1);
180             thread = tmpstr.section('/', 1, 1);
181             refBase = tmpstr.section('/', 2, 2);
182             break;
183         }
184     }
185
186     if (thread.isEmpty()) return QString();
187
188     if (!refBase.isEmpty()) {
189
190         if (refBase.at(0) == '-') refstr = '1' + refBase;
191         else refstr = refBase;
192     }
193
194     /* create new URL */
195     QString newUrl;
196     if (mode == URLMODE_DAT) newUrl = bdata->basePath() + "dat/" + thread + bdata->ext();
197     else {
198         newUrl = bdata->cgiBasePath();
199
200         switch (bdata->type()) {
201
202         case Board_MachiBBS:
203             newUrl += "&KEY=" + thread;
204             break;
205
206         default:
207             newUrl += thread;
208             break;
209         }
210     }
211
212     /* cache */
213     m_prevConvMode = mode;
214     m_prevConvUrl = url.prettyUrl();
215     m_prevConvNewUrl = newUrl;
216     m_prevConvRefstr = refstr;
217
218     return newUrl;
219 }
220
221
222
223 /**
224  * http://pc5.2ch.net/linux/dat/1089905503.dat
225  * -> http://pc5.2ch.net/test/offlaw.cgi?bbs=linux&key=1089905503
226  */
227 QString Kita::datToOfflaw(const KUrl& datUrl)
228 {
229     /* TODO: not tested. */
230     KUrl url(datUrl);
231     QString root = url.host();
232
233     QStringList list = url.fileName().split('.');
234     if (list.size() != 2) {
235         return QString();
236     }
237     QString datName = list[ 0 ];
238
239     url.cd("..");
240     if (url.fileName() != "dat") {
241         return QString();
242     }
243
244     url.cd("..");
245     QString board = url.fileName();
246
247     return QString("http://%1/test/offlaw.cgi?raw=0.0&bbs=%2&key=%3").arg(root).arg(board).arg(datName);
248 }
249
250
251 /*------------------------------------------------------------*/
252 /*------------------------------------------------------------*/
253
254 /* utilities */
255
256 uint Kita::datToSince(const KUrl& datUrl)
257 {
258     return KUrl(datUrl).fileName().section('.', 0, 0).toInt();
259 }
260
261
262
263 /* convert strings to positive number.  */
264 /* if cdat is not number, return -1.    */
265
266 /*  For example, if cdat = "1234", then
267     ret = 1234. If cdat = "abcd", then
268     ret = -1.                           */
269 int Kita::stringToPositiveNum(const QChar *cdat, const unsigned int length)
270 {
271     int ret = 0;
272
273     for (unsigned int i = 0 ; i < length ; i++) {
274
275         unsigned short c = cdat[ i ].unicode();
276
277         if ((c < UTF16_0 || c > UTF16_9) && (c < '0' || c > '9')) return -1;
278
279         ret *= 10;
280         if (c >= UTF16_0) ret += c - UTF16_0;
281         else ret += c - '0';
282     }
283
284     return ret;
285 }
286
287
288
289 /*------------------------------------------------------------*/
290 /*------------------------------------------------------------*/
291
292 /* internal parsing functions  */
293
294 QStringList Kita::parseSearchQuery(const QString& input)
295 {
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);
302     return ret_list;
303 }
304
305
306 /* for Machi BBS */
307
308
309 /* init parser. Don't forget to call this before parsing. */
310 void Kita::InitParseMachiBBS()
311 {
312     m_machiSubject.clear();
313     m_machiLine.clear();
314 }
315
316 QString Kita::ParseMachiBBSOneLine(const QString& inputLine, int& nextNum)
317 {
318     QString ret;
319     m_machiLine += inputLine;
320
321     int num = 0;
322     QString name;
323     QString mail;
324     QString date;
325     QString time;
326     QString id;
327     QString host;
328     QString message;
329
330     // Subject
331     QRegExp title_regexp("<title>(.*)</title>");
332
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>(.*)");
336
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>(.*)");
340
341     /* abone */
342     QRegExp regexp5("<dt>(\\d*) .*<br><dd>.*");
343
344
345     if (regexp.indexIn(m_machiLine) != -1) {
346
347         num = regexp.cap(1).toInt();
348         name = regexp.cap(2);
349         date = regexp.cap(3);
350         time = regexp.cap(4);
351         id = regexp.cap(5);
352         message = regexp.cap(6);
353
354     } else if (regexp2.indexIn(m_machiLine) != -1) {
355
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);
361         id = regexp2.cap(6);
362         message = regexp2.cap(7);
363
364     } else if (regexp3.indexIn(m_machiLine) != -1) {
365
366         num = regexp3.cap(1).toInt();
367         name = regexp3.cap(2);
368         date = regexp3.cap(3);
369         time = regexp3.cap(4);
370         id = regexp3.cap(5);
371         host = regexp3.cap(6);
372         message = regexp3.cap(7);
373
374     } else if (regexp4.indexIn(m_machiLine) != -1) {
375
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);
381         id = regexp4.cap(6);
382         host = regexp4.cap(7);
383         message = regexp4.cap(8);
384
385     } else if (regexp5.indexIn(m_machiLine) != -1) { /* abone */
386
387         num = regexp5.cap(1).toInt();
388         m_machiLine.clear();
389         if (num == nextNum) return "abone<><><>abone<>";
390         else return QString();
391
392     } else if (title_regexp.indexIn(m_machiLine) != -1) { /* get title */
393
394         m_machiSubject = title_regexp.cap(1);
395         m_machiLine.clear();
396         return QString();
397     }
398     else return QString();
399
400     if (num >= nextNum) {
401
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;
406         nextNum = num;
407     }
408
409     m_machiLine.clear();
410     return ret;
411 }
412
413
414 /*---------------------------------*/
415
416 /* for JBBS */
417
418 QString Kita::ParseJBBSOneLine(const QString& line, int& nextNum)
419 {
420     QString ret;
421     QStringList list = line.split("<>");
422     if (list.size() != 7) return QString();
423
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 ];
431
432     if (num < nextNum) return QString();
433
434     /* remove tag */
435     QRegExp rex("<[^<]*>");
436     name.remove(rex);
437
438     /* remove week */
439     rex = QRegExp("\\(.*\\)");
440     date.remove(rex);
441
442     ret += name + "<>" + mail + "<>" + date + " ID:" + id + "<>" + body + "<>" + subject;
443     nextNum = num;
444
445     return ret;
446 }
447
448
449 /*---------------------------------*/
450
451 /* for Flash CGI/Mini Thread  */
452
453 QString Kita::ParseFlashCGIOneLine(const QString& line)
454 {
455     QString ret;
456     QStringList list = line.split("<>");
457     if (list.size() != 13) return QString();
458
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 ];
466
467     /* remove tag */
468     QRegExp rex("<[^<]*>");
469     name.remove(rex);
470
471     ret += name + "<>" + mail + "<>" + date + " ID:" + id;
472     if (!host.isEmpty()) ret += " HOST:" + host;
473     ret += "<>" + body + "<>" + subject;
474
475     return ret;
476 }
477
478
479 /*-------------------------------------------------*/
480 /*-------------------------------------------------*/
481
482 /* parsing functions */
483
484 /*-------------------------------------------------*/
485 /*-------------------------------------------------*/
486
487 QString Kita::getCategory(const QString& line)
488 {
489     QRegExp regexp("<BR><BR><B>(.*)</B><BR>");
490     if (regexp.indexIn(line) != -1) {
491         return regexp.cap(1);
492     } else {
493         return QString();
494     }
495 }
496
497 bool Kita::isBoardUrl(const QString& url)
498 {
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/.*");
503
504     if (url.isEmpty()) return false;
505
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;
509
510     return true;
511 }
512
513 QString Kita::fontToString(const QFont& font)
514 {
515     return font.family() + ' ' + QString::number(font.pointSize());
516 }