OSDN Git Service

VP27マージ
[peercast-im/PeerCastIM.git] / PeerCast.root / PeerCast / core / common / html.cpp
1 // ------------------------------------------------
2 // File : html.cpp
3 // Date: 4-apr-2002
4 // Author: giles
5 // Desc: 
6 //              HTML protocol handling
7 //
8 // (c) 2002 peercast.org
9 // ------------------------------------------------
10 // This program is free software; you can redistribute it and/or modify
11 // it under the terms of the GNU General Public License as published by
12 // the Free Software Foundation; either version 2 of the License, or
13 // (at your option) any later version.
14
15 // This program is distributed in the hope that it will be useful,
16 // but WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18 // GNU General Public License for more details.
19 // ------------------------------------------------
20
21
22 #include <stdarg.h>
23 #include <stdlib.h>
24 #include "html.h"
25 #include "http.h"
26 #include "stream.h"
27 #include "gnutella.h"
28 #include "servmgr.h"
29 #include "channel.h"
30 #include "stats.h"
31 #include "version2.h"
32 #ifdef _DEBUG
33 #include "chkMemoryLeak.h"
34 #define DEBUG_NEW new(__FILE__, __LINE__)
35 #define new DEBUG_NEW
36 #endif
37
38
39 // --------------------------------------
40 HTML::HTML(const char *t, Stream &o)
41 {
42         o.writeCRLF = false;
43         out = new WriteBufferStream(8192, &o);
44         out->writeCRLF = false;
45
46         title.set(t);
47         tagLevel = 0;
48         refresh = 0;
49 }
50
51 HTML::~HTML()
52 {
53         try {
54                 out->flush();
55         } catch (StreamException &) {}
56         delete out;
57 }
58
59 // --------------------------------------
60 void HTML::writeOK(const char *content)
61 {
62         out->writeLine(HTTP_SC_OK);
63         out->writeLineF("%s %s",HTTP_HS_SERVER,PCX_AGENT);
64         //out->writeLine("%s %s",HTTP_HS_CACHE,"no-cache");
65         out->writeLineF("%s %s",HTTP_HS_CONNECTION,"close");
66     out->writeLineF("%s %s",HTTP_HS_CONTENT,content);
67         out->writeLine("");
68 }
69 // --------------------------------------
70 void HTML::writeVariable(Stream &s,const String &varName, int loop)
71 {
72         bool r=false;
73         if (varName.startsWith("servMgr."))
74                 r=servMgr->writeVariable(s,varName+8);
75         else if (varName.startsWith("chanMgr."))
76                 r=chanMgr->writeVariable(s,varName+8,loop);
77         else if (varName.startsWith("stats."))
78                 r=stats.writeVariable(s,varName+6);
79         else if (varName.startsWith("sys."))
80         {
81                 if (varName == "sys.log.dumpHTML")
82                 {
83                         sys->logBuf->dumpHTML(s);
84                         r=true;
85                 }
86         }
87         else if (varName.startsWith("loop."))
88         {
89                 if (varName.startsWith("loop.channel."))
90                 {
91                         Channel *ch = chanMgr->findChannelByIndex(loop);
92                         if (ch)
93                                 r = ch->writeVariable(s,varName+13,loop);
94                 }else if (varName.startsWith("loop.servent."))
95                 {
96                         Servent *sv = servMgr->findServentByIndex(loop);
97                         if (sv)
98                                 r = sv->writeVariable(s,varName+13);
99                 }else if (varName.startsWith("loop.filter."))
100                 {
101                         ServFilter *sf = &servMgr->filters[loop];
102                         r = sf->writeVariable(s,varName+12);
103
104                 }else if (varName.startsWith("loop.bcid."))
105                 {
106                         BCID *bcid = servMgr->findValidBCID(loop);
107                         if (bcid)
108                                 r = bcid->writeVariable(s,varName+10);
109                 
110                 }else if (varName == "loop.indexEven")
111                 {
112                         s.writeStringF("%d",(loop&1)==0);
113                         r = true;
114                 }else if (varName == "loop.index")
115                 {
116                         s.writeStringF("%d",loop);
117                         r = true;
118                 }else if (varName.startsWith("loop.hit."))
119                 {
120                         char *idstr = getCGIarg(tmplArgs,"id=");
121                         if (idstr)
122                         {
123                                 GnuID id;
124                                 id.fromStr(idstr);
125                                 ChanHitList *chl = chanMgr->findHitListByID(id);
126                                 if (chl)
127                                 {
128                                         int cnt=0;
129                                         ChanHit *ch = chl->hit;
130                                         while (ch)
131                                         {
132                                                 if (ch->host.ip && !ch->dead)
133                                                 {
134                                                         if (cnt == loop)
135                                                         {
136                                                                 r = ch->writeVariable(s,varName+9);
137                                                                 break;
138                                                         }
139                                                         cnt++;
140                                                 }
141                                                 ch=ch->next;
142                                         }
143
144                                 }
145                         }
146                 }
147
148         }
149         else if (varName.startsWith("page."))
150         {
151                 if (varName.startsWith("page.channel."))
152                 {
153                         char *idstr = getCGIarg(tmplArgs,"id=");
154                         if (idstr)
155                         {
156                                 GnuID id;
157                                 id.fromStr(idstr);
158                                 Channel *ch = chanMgr->findChannelByID(id);
159                                 if (ch)
160                                         r = ch->writeVariable(s,varName+13,loop);
161                         }
162                 }else
163                 {
164
165                         String v = varName+5;
166                         v.append('=');
167                         char *a = getCGIarg(tmplArgs,v);
168                         if (a)
169                         {
170                                 s.writeString(a);               
171                                 r=true;
172                         }
173                 }
174         }
175
176
177         if (!r)
178                 s.writeString(varName);
179 }
180 // --------------------------------------
181 int HTML::getIntVariable(const String &varName,int loop)
182 {
183         String val;
184         LOG_DEBUG("AAA %d %d %d %d", val[0], val[1], val[2], val[3]);
185         MemoryStream mem(val.cstr(),String::MAX_LEN);
186
187         writeVariable(mem,varName,loop);
188
189         LOG_DEBUG("AAA %d %d %d %d", val[0], val[1], val[2], val[3]);
190         return atoi(val.cstr());
191 }
192 // --------------------------------------
193 bool HTML::getBoolVariable(const String &varName,int loop)
194 {
195         String val;
196         MemoryStream mem(val.cstr(),String::MAX_LEN);
197
198         writeVariable(mem,varName,loop);
199
200         String tmp;
201         tmp = varName;
202         LOG_DEBUG("*** %s : %c", tmp.cstr(), val[0]);
203
204         // integer
205         if ((val[0] >= '0') && (val[0] <= '9'))
206                 return atoi(val.cstr()) != 0;   
207
208         // string
209         if (val[0]!=0)
210                 return true;    
211
212         return false;
213 }
214
215 // --------------------------------------
216 void    HTML::readIf(Stream &in,Stream *outp,int loop)
217 {
218         String var;
219         bool varCond=true;
220
221         while (!in.eof())
222         {
223                 char c = in.readChar();
224
225                 if (c == '}')
226                 {
227                         if (getBoolVariable(var,loop)==varCond)
228                         {
229                                 LOG_DEBUG("==varCond, loop = %d", loop);
230                                 if (readTemplate(in,outp,loop))
231                                         readTemplate(in,NULL,loop);
232                         }else{
233                                 LOG_DEBUG("!=varCond, loop = %d", loop);
234                                 if (readTemplate(in,NULL,loop))
235                                         readTemplate(in,outp,loop);
236                         }
237                         return;
238                 }else if (c == '!')
239                 {
240                         varCond = !varCond;
241                 }else
242                 {
243                         var.append(c);
244                 }
245         }
246
247 }
248
249 // --------------------------------------
250 void    HTML::readLoop(Stream &in,Stream *outp,int loop)
251 {
252         String var;
253         while (!in.eof())
254         {
255                 char c = in.readChar();
256
257                 if (c == '}')
258                 {
259                         int cnt = getIntVariable(var,loop);
260
261                         LOG_DEBUG("loop_cnt : %s = %d", var.cstr(), cnt);
262
263                         if (cnt)
264                         {
265                                 int spos = in.getPosition();
266                                 for(int i=0; i<cnt; i++)
267                                 {
268                                         in.seekTo(spos);
269                                         readTemplate(in,outp,i);
270                                 }
271                         }else
272                         {
273                                 readTemplate(in,NULL,0);
274                         }
275                         return;
276
277                 }else
278                 {
279                         var.append(c);
280                 }
281         }
282
283 }
284
285 // --------------------------------------
286 int HTML::readCmd(Stream &in,Stream *outp,int loop)
287 {
288         String cmd;
289
290         int tmpl = TMPL_UNKNOWN;
291
292         while (!in.eof())
293         {
294                 char c = in.readChar();
295
296                 if (String::isWhitespace(c) || (c=='}'))
297                 {
298                         if (cmd == "loop")
299                         {
300                                 readLoop(in,outp,loop);
301                                 tmpl = TMPL_LOOP;
302                         }else if (cmd == "if")
303                         {
304                                 readIf(in,outp,loop);
305                                 tmpl = TMPL_IF;
306                         }else if (cmd == "end")
307                         {
308                                 tmpl = TMPL_END;
309                         }
310                         else if (cmd == "else")
311                         {
312                                 tmpl = TMPL_ELSE;
313                         }
314                         break;
315                 }else
316                 {
317                         cmd.append(c);
318                 }
319         }
320         return tmpl;
321 }
322
323 // --------------------------------------
324 void    HTML::readVariable(Stream &in,Stream *outp,int loop)
325 {
326         String var;
327         while (!in.eof())
328         {
329                 char c = in.readChar();
330                 if (c == '}')
331                 {
332                         if (outp)
333                                 writeVariable(*outp,var,loop);
334                         return;
335                 }else
336                 {
337                         var.append(c);
338                 }
339         }
340
341 }
342 // --------------------------------------
343 bool HTML::readTemplate(Stream &in,Stream *outp,int loop)
344 {
345         while (!in.eof())
346         {
347                 char c = in.readChar();
348
349                 if (c == '{')
350                 {
351                         c = in.readChar();
352                         if (c == '$')
353                         {
354                                 readVariable(in,outp,loop);
355                         }
356                         else if (c == '@')
357                         {
358                                 int t = readCmd(in,outp,loop);
359                                 if (t == TMPL_END)
360                                         return false;
361                                 else if (t == TMPL_ELSE)
362                                         return true;
363                         }
364                         else if (c == '{')
365                         {
366                                 if (outp)
367                                         outp->writeChar(c);
368                         }
369                         else
370                                 throw StreamException("Unknown template escape");
371                 }else
372                 {
373                         if (outp)
374                                 outp->writeChar(c);
375                 }
376         }
377         return false;
378 }
379
380 // --------------------------------------
381 void HTML::writeTemplate(const char *fileName, const char *args)
382 {
383         FileStream file;
384         MemoryStream mm;
385         try
386         {
387                 file.openReadOnly(fileName);
388                 mm.readFromFile(file);
389
390                 tmplArgs = args;
391                 readTemplate(mm,out,0);
392
393         }catch(StreamException &e)
394         {
395                 out->writeString(e.msg);
396                 out->writeString(" : ");
397                 out->writeString(fileName);
398         }
399
400         mm.free2();
401         file.close();
402 }
403 // --------------------------------------
404 void HTML::writeRawFile(const char *fileName)
405 {
406         FileStream file;
407         try
408         {
409                 file.openReadOnly(fileName);
410
411                 file.writeTo(*out,file.length());
412
413         }catch(StreamException &)
414         {
415         }
416
417         file.close();
418 }
419
420 // --------------------------------------
421 void HTML::locateTo(const char *url)
422 {
423         out->writeLine(HTTP_SC_FOUND);
424         out->writeLineF("Location: %s",url);
425         out->writeLine("");
426 }
427 // --------------------------------------
428 void HTML::startHTML()
429 {
430         startNode("html");
431 }
432 // --------------------------------------
433 void HTML::startBody()
434 {
435         startNode("body");
436 }
437 // --------------------------------------
438 void HTML::addHead()
439 {
440         char buf[512];
441                 startNode("head");
442                         startTagEnd("title",title.cstr());
443                         startTagEnd("meta http-equiv=\"Content-Type\" content=\"text/html; charset=iso-8859-1\"");
444
445                         if (!refreshURL.isEmpty())
446                         {
447                                 sprintf(buf,"meta http-equiv=\"refresh\" content=\"%d;URL=%s\"",refresh,refreshURL.cstr());
448                                 startTagEnd(buf);
449                         }else if (refresh)
450                         {
451                                 sprintf(buf,"meta http-equiv=\"refresh\" content=\"%d\"",refresh);
452                                 startTagEnd(buf);
453                         }
454
455
456                 end();
457 }
458 // --------------------------------------
459 void HTML::addContent(const char *s)
460 {
461         out->writeString(s);
462 }
463 // --------------------------------------
464 void HTML::startNode(const char *tag, const char *data)
465 {
466         const char *p = tag;
467         char *o = &currTag[tagLevel][0];
468
469         int i;
470         for(i=0; i<MAX_TAGLEN-1; i++)
471         {
472                 char c = *p++;
473                 if ((c==0) || (c==' '))
474                         break;
475                 else
476                         *o++ = c;
477         }
478         *o = 0;
479
480         out->writeString("<");
481         out->writeString(tag);
482         out->writeString(">");
483         if (data)
484                 out->writeString(data);
485
486         tagLevel++;
487         if (tagLevel >= MAX_TAGLEVEL)
488                 throw StreamException("HTML too deep!");
489 }
490 // --------------------------------------
491 void HTML::end()
492 {
493         tagLevel--;
494         if (tagLevel < 0)
495                 throw StreamException("HTML premature end!");
496
497         out->writeString("</");
498         out->writeString(&currTag[tagLevel][0]);
499         out->writeString(">");
500 }
501 // --------------------------------------
502 void HTML::addLink(const char *url, const char *text, bool toblank)
503 {
504         char buf[1024];
505
506         sprintf(buf,"a href=\"%s\" %s",url,toblank?"target=\"_blank\"":"");
507         startNode(buf,text);
508         end();
509 }
510 // --------------------------------------
511 void HTML::startTag(const char *tag, const char *fmt,...)
512 {
513         if (fmt)
514         {
515
516                 va_list ap;
517                 va_start(ap, fmt);
518
519                 char tmp[512];
520                 vsprintf(tmp,fmt,ap);
521                 startNode(tag,tmp);
522
523                 va_end(ap);     
524         }else{
525                 startNode(tag,NULL);
526         }
527 }
528 // --------------------------------------
529 void HTML::startTagEnd(const char *tag, const char *fmt,...)
530 {
531         if (fmt)
532         {
533
534                 va_list ap;
535                 va_start(ap, fmt);
536
537                 char tmp[512];
538                 vsprintf(tmp,fmt,ap);
539                 startNode(tag,tmp);
540
541                 va_end(ap);     
542         }else{
543                 startNode(tag,NULL);
544         }
545         end();
546 }
547 // --------------------------------------
548 void HTML::startSingleTagEnd(const char *fmt,...)
549 {
550         va_list ap;
551         va_start(ap, fmt);
552
553         char tmp[512];
554         vsprintf(tmp,fmt,ap);
555         startNode(tmp);
556
557         va_end(ap);     
558         end();
559 }
560
561 // --------------------------------------
562 void HTML::startTableRow(int i)
563 {
564         if (i & 1)
565                 startTag("tr bgcolor=\"#dddddd\" align=\"left\"");
566         else
567                 startTag("tr bgcolor=\"#eeeeee\" align=\"left\"");
568 }