OSDN Git Service

IM0027-4
[peercast-im/PeerCastIM.git] / PeerCast.root / PeerCast / core / common / servhs.cpp
1 // ------------------------------------------------
2 // File : servhs.cpp
3 // Date: 4-apr-2002
4 // Author: giles
5 // Desc: 
6 //              Servent handshaking, TODO: should be in its own class
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 <stdlib.h>
23 #include "servent.h"
24 #include "servmgr.h"
25 #include "html.h"
26 #include "stats.h"
27 #include "peercast.h"
28 #include "pcp.h"
29 #include "version2.h"
30 #ifdef _DEBUG
31 #include "chkMemoryLeak.h"
32 #define DEBUG_NEW new(__FILE__, __LINE__)
33 #define new DEBUG_NEW
34 #endif
35
36 // -----------------------------------
37 static void termArgs(char *str)
38 {
39         if (str)
40         {
41                 size_t slen = strlen(str);
42                 for(size_t i=0; i<slen; i++)
43                         if (str[i]=='&') str[i] = 0;
44         }
45 }
46 // -----------------------------------
47 char *nextCGIarg(char *cp, char *cmd, char *arg)
48 {
49         if (!*cp)
50                 return NULL;
51
52         int cnt=0;
53
54         // fetch command
55         while (*cp)
56         {
57                 char c = *cp++;
58                 if (c == '=')
59                         break;
60                 else
61                         *cmd++ = c;
62
63                 cnt++;
64                 if (cnt >= (MAX_CGI_LEN-1))
65                         break;
66         }
67         *cmd = 0;
68
69         cnt=0;
70         // fetch arg
71         while (*cp)
72         {
73                 char c = *cp++;
74                 if (c == '&')
75                         break;
76                 else
77                         *arg++ = c;
78
79                 cnt++;
80                 if (cnt >= (MAX_CGI_LEN-1))
81                         break;
82         }
83         *arg = 0;
84
85         return cp;
86 }
87 // -----------------------------------
88 bool getCGIargBOOL(char *a)
89 {
90         return (strcmp(a,"1")==0);
91 }
92 // -----------------------------------
93 int getCGIargINT(char *a)
94 {
95         return atoi(a);
96 }
97
98 // -----------------------------------
99 void Servent::handshakeHTTP(HTTP &http, bool isHTTP)
100 {
101         char *in = http.cmdLine;
102
103         if (http.isRequest("GET /"))
104         {
105                 char *fn = in+4;
106
107                 char *pt = strstr(fn,HTTP_PROTO1);
108                 if (pt)
109                         pt[-1] = 0;
110
111                 if (strncmp(fn,"/admin?",7)==0)
112                 {
113                         if (!isAllowed(ALLOW_HTML))
114                                 throw HTTPException(HTTP_SC_UNAVAILABLE,503);
115
116
117                         LOG_DEBUG("Admin client");
118                         handshakeCMD(fn+7);
119
120                 }else if (strncmp(fn,"/http/",6)==0)
121                 {
122                         String dirName = fn+6;
123
124                         if (!isAllowed(ALLOW_HTML))
125                                 throw HTTPException(HTTP_SC_UNAVAILABLE,503);                   
126
127                         if (!handshakeAuth(http,fn,false))
128                                 throw HTTPException(HTTP_SC_UNAUTHORIZED,401);                  
129
130
131                         handshakeRemoteFile(dirName);
132
133
134                 }else if (strncmp(fn,"/html/",6)==0)
135                 {
136                         String dirName = fn+1;
137
138                         if (!isAllowed(ALLOW_HTML))
139                                 throw HTTPException(HTTP_SC_UNAVAILABLE,503);
140
141                         if (handshakeAuth(http,fn,true))
142                                 handshakeLocalFile(dirName);
143
144
145                 }else if (strncmp(fn,"/admin/?",8)==0)
146                 {
147                         if (!isAllowed(ALLOW_HTML))
148                                 throw HTTPException(HTTP_SC_UNAVAILABLE,503);
149
150                         LOG_DEBUG("Admin client");
151                         handshakeCMD(fn+8);
152
153                 }else if (strncmp(fn,"/admin.cgi",10)==0)
154                 {
155                         if (!isAllowed(ALLOW_BROADCAST))
156                                 throw HTTPException(HTTP_SC_UNAVAILABLE,503);
157
158                         char *pwdArg = getCGIarg(fn,"pass=");
159                         char *songArg = getCGIarg(fn,"song=");
160                         char *mountArg = getCGIarg(fn,"mount=");
161                         char *urlArg = getCGIarg(fn,"url=");
162
163                         if (pwdArg && songArg)
164                         {
165                                 size_t i;
166                                 size_t slen = strlen(fn);
167                                 for(i=0; i<slen; i++)
168                                         if (fn[i]=='&') fn[i] = 0;
169
170                                 Channel *c=chanMgr->channel;
171                                 while (c)
172                                 {
173                                         if ((c->status == Channel::S_BROADCASTING) &&
174                                            (c->info.contentType == ChanInfo::T_MP3) )
175                                         {
176                                                 // if we have a mount point then check for it, otherwise update all channels.
177                                                 bool match=true;
178
179                                                 if (mountArg)
180                                                         match = strcmp(c->mount,mountArg)==0;
181
182                                                 if (match)
183                                                 {
184                                                         ChanInfo newInfo = c->info;
185                                                         newInfo.track.title.set(songArg,String::T_ESC);
186                                                         newInfo.track.title.convertTo(String::T_UNICODE);
187
188                                                         if (urlArg)
189                                                                 if (urlArg[0])
190                                                                         newInfo.track.contact.set(urlArg,String::T_ESC);
191                                                         LOG_CHANNEL("Channel Shoutcast update: %s",songArg);
192                                                         c->updateInfo(newInfo);
193                                                 }
194                                         }
195                                         c=c->next;
196                                 }
197                         }
198
199                 }else if (strncmp(fn,"/pls/",5)==0)
200                 {
201
202                         if (!sock->host.isLocalhost())
203                                 if (!isAllowed(ALLOW_DIRECT) || !isFiltered(ServFilter::F_DIRECT))
204                                         throw HTTPException(HTTP_SC_UNAVAILABLE,503);
205
206                         
207                         ChanInfo info;
208                         if (servMgr->getChannel(fn+5,info,isPrivate()))
209                                 handshakePLS(info,false);
210                         else
211                                 throw HTTPException(HTTP_SC_NOTFOUND,404);
212
213                 }else if (strncmp(fn,"/stream/",8)==0)
214                 {
215
216                         if (!sock->host.isLocalhost())
217                                 if (!isAllowed(ALLOW_DIRECT) || !isFiltered(ServFilter::F_DIRECT))
218                                         throw HTTPException(HTTP_SC_UNAVAILABLE,503);
219
220                         triggerChannel(fn+8,ChanInfo::SP_HTTP,isPrivate());
221
222                         
223                 }else if (strncmp(fn,"/channel/",9)==0)
224                 {
225
226                         if (!sock->host.isLocalhost())
227                                 if (!isAllowed(ALLOW_NETWORK) || !isFiltered(ServFilter::F_NETWORK))
228                                         throw HTTPException(HTTP_SC_UNAVAILABLE,503);
229
230                         triggerChannel(fn+9,ChanInfo::SP_PCP,false);
231
232                 }else 
233                 {
234                         while (http.nextHeader());
235                         http.writeLine(HTTP_SC_FOUND);
236                         http.writeLineF("Location: /%s/index.html",servMgr->htmlPath);
237                         http.writeLine("");
238                 }
239         }
240         else if (http.isRequest("POST /"))
241         {
242                 char *fn = in+5;
243
244                 char *pt = strstr(fn,HTTP_PROTO1);
245                 if (pt)
246                         pt[-1] = 0;
247
248                 if (strncmp(fn,"/pls/",5)==0)
249                 {
250
251                         if (!sock->host.isLocalhost())
252                                 if (!isAllowed(ALLOW_DIRECT) || !isFiltered(ServFilter::F_DIRECT))
253                                         throw HTTPException(HTTP_SC_UNAVAILABLE,503);
254
255                         
256                         ChanInfo info;
257                         if (servMgr->getChannel(fn+5,info,isPrivate()))
258                                 handshakePLS(info,false);
259                         else
260                                 throw HTTPException(HTTP_SC_NOTFOUND,404);
261
262                 }else if (strncmp(fn,"/stream/",8)==0)
263                 {
264
265                         if (!sock->host.isLocalhost())
266                                 if (!isAllowed(ALLOW_DIRECT) || !isFiltered(ServFilter::F_DIRECT))
267                                         throw HTTPException(HTTP_SC_UNAVAILABLE,503);
268
269                         triggerChannel(fn+8,ChanInfo::SP_HTTP,isPrivate());
270
271                 }else if (strncmp(fn,"/admin",7)==0)
272                 {
273                         if (!isAllowed(ALLOW_HTML))
274                                 throw HTTPException(HTTP_SC_UNAVAILABLE,503);
275
276
277                         LOG_DEBUG("Admin client");
278                         while(http.nextHeader()){
279                                 LOG_DEBUG("%s",http.cmdLine);
280                         }
281                         char buf[8192];
282                         if (sock->readLine(buf, sizeof(buf)) != 0){
283                                 handshakeCMD(buf);
284                         }
285
286                 }else 
287                 {
288                         while (http.nextHeader());
289                         http.writeLine(HTTP_SC_FOUND);
290                         http.writeLineF("Location: /%s/index.html",servMgr->htmlPath);
291                         http.writeLine("");
292                 }
293         }else if (http.isRequest("GIV"))
294         {
295                 HTTP http(*sock);
296         
297                 while (http.nextHeader()) ;
298
299                 if (!isAllowed(ALLOW_NETWORK))
300                         throw HTTPException(HTTP_SC_UNAVAILABLE,503);
301
302                 GnuID id;
303                 id.clear();
304
305                 char *idstr = strstr(in,"/");
306                 if (idstr)
307                         id.fromStr(idstr+1);
308
309                 char ipstr[64];
310                 sock->host.toStr(ipstr);
311
312                 if (id.isSet())
313                 {
314                         // at the moment we don`t really care where the GIV came from, so just give to chan. no. if its waiting.
315                         Channel *ch = chanMgr->findChannelByID(id);
316
317                         if (!ch)
318                                 throw HTTPException(HTTP_SC_NOTFOUND,404);
319
320                         if (!ch->acceptGIV(sock))
321                                 throw HTTPException(HTTP_SC_UNAVAILABLE,503);
322
323                 
324                         LOG_DEBUG("Accepted GIV channel %s from: %s",idstr,ipstr);
325
326                         sock=NULL;                                      // release this servent but dont close socket.  
327                 }else 
328                 {
329
330                         if (!servMgr->acceptGIV(sock))
331                                 throw HTTPException(HTTP_SC_UNAVAILABLE,503);
332
333                         LOG_DEBUG("Accepted GIV PCP from: %s",ipstr);
334                         sock=NULL;                                      // release this servent but dont close socket.  
335                 }
336
337         }else if (http.isRequest(PCX_PCP_CONNECT))
338         {
339
340                 if (!isAllowed(ALLOW_NETWORK) || !isFiltered(ServFilter::F_NETWORK))
341                         throw HTTPException(HTTP_SC_UNAVAILABLE,503);
342                 
343                 processIncomingPCP(true);
344
345         }else if (http.isRequest("PEERCAST CONNECT"))
346         {
347                 if (!isAllowed(ALLOW_NETWORK) || !isFiltered(ServFilter::F_NETWORK))
348                         throw HTTPException(HTTP_SC_UNAVAILABLE,503);
349
350                 LOG_DEBUG("PEERCAST client");
351                 processServent();
352
353         }else if (http.isRequest("SOURCE"))
354         {
355                 if (!isAllowed(ALLOW_BROADCAST))
356                         throw HTTPException(HTTP_SC_UNAVAILABLE,503);
357
358                 char *mount = NULL;
359
360                 char *ps;
361                 if (ps=strstr(in,"ICE/1.0"))
362                 {
363                         mount = in+7;
364                         *ps = 0;
365                         LOG_DEBUG("ICE 1.0 client to %s",mount?mount:"unknown");
366                 }else{
367                         mount = in+strlen(in);
368                         while (*--mount)
369                                 if (*mount == '/')
370                                 {
371                                         mount[-1] = 0; // password preceeds
372                                         break;
373                                 }
374                         loginPassword.set(in+7);
375                         
376                         LOG_DEBUG("ICY client: %s %s",loginPassword.cstr(),mount?mount:"unknown");
377                 }
378
379                 if (mount)
380                         loginMount.set(mount);
381
382                 handshakeICY(Channel::SRC_ICECAST,isHTTP);
383                 sock = NULL;    // socket is taken over by channel, so don`t close it
384
385         }else if (http.isRequest(servMgr->password))
386         {
387                 if (!isAllowed(ALLOW_BROADCAST))
388                         throw HTTPException(HTTP_SC_UNAVAILABLE,503);
389
390                 loginPassword.set(servMgr->password);   // pwd already checked
391
392                 sock->writeLine("OK2");
393                 sock->writeLine("icy-caps:11");
394                 sock->writeLine("");
395                 LOG_DEBUG("ShoutCast client");
396
397                 handshakeICY(Channel::SRC_SHOUTCAST,isHTTP);
398                 sock = NULL;    // socket is taken over by channel, so don`t close it
399
400         }else
401         {
402                 throw HTTPException(HTTP_SC_BADREQUEST,400);
403         }
404
405 }
406 // -----------------------------------
407 bool Servent::canStream(Channel *ch)
408 {
409         if (ch==NULL)
410                 return false;
411
412         if (servMgr->isDisabled)
413                 return false;
414
415         if (!isPrivate())
416         {
417                 if  (!ch->isPlaying() || ch->isFull() || ((type == T_DIRECT) && servMgr->directFull()))
418                         return false;
419
420                 if (!isIndexTxt(ch) && (type == T_RELAY) && (servMgr->relaysFull()))
421                         return false;
422
423                 Channel *c = chanMgr->channel;
424                 int noRelay = 0;
425                 unsigned int needRate = 0;
426                 unsigned int allRate = 0;
427                 while(c){
428                         if (c->isPlaying()){
429                                 int nlr = c->localRelays();
430                                 allRate += c->info.bitrate * nlr;
431                                 if ((c != ch) && (nlr == 0)){
432                                         if(!isIndexTxt(c))      // for PCRaw (relay)
433                                                 noRelay++;
434                                         needRate+=c->info.bitrate;
435                                 }
436                         }
437                         c = c->next;
438                 }
439                 unsigned int numRelay = servMgr->numStreams(Servent::T_RELAY,false);
440                 int diff = servMgr->maxRelays - numRelay;
441                 if (ch->localRelays()){
442                         if (noRelay > diff){
443                                 noRelay = diff;
444                         }
445                 } else {
446                         noRelay = 0;
447                         needRate = 0;
448                 }
449
450                 LOG_DEBUG("Relay check: Max=%d Now=%d Need=%d ch=%d",
451                         servMgr->maxBitrateOut, allRate, needRate, ch->info.bitrate);
452                 //              if  (   !ch->isPlaying()
453                 //                              || ch->isFull()
454                 //                              || (allRate + needRate + ch->info.bitrate > servMgr->maxBitrateOut)
455                 //                              || ((type == T_RELAY) && servMgr->relaysFull() && force_off)    // for PCRaw (relay) (force_off)
456                 //                              || ((type == T_RELAY) && (((servMgr->numStreams(Servent::T_RELAY,false) + noRelay) >= servMgr->maxRelays)) && force_off)        // for PCRaw (relay) (force_off)
457                 //                              || ((type == T_DIRECT) && servMgr->directFull())
458                 //              ){
459
460                 if (allRate + needRate + ch->info.bitrate > servMgr->maxBitrateOut)
461                 {
462                         LOG_DEBUG("Relay check: NG");
463                         return false;
464                 }
465
466                 if (!isIndexTxt(ch) && (type == T_RELAY) && (numRelay + noRelay >= servMgr->maxRelays))
467                 {
468                         LOG_DEBUG("Relay check: NG");
469                         return false;
470                 }
471         }
472
473         LOG_DEBUG("Relay check: OK");
474         return true;
475 }
476 // -----------------------------------
477 void Servent::handshakeIncoming()
478 {
479
480         setStatus(S_HANDSHAKE);
481
482         char buf[2048];
483         sock->readLine(buf,sizeof(buf));
484
485         char sb[64];
486         sock->host.toStr(sb);
487
488
489         if (stristr(buf,RTSP_PROTO1))
490         {
491                 LOG_DEBUG("RTSP from %s '%s'",sb,buf);
492                 RTSP rtsp(*sock);
493                 rtsp.initRequest(buf);
494                 handshakeRTSP(rtsp);
495         }else if (stristr(buf,HTTP_PROTO1))
496         {
497                 LOG_DEBUG("HTTP from %s '%s'",sb,buf);
498                 HTTP http(*sock);
499                 http.initRequest(buf);
500                 handshakeHTTP(http,true);
501         }else
502         {
503                 LOG_DEBUG("Connect from %s '%s'",sb,buf);
504                 HTTP http(*sock);
505                 http.initRequest(buf);
506                 handshakeHTTP(http,false);
507         }
508
509 }
510 // -----------------------------------
511 void Servent::triggerChannel(char *str, ChanInfo::PROTOCOL proto,bool relay)    
512 {
513
514         ChanInfo info;
515 //      WLockBlock lb(&(chanMgr->channellock));
516
517 //      LOG_DEBUG("----------triggerChannel LOCK ON");
518 //      lb.on();
519         servMgr->getChannel(str,info,relay);
520 //      LOG_DEBUG("==========triggerChannel LOCK OFF");
521 //      lb.off();
522
523         if (proto == ChanInfo::SP_PCP)
524                 type = T_RELAY;
525         else
526                 type = T_DIRECT;
527
528         outputProtocol = proto;
529
530         processStream(false,info);
531
532 }
533 // -----------------------------------
534 void writePLSHeader(Stream &s, PlayList::TYPE type)
535 {
536         s.writeLine(HTTP_SC_OK);
537         s.writeLineF("%s %s",HTTP_HS_SERVER,PCX_AGENT);
538
539         const char *content;
540         switch(type)
541         {
542                 case PlayList::T_PLS:
543                         content = MIME_XM3U;
544                         break;
545                 case PlayList::T_ASX:
546                         content = MIME_ASX;
547                         break;
548                 case PlayList::T_RAM:
549                         content = MIME_RAM;
550                         break;
551                 default:
552                         content = MIME_TEXT;
553                         break;
554         }
555         s.writeLineF("%s %s",HTTP_HS_CONTENT,content);
556     s.writeLine("Content-Disposition: inline");
557     s.writeLine("Cache-Control: private" );
558         s.writeLineF("%s %s",HTTP_HS_CONNECTION,"close");
559
560         s.writeLine("");
561 }
562
563 // -----------------------------------
564 void Servent::handshakePLS(ChanInfo &info, bool doneHandshake)
565 {
566         char url[256];
567
568         char in[128];
569
570         if (!doneHandshake)
571                 while (sock->readLine(in,128));
572
573
574         if (getLocalTypeURL(url,info.contentType))
575         {
576
577                 PlayList::TYPE type;
578
579                 if ((info.contentType == ChanInfo::T_WMA) || (info.contentType == ChanInfo::T_WMV))
580                         type = PlayList::T_ASX;
581                 else if (info.contentType == ChanInfo::T_OGM)
582                         type = PlayList::T_RAM;
583                 else
584                         type = PlayList::T_PLS;
585
586                 writePLSHeader(*sock,type);
587
588                 PlayList *pls;
589
590                 pls = new PlayList(type,1);
591
592                 pls->addChannel(url,info);
593
594                 pls->write(*sock);
595
596                 delete pls;
597         }
598 }
599 // -----------------------------------
600 void Servent::handshakePLS(ChanHitList **cl, int num, bool doneHandshake)
601 {
602         char url[256];
603         char in[128];
604
605         if (!doneHandshake)
606                 while (sock->readLine(in,128));
607
608         if (getLocalURL(url))
609         {
610                 writePLSHeader(*sock,PlayList::T_SCPLS);
611
612                 PlayList *pls;
613
614                 pls = new PlayList(PlayList::T_SCPLS,num);
615
616                 for(int i=0; i<num; i++)
617                         pls->addChannel(url,cl[i]->info);
618
619                 pls->write(*sock);
620
621                 delete pls;
622         }
623 }
624 // -----------------------------------
625 bool Servent::getLocalURL(char *str)
626 {
627         if (!sock)
628                 throw StreamException("Not connected");
629
630
631         char ipStr[64];
632
633         Host h;
634         
635         if (sock->host.localIP())
636                 h = sock->getLocalHost();
637         else
638                 h = servMgr->serverHost;
639
640         h.port = servMgr->serverHost.port;
641
642         h.toStr(ipStr);
643
644         sprintf(str,"http://%s",ipStr);                 
645         return true;
646 }
647
648 // -----------------------------------
649 bool Servent::getLocalTypeURL(char *str, ChanInfo::TYPE type)
650 {
651         if (!sock)
652                 throw StreamException("Not connected");
653
654
655         char ipStr[64];
656
657         Host h;
658         
659         if (sock->host.localIP())
660                 h = sock->getLocalHost();
661         else
662                 h = servMgr->serverHost;
663
664         h.port = servMgr->serverHost.port;
665
666         h.toStr(ipStr);
667         switch(type) {
668                 case ChanInfo::T_WMA:
669                 case ChanInfo::T_WMV:
670                         sprintf(str,"mms://%s",ipStr);  
671                         break;
672                 default:
673                         sprintf(str,"http://%s",ipStr); 
674         }
675         return true;
676 }
677 // -----------------------------------
678 // Warning: testing RTSP/RTP stuff below.
679 // .. moved over to seperate app now.
680 // -----------------------------------
681 void Servent::handshakePOST()
682 {
683         char tmp[1024];
684     while (sock->readLine(tmp,sizeof(tmp)))
685                 LOG_DEBUG("POST: %s",tmp);
686
687         throw HTTPException(HTTP_SC_BADREQUEST,400);
688 }
689
690
691 // -----------------------------------
692 void Servent::handshakeRTSP(RTSP &rtsp)
693 {
694         throw HTTPException(HTTP_SC_BADREQUEST,400);
695 }
696 // -----------------------------------
697 bool Servent::handshakeAuth(HTTP &http,const char *args,bool local)
698 {
699         char user[1024],pass[1024];
700         user[0] = pass[0] = 0;
701
702         char *pwd  = getCGIarg(args, "pass=");
703
704         if ((pwd) && strlen(servMgr->password))
705         {
706                 String tmp = pwd;
707                 char *as = strstr(tmp.cstr(),"&");
708                 if (as) *as = 0;
709                 if (strcmp(tmp,servMgr->password)==0)
710                 {
711                     while (http.nextHeader());
712                         return true;
713                 }
714         }
715
716         Cookie gotCookie;
717         cookie.clear();
718
719     while (http.nextHeader())
720         {
721                 char *arg = http.getArgStr();
722                 if (!arg)
723                         continue;
724
725                 switch (servMgr->authType)
726                 {
727                         case ServMgr::AUTH_HTTPBASIC:
728                                 if (http.isHeader("Authorization"))
729                                         http.getAuthUserPass(user, pass, sizeof(user), sizeof(pass));
730                                 break;
731                         case ServMgr::AUTH_COOKIE:
732                                 if (http.isHeader("Cookie"))
733                                 {
734                                         LOG_DEBUG("Got cookie: %s",arg);
735                                         char *idp=arg;
736                                         while ((idp = strstr(idp,"id=")))
737                                         {
738                                                 idp+=3;
739                                                 gotCookie.set(idp,sock->host.ip);
740                                                 if (servMgr->cookieList.contains(gotCookie))
741                                                 {
742                                                         LOG_DEBUG("Cookie found");
743                                                         cookie = gotCookie;
744                                                         break;
745                                                 }
746
747                                         }
748                                 }
749                                 break;
750                 }
751         }
752
753         if (sock->host.isLocalhost())
754                 return true;
755
756
757         switch (servMgr->authType)
758         {
759                 case ServMgr::AUTH_HTTPBASIC:
760                                 
761                         if ((strcmp(pass,servMgr->password)==0) && strlen(servMgr->password))
762                                 return true;
763                         break;
764                 case ServMgr::AUTH_COOKIE:
765                         if (servMgr->cookieList.contains(cookie))
766                                 return true;
767                         break;
768         }
769
770
771
772         if (servMgr->authType == ServMgr::AUTH_HTTPBASIC)
773         {
774                 http.writeLine(HTTP_SC_UNAUTHORIZED);
775                 http.writeLine("WWW-Authenticate: Basic realm=\"PeerCast Admin\"");
776         }else if (servMgr->authType == ServMgr::AUTH_COOKIE)
777         {
778                 String file = servMgr->htmlPath;
779                 file.append("/login.html");
780                 if (local)
781                         handshakeLocalFile(file);
782                 else
783                         handshakeRemoteFile(file);
784         }
785         
786
787         return false;
788 }
789
790 // -----------------------------------
791 void Servent::handshakeCMD(char *cmd)
792 {
793         char result[MAX_CGI_LEN];
794         char arg[MAX_CGI_LEN];
795         char curr[MAX_CGI_LEN];
796
797         char    jumpStr[128];
798         char    *jumpArg=NULL;
799         bool    retHTML=true;
800         strcpy(result,"OK");
801
802         HTTP http(*sock);
803         HTML html("",*sock);
804
805
806         if (!handshakeAuth(http,cmd,true))
807                 return;
808
809         try
810         {
811                 if (cmpCGIarg(cmd,"cmd=","redirect"))
812                 {
813                         char *j = getCGIarg(cmd,"url=");
814                         if (j)
815                         {
816                                 termArgs(cmd);
817                                 String url;
818                                 url.set(j,String::T_ESC);
819                                 url.convertTo(String::T_ASCII);
820
821                                 if (!url.contains("http://"))
822                                         url.prepend("http://");
823
824                                 html.setRefreshURL(url.cstr());
825                                 html.startHTML();
826                                         html.addHead();
827                                         html.startBody();
828                                                 html.startTagEnd("h3","Please wait...");
829                                         html.end();
830                                 html.end();
831
832                         }
833                 }else{
834
835                         if (cmpCGIarg(cmd,"cmd=","viewxml"))
836                         {
837
838                                 handshakeXML();
839                                 retHTML = false;
840                         }else if (cmpCGIarg(cmd,"cmd=","clearlog"))
841                         {
842                                 sys->logBuf->clear();
843                                 sprintf(jumpStr,"/%s/viewlog.html",servMgr->htmlPath);                                  
844                                 jumpArg = jumpStr;
845
846                         }else if (cmpCGIarg(cmd,"cmd=","save"))
847                         {
848
849                                 peercastInst->saveSettings();
850
851                                 sprintf(jumpStr,"/%s/settings.html",servMgr->htmlPath);                                 
852                                 jumpArg = jumpStr;
853                         }else if (cmpCGIarg(cmd,"cmd=","reg"))
854                         {
855                                 char idstr[128];
856                                 chanMgr->broadcastID.toStr(idstr);
857                                 sprintf(jumpStr,"http://www.peercast.org/register/?id=%s",idstr);                                       
858                                 jumpArg = jumpStr;
859                         }else if (cmpCGIarg(cmd,"cmd=","edit_bcid"))
860                         {
861                                 char *cp = cmd;
862                                 GnuID id;
863                                 BCID *bcid;
864                                 while (cp=nextCGIarg(cp,curr,arg))
865                                 {
866                                         if (strcmp(curr,"id")==0)
867                                                 id.fromStr(arg);
868                                         else if (strcmp(curr,"del")==0)
869                                                 servMgr->removeValidBCID(id);
870                                         else if (strcmp(curr,"valid")==0)
871                                         {
872                                                 bcid = servMgr->findValidBCID(id);
873                                                 if (bcid)
874                                                         bcid->valid = getCGIargBOOL(arg);
875                                         }
876                                 }
877                                 peercastInst->saveSettings();
878                                 sprintf(jumpStr,"/%s/bcid.html",servMgr->htmlPath);                                     
879                                 jumpArg = jumpStr;
880
881                         }else if (cmpCGIarg(cmd,"cmd=","add_bcid"))
882                         {
883                                 BCID *bcid = new BCID();
884
885                                 char *cp = cmd;
886                                 bool result=false;
887                                 while (cp=nextCGIarg(cp,curr,arg))
888                                 {
889                                         if (strcmp(curr,"id")==0)
890                                                 bcid->id.fromStr(arg);
891                                         else if (strcmp(curr,"name")==0)
892                                                 bcid->name.set(arg);
893                                         else if (strcmp(curr,"email")==0)
894                                                 bcid->email.set(arg);
895                                         else if (strcmp(curr,"url")==0)
896                                                 bcid->url.set(arg);
897                                         else if (strcmp(curr,"valid")==0)
898                                                 bcid->valid = getCGIargBOOL(arg);
899                                         else if (strcmp(curr,"result")==0)
900                                                 result = true;
901
902                                 }
903         
904                                 LOG_DEBUG("Adding BCID : %s",bcid->name.cstr());                        
905                                 servMgr->addValidBCID(bcid);
906                                 peercastInst->saveSettings();
907                                 if (result)
908                                 {
909                                         http.writeLine(HTTP_SC_OK);
910                                         http.writeLine("");
911                                         http.writeString("OK");
912                                 }else
913                                 {
914                                         sprintf(jumpStr,"/%s/bcid.html",servMgr->htmlPath);                                     
915                                         jumpArg = jumpStr;
916                                 }
917
918
919                         }else if (cmpCGIarg(cmd,"cmd=","apply"))
920                         {       
921                                 //servMgr->numFilters = 0;
922                                 ServFilter *currFilter=servMgr->filters;
923                                 bool beginfilt = false;
924
925                                 bool brRoot=false;
926                                 bool getUpd=false;
927                                 int showLog=0;
928                                 int allowServer1=0;
929                                 int allowServer2=0;
930                                 int newPort=servMgr->serverHost.port;
931                                 int enableGetName = 0;
932                                 int allowConnectPCST = 0;
933                                 int disableAutoBumpIfDirect = 0; //JP-MOD
934                                 int asxDetailedMode = 0; //JP-MOD
935
936                                 char *cp = cmd;
937                                 while (cp=nextCGIarg(cp,curr,arg))
938                                 {
939                                         LOG_DEBUG("ARG: %s = %s", curr, arg);
940
941                                         // server
942                                         if (strcmp(curr,"serveractive")==0)
943                                                 servMgr->autoServe = getCGIargBOOL(arg);
944                                         else if (strcmp(curr,"port")==0)
945                                                 newPort = getCGIargINT(arg);
946                                         else if (strcmp(curr,"icymeta")==0)
947                                         {
948                                                 int iv = getCGIargINT(arg);
949                                                 if (iv < 0) iv = 0;
950                                                 else if (iv > 16384) iv = 16384;
951
952                                                 chanMgr->icyMetaInterval = iv;
953
954                                         }else if (strcmp(curr,"passnew")==0)
955                                                 strcpy(servMgr->password,arg);
956                                         else if (strcmp(curr,"root")==0)
957                                                 servMgr->isRoot = getCGIargBOOL(arg);
958                                         else if (strcmp(curr,"brroot")==0)
959                                                 brRoot = getCGIargBOOL(arg);
960                                         else if (strcmp(curr,"getupd")==0)
961                                                 getUpd = getCGIargBOOL(arg);
962                                         else if (strcmp(curr,"huint")==0)
963                                                 chanMgr->setUpdateInterval(getCGIargINT(arg));
964                                         else if (strcmp(curr,"forceip")==0)
965                                                 servMgr->forceIP = arg;
966                                         else if (strcmp(curr,"htmlPath")==0)
967                                         {
968                                                 strcpy(servMgr->htmlPath,"html/");
969                                                 strcat(servMgr->htmlPath,arg);
970                                         }else if (strcmp(curr,"djmsg")==0)
971                                         {
972                                                 String msg;
973                                                 msg.set(arg,String::T_ESC);
974                                                 msg.convertTo(String::T_UNICODE);
975                                                 chanMgr->setBroadcastMsg(msg);
976                                         }
977                                         else if (strcmp(curr,"pcmsg")==0)
978                                         {
979                                                 servMgr->rootMsg.set(arg,String::T_ESC);
980                                                 servMgr->rootMsg.convertTo(String::T_UNICODE);
981                                         }else if (strcmp(curr,"minpgnu")==0)
982                                                 servMgr->minGnuIncoming = atoi(arg);
983                                         else if (strcmp(curr,"maxpgnu")==0)
984                                                 servMgr->maxGnuIncoming = atoi(arg);
985                                         
986
987
988                                         // connections
989                                         else if (strcmp(curr,"maxcin")==0)
990                                                 servMgr->maxControl = getCGIargINT(arg);
991
992                                         else if (strcmp(curr,"maxup")==0)
993                                                 servMgr->maxBitrateOut = getCGIargINT(arg);
994                                         else if (strcmp(curr,"maxrelays")==0)
995                                                 servMgr->setMaxRelays(getCGIargINT(arg));
996                                         else if (strcmp(curr,"maxdirect")==0)
997                                                 servMgr->maxDirect = getCGIargINT(arg);
998                                         else if (strcmp(curr,"maxrelaypc")==0)
999                                                 chanMgr->maxRelaysPerChannel = getCGIargINT(arg);
1000                                         else if (strncmp(curr,"filt_",5)==0)
1001                                         {
1002                                                 if (!beginfilt) {
1003                                                         servMgr->numFilters = 0;
1004                                                         beginfilt = true;
1005                                                 }
1006                                                 char *fs = curr+5;
1007                                                 {
1008                                                         if (strncmp(fs,"ip",2)==0)              // ip must be first
1009                                                         {
1010                                                                 currFilter = &servMgr->filters[servMgr->numFilters];
1011                                                                 currFilter->init();     
1012                                                                 currFilter->host.fromStrIP(arg,DEFAULT_PORT);
1013                                                                 if ((currFilter->host.ip) && (servMgr->numFilters < (ServMgr::MAX_FILTERS-1)))
1014                                                                 {
1015                                                                         servMgr->numFilters++;
1016                                                                         servMgr->filters[servMgr->numFilters].init();   // clear new entry
1017                                                                         LOG_DEBUG("numFilters = %d", servMgr->numFilters);
1018                                                                 }
1019
1020                                                         }else if (strncmp(fs,"bn",2)==0)
1021                                                                 currFilter->flags |= ServFilter::F_BAN;
1022                                                         else if (strncmp(fs,"pr",2)==0)
1023                                                                 currFilter->flags |= ServFilter::F_PRIVATE;
1024                                                         else if (strncmp(fs,"nw",2)==0)
1025                                                                 currFilter->flags |= ServFilter::F_NETWORK;
1026                                                         else if (strncmp(fs,"di",2)==0)
1027                                                                 currFilter->flags |= ServFilter::F_DIRECT;
1028                                                 }
1029                                         }
1030
1031                                         // client
1032                                         else if (strcmp(curr,"clientactive")==0)
1033                                                 servMgr->autoConnect = getCGIargBOOL(arg);
1034                                         else if (strcmp(curr,"yp")==0)
1035                                         {
1036                                                 if (!PCP_FORCE_YP)
1037                                                 {
1038                                                         String str(arg,String::T_ESC);
1039                                                         str.convertTo(String::T_ASCII);
1040                                                         servMgr->rootHost = str;
1041                                                 }
1042                                         }
1043                                         else if (strcmp(curr,"yp2")==0)
1044                                         {
1045                                                 if (!PCP_FORCE_YP)
1046                                                 {
1047                                                         String str(arg,String::T_ESC);
1048                                                         str.convertTo(String::T_ASCII);
1049                                                         servMgr->rootHost2 = str;
1050                                                 }
1051                                         }
1052                                         else if (strcmp(curr,"deadhitage")==0)
1053                                                 chanMgr->deadHitAge = getCGIargINT(arg);
1054                                         else if (strcmp(curr,"refresh")==0)
1055                                                 servMgr->refreshHTML = getCGIargINT(arg);
1056                                         else if (strcmp(curr,"auth")==0)
1057                                         {
1058                                                 if (strcmp(arg,"cookie")==0)
1059                                                         servMgr->authType = ServMgr::AUTH_COOKIE;
1060                                                 else if (strcmp(arg,"http")==0)
1061                                                         servMgr->authType = ServMgr::AUTH_HTTPBASIC;
1062
1063                                         }else if (strcmp(curr,"expire")==0)
1064                                         {
1065                                                 if (strcmp(arg,"session")==0)
1066                                                         servMgr->cookieList.neverExpire = false;
1067                                                 else if (strcmp(arg,"never")==0)
1068                                                         servMgr->cookieList.neverExpire = true;
1069                                         }
1070
1071                                         else if (strcmp(curr,"logDebug")==0)
1072                                                 showLog |= atoi(arg)?(1<<LogBuffer::T_DEBUG):0;
1073                                         else if (strcmp(curr,"logErrors")==0)
1074                                                 showLog |= atoi(arg)?(1<<LogBuffer::T_ERROR):0;
1075                                         else if (strcmp(curr,"logNetwork")==0)
1076                                                 showLog |= atoi(arg)?(1<<LogBuffer::T_NETWORK):0;
1077                                         else if (strcmp(curr,"logChannel")==0)
1078                                                 showLog |= atoi(arg)?(1<<LogBuffer::T_CHANNEL):0;
1079
1080                                         else if (strcmp(curr,"allowHTML1")==0)
1081                                                 allowServer1 |= atoi(arg)?(ALLOW_HTML):0;
1082                                         else if (strcmp(curr,"allowNetwork1")==0)
1083                                                 allowServer1 |= atoi(arg)?(ALLOW_NETWORK):0;
1084                                         else if (strcmp(curr,"allowBroadcast1")==0)
1085                                                 allowServer1 |= atoi(arg)?(ALLOW_BROADCAST):0;
1086                                         else if (strcmp(curr,"allowDirect1")==0)
1087                                                 allowServer1 |= atoi(arg)?(ALLOW_DIRECT):0;
1088
1089                                         else if (strcmp(curr,"allowHTML2")==0)
1090                                                 allowServer2 |= atoi(arg)?(ALLOW_HTML):0;
1091                                         else if (strcmp(curr,"allowBroadcast2")==0)
1092                                                 allowServer2 |= atoi(arg)?(ALLOW_BROADCAST):0;
1093
1094                                         // JP-EX
1095                                         else if (strcmp(curr, "autoRelayKeep") ==0)
1096                                                         servMgr->autoRelayKeep = getCGIargINT(arg);
1097                                         else if (strcmp(curr, "autoMaxRelaySetting") ==0)
1098                                                         servMgr->autoMaxRelaySetting = getCGIargINT(arg);
1099                                         else if (strcmp(curr, "autoBumpSkipCount") ==0)
1100                                                         servMgr->autoBumpSkipCount = getCGIargINT(arg);
1101                                         else if (strcmp(curr, "kickPushStartRelays") ==0)
1102                                                         servMgr->kickPushStartRelays = getCGIargINT(arg);
1103                                         else if (strcmp(curr, "kickPushInterval") ==0)
1104                                                         servMgr->kickPushInterval = getCGIargINT(arg);
1105                                         else if (strcmp(curr, "allowConnectPCST") ==0)
1106                                                 allowConnectPCST = atoi(arg) ? 1 : 0;
1107                                         else if (strcmp(curr, "enableGetName") ==0)
1108                                                 enableGetName = atoi(arg)? 1 : 0;
1109                                         else if (strcmp(curr, "autoPort0Kick") ==0)
1110                                                 servMgr->autoPort0Kick = getCGIargBOOL(arg);
1111                                         else if (strcmp(curr, "allowOnlyVP") ==0)
1112                                                 servMgr->allowOnlyVP = getCGIargBOOL(arg);
1113                                         else if (strcmp(curr, "kickKeepTime") ==0)
1114                                                 servMgr->kickKeepTime = getCGIargINT(arg);
1115
1116                                         else if (strcmp(curr, "maxRelaysIndexTxt") ==0)         // for PCRaw (relay)
1117                                                 servMgr->maxRelaysIndexTxt = getCGIargINT(arg);
1118                                         else if (strcmp(curr, "disableAutoBumpIfDirect") ==0) //JP-MOD
1119                                                 disableAutoBumpIfDirect = atoi(arg) ? 1 : 0;
1120                                         else if (strcmp(curr, "asxDetailedMode") ==0) //JP-MOD
1121                                                 asxDetailedMode = getCGIargINT(arg);
1122                                 }
1123
1124
1125
1126                                 servMgr->showLog = showLog;
1127                                 servMgr->allowServer1 = allowServer1;
1128                                 servMgr->allowServer2 = allowServer2;
1129                                 servMgr->enableGetName = enableGetName;
1130                                 servMgr->allowConnectPCST = allowConnectPCST;
1131                                 servMgr->disableAutoBumpIfDirect = disableAutoBumpIfDirect; //JP-MOD
1132                                 servMgr->asxDetailedMode = asxDetailedMode; //JP-MOD
1133                                 if (!(servMgr->allowServer1 & ALLOW_HTML) && !(servMgr->allowServer2 & ALLOW_HTML))
1134                                         servMgr->allowServer1 |= ALLOW_HTML;
1135
1136                                 if (servMgr->serverHost.port != newPort)
1137                                 {
1138                                         Host lh(ClientSocket::getIP(NULL),newPort);
1139                                         char ipstr[64];
1140                                         lh.toStr(ipstr);
1141                                         sprintf(jumpStr,"http://%s/%s/settings.html",ipstr,servMgr->htmlPath);                                  
1142
1143                                         servMgr->serverHost.port = newPort;
1144                                         servMgr->restartServer=true;
1145                                         //html.setRefresh(3);
1146                                         //html.setRefreshURL(jumpStr);
1147                                         //html.startHTML();
1148                                         //html.addHead();
1149                                         //      html.startBody();
1150                                         //              html.startTagEnd("h1","Please wait...");
1151                                         //      html.end();
1152                                         //html.end();
1153
1154                                         
1155
1156                                         //char ipstr[64];
1157                                         //servMgr->serverHost.toStr(ipstr);
1158                                         //sprintf(jumpStr,"/%s/settings.html",ipstr,servMgr->htmlPath);                                 
1159                                         jumpArg = jumpStr;
1160
1161                                 }else
1162                                 {
1163                                         sprintf(jumpStr,"/%s/settings.html",servMgr->htmlPath);                                 
1164                                         jumpArg = jumpStr;
1165                                 }
1166
1167                                 peercastInst->saveSettings();
1168
1169                                 peercastApp->updateSettings();
1170
1171                                 if ((servMgr->isRoot) && (brRoot))
1172                                         servMgr->broadcastRootSettings(getUpd);
1173
1174
1175
1176                                 
1177
1178                         }else if (cmpCGIarg(cmd,"cmd=","fetch"))
1179                         {
1180
1181                                 ChanInfo info;
1182                                 String curl;
1183
1184                                 char *cp = cmd;
1185                                 while (cp=nextCGIarg(cp,curr,arg))
1186                                 {
1187                                         if (strcmp(curr,"url")==0)
1188                                         {
1189                                                 curl.set(arg,String::T_ESC);
1190                                                 curl.convertTo(String::T_UNICODE);
1191                                         }else if (strcmp(curr,"name")==0)
1192                                         {
1193                                                 info.name.set(arg,String::T_ESC);
1194                                                 info.name.convertTo(String::T_UNICODE);
1195                                         }else if (strcmp(curr,"desc")==0)
1196                                         {
1197                                                 info.desc.set(arg,String::T_ESC);
1198                                                 info.desc.convertTo(String::T_UNICODE);
1199                                         }else if (strcmp(curr,"genre")==0)
1200                                         {
1201                                                 info.genre.set(arg,String::T_ESC);
1202                                                 info.genre.convertTo(String::T_UNICODE);
1203                                         }else if (strcmp(curr,"contact")==0)
1204                                         {
1205                                                 info.url.set(arg,String::T_ESC);
1206                                                 info.url.convertTo(String::T_UNICODE);
1207                                         }else if (strcmp(curr,"bitrate")==0)
1208                                         {
1209                                                 info.bitrate = atoi(arg);
1210                                         }else if (strcmp(curr,"type")==0)
1211                                         {
1212                                                 info.contentType = ChanInfo::getTypeFromStr(arg);
1213                                         }else if (strcmp(curr,"bcstClap")==0) //JP-MOD
1214                                         {
1215                                                 info.ppFlags |= ServMgr::bcstClap;
1216                                         }
1217
1218                                 }
1219                                 
1220                                 info.bcID = chanMgr->broadcastID;
1221
1222                                 Channel *c = chanMgr->createChannel(info,NULL);
1223                                 if (c)
1224                                         c->startURL(curl.cstr());
1225
1226
1227                                 sprintf(jumpStr,"/%s/relays.html",servMgr->htmlPath);                                   
1228                                 jumpArg = jumpStr;
1229
1230                         }else if (cmpCGIarg(cmd,"cmd=","stopserv"))
1231                         {
1232
1233                                 char *cp = cmd;
1234                                 while (cp=nextCGIarg(cp,curr,arg))
1235                                 {
1236                                         if (strcmp(curr,"index")==0)
1237                                         {
1238                                                 Servent *s = servMgr->findServentByIndex(atoi(arg));
1239                                                 if (s)
1240                                                         s->abort();
1241                                         }
1242                                 }
1243                                 sprintf(jumpStr,"/%s/connections.html",servMgr->htmlPath);                                      
1244                                 jumpArg = jumpStr;
1245
1246
1247                         }else if (cmpCGIarg(cmd,"cmd=","hitlist"))
1248                         {                       
1249                                         
1250                                 bool stayConnected=hasCGIarg(cmd,"relay");
1251
1252                                 int index = 0;
1253                                 ChanHitList *chl = chanMgr->hitlist;                            
1254                                 while (chl)
1255                                 {
1256                                         if (chl->isUsed())
1257                                         {
1258                                                 char tmp[64];
1259                                                 sprintf(tmp,"c%d=",index);
1260                                                 if (cmpCGIarg(cmd,tmp,"1"))
1261                                                 {
1262                                                         Channel *c;
1263                                                         if (!(c=chanMgr->findChannelByID(chl->info.id)))
1264                                                         {
1265                                                                 c = chanMgr->createChannel(chl->info,NULL);
1266                                                                 if (!c)
1267                                                                         throw StreamException("out of channels");
1268                                                                 c->stayConnected = stayConnected;
1269                                                                 c->startGet();
1270                                                         }
1271                                                 }
1272                                         }
1273                                         chl = chl->next;
1274                                         index++;
1275                                 }
1276
1277                                 char *findArg = getCGIarg(cmd,"keywords=");
1278
1279                                 if (hasCGIarg(cmd,"relay"))
1280                                 {
1281                                         sys->sleep(500);
1282                                         sprintf(jumpStr,"/%s/relays.html",servMgr->htmlPath);                                   
1283                                         jumpArg = jumpStr;
1284                                 }
1285                         }else if (cmpCGIarg(cmd,"cmd=","clear"))
1286                         {
1287                                 char *cp = cmd;
1288                                 while (cp=nextCGIarg(cp,curr,arg))
1289                                 {
1290                                         if (strcmp(curr,"hostcache")==0)
1291                                                 servMgr->clearHostCache(ServHost::T_SERVENT);
1292                                         else if (strcmp(curr,"hitlists")==0)
1293                                                 chanMgr->clearHitLists();
1294                                         else if (strcmp(curr,"packets")==0)
1295                                         {
1296                                                 stats.clearRange(Stats::PACKETSSTART,Stats::PACKETSEND);
1297                                                 servMgr->numVersions = 0;
1298                                         }
1299                                 }
1300
1301                                 sprintf(jumpStr,"/%s/index.html",servMgr->htmlPath);                                    
1302                                 jumpArg = jumpStr;
1303
1304                         }else if (cmpCGIarg(cmd,"cmd=","upgrade"))
1305                         {
1306                                 if (servMgr->downloadURL[0])
1307                                 {
1308                                         sprintf(jumpStr,"/admin?cmd=redirect&url=%s",servMgr->downloadURL);
1309                                         jumpArg = jumpStr;
1310                                 }
1311
1312
1313
1314
1315                         }else if (cmpCGIarg(cmd,"cmd=","connect"))
1316                         {                       
1317                                         
1318
1319                                 Servent *s = servMgr->servents;
1320                                 {
1321                                         char tmp[64];
1322                                         sprintf(tmp,"c%d=",s->serventIndex);
1323                                         if (cmpCGIarg(cmd,tmp,"1"))
1324                                         {
1325                                                 if (hasCGIarg(cmd,"stop"))
1326                                                         s->thread.active = false;
1327                                         }
1328                                         s=s->next;
1329                                 }
1330                                 sprintf(jumpStr,"/%s/connections.html",servMgr->htmlPath);                                      
1331                                 jumpArg = jumpStr;
1332
1333                         }else if (cmpCGIarg(cmd,"cmd=","shutdown"))
1334                         {
1335                                 servMgr->shutdownTimer = 1;
1336
1337                         }else if (cmpCGIarg(cmd,"cmd=","stop"))
1338                         {
1339                                 GnuID id;
1340                                 char *cp = cmd;
1341                                 while (cp=nextCGIarg(cp,curr,arg))
1342                                 {
1343                                         if (strcmp(curr,"id")==0)
1344                                                 id.fromStr(arg);
1345                                 }
1346
1347                                 Channel *c = chanMgr->findChannelByID(id);
1348                                 if (c){
1349                                         c->thread.active = false;
1350                                         c->thread.finish = true;
1351                                 }
1352
1353                                 sys->sleep(500);
1354                                 sprintf(jumpStr,"/%s/relays.html",servMgr->htmlPath);                                   
1355                                 jumpArg = jumpStr;
1356
1357                         }else if (cmpCGIarg(cmd,"cmd=","bump"))
1358                         {
1359                                 GnuID id;
1360                                 char *cp = cmd;
1361                                 while (cp=nextCGIarg(cp,curr,arg))
1362                                 {
1363                                         if (strcmp(curr,"id")==0)
1364                                                 id.fromStr(arg);
1365                                 }
1366
1367                                 Channel *c = chanMgr->findChannelByID(id);
1368                                 if (c)
1369                                         c->bump = true;
1370
1371                                 sprintf(jumpStr,"/%s/relays.html",servMgr->htmlPath);                                   
1372                                 jumpArg = jumpStr;
1373
1374                         }else if (cmpCGIarg(cmd,"cmd=","keep"))
1375                         {
1376                                 GnuID id;
1377                                 char *cp = cmd;
1378                                 while (cp=nextCGIarg(cp,curr,arg))
1379                                 {
1380                                         if (strcmp(curr,"id")==0)
1381                                                 id.fromStr(arg);
1382                                 }
1383
1384                                 Channel *c = chanMgr->findChannelByID(id);
1385                                 if (c)
1386                                 { //JP-Patch
1387                                         //c->stayConnected = true;
1388                                         if (!c->stayConnected)
1389                                         {
1390                                                 //if (servMgr->getFirewall() == ServMgr::FW_OFF)
1391                                                 c->stayConnected = true;
1392                                         }
1393                                         else
1394                                                 c->stayConnected = false;
1395                                 } //JP-Patch
1396
1397                                 sprintf(jumpStr,"/%s/relays.html",servMgr->htmlPath);                                   
1398                                 jumpArg = jumpStr;
1399
1400                         }else if (cmpCGIarg(cmd,"cmd=","relay"))
1401                         {
1402                                 ChanInfo info;
1403                                 char *cp = cmd;
1404                                 while (cp=nextCGIarg(cp,curr,arg))
1405                                 {
1406                                         if (strcmp(curr,"id")==0)
1407                                                 info.id.fromStr(arg);
1408                                 }
1409
1410
1411                                 if (!chanMgr->findChannelByID(info.id))
1412                                 {
1413
1414                                         ChanHitList *chl = chanMgr->findHitList(info);
1415                                         if (!chl)
1416                                                 throw StreamException("channel not found");
1417
1418
1419                                         Channel *c = chanMgr->createChannel(chl->info,NULL);
1420                                         if (!c)
1421                                                 throw StreamException("out of channels");
1422
1423                                         c->stayConnected = true;
1424                                         c->startGet();
1425                                 }
1426
1427                                 sprintf(jumpStr,"/%s/relays.html",servMgr->htmlPath);                                   
1428                                 jumpArg = jumpStr;
1429
1430
1431                         }else if (cmpCGIarg(cmd,"net=","add"))
1432                         {
1433                                 
1434                                 GnuID id;
1435                                 id.clear();
1436                                 while (cmd=nextCGIarg(cmd,curr,arg))
1437                                 {
1438                                         if (strcmp(curr,"ip")==0)
1439                                         {
1440                                                 Host h;
1441                                                 h.fromStrIP(arg,DEFAULT_PORT);
1442                                                 if (servMgr->addOutgoing(h,id,true))
1443                                                         LOG_NETWORK("Added connection: %s",arg);
1444
1445                                         }else if (strcmp(curr,"id")==0)
1446                                         {
1447                                                 id.fromStr(arg);
1448                                         }
1449
1450                                 }
1451
1452                         }else if (cmpCGIarg(cmd,"cmd=","logout"))
1453                         {
1454                                 jumpArg = "/";
1455                                 servMgr->cookieList.remove(cookie);
1456
1457                         }else if (cmpCGIarg(cmd,"cmd=","login"))
1458                         {
1459                                 GnuID id;
1460                                 char idstr[64];
1461                                 id.generate();
1462                                 id.toStr(idstr);
1463
1464                                 cookie.set(idstr,sock->host.ip);
1465                                 servMgr->cookieList.add(cookie);        
1466
1467                                 http.writeLine(HTTP_SC_FOUND);
1468                                 if (servMgr->cookieList.neverExpire)
1469                                         http.writeLineF("%s id=%s; path=/; expires=\"Mon, 01-Jan-3000 00:00:00 GMT\";",HTTP_HS_SETCOOKIE,idstr);
1470                                 else
1471                                         http.writeLineF("%s id=%s; path=/;",HTTP_HS_SETCOOKIE,idstr);
1472                                 http.writeLineF("Location: /%s/index.html",servMgr->htmlPath);
1473                                 http.writeLine("");
1474
1475                         }else if (cmpCGIarg(cmd,"cmd=","setmeta"))
1476                         {
1477                                 char *cp = cmd;
1478                                 while (cp=nextCGIarg(cp,curr,arg))
1479                                 {
1480                                         if (strcmp(curr,"name")==0)
1481                                         {
1482 /*                                              String chname;
1483                                                 chname.set(arg,String::T_ESC);
1484                                                 chname.convertTo(String::T_ASCII);
1485                                                 for(int i=0; i<ChanMgr::MAX_CHANNELS; i++)
1486                                                 {
1487                                                         Channel *c = &chanMgr->channels[i];
1488                                                         if ((c->isActive()) && (c->status == Channel::S_BROADCASTING) && (strcmp(c->info.name.cstr(),chname.cstr())==0)) 
1489                                                         {       
1490                                                                 ChanInfo newInfo = c->info;
1491
1492                                                                 while (cmd=nextCGIarg(cmd,curr,arg))
1493                                                                 {
1494                                                                         String chmeta;
1495                                                                         chmeta.set(arg,String::T_ESC);
1496                                                                         chmeta.convertTo(String::T_ASCII);
1497                                                                         if (strcmp(curr,"desc")==0)
1498                                                                                 newInfo.desc = chmeta.cstr();
1499                                                                         else if (strcmp(curr,"url")==0)
1500                                                                                 newInfo.url = chmeta.cstr();
1501                                                                         else if (strcmp(curr,"genre")==0)
1502                                                                                 newInfo.genre = chmeta.cstr();
1503                                                                         else if (strcmp(curr,"comment")==0)
1504                                                                                 newInfo.comment = chmeta.cstr();
1505                                                                         else if (strcmp(curr,"t_contact")==0)
1506                                                                                 newInfo.track.contact = chmeta.cstr();
1507                                                                         else if (strcmp(curr,"t_title")==0)
1508                                                                                 newInfo.track.title = chmeta.cstr();
1509                                                                         else if (strcmp(curr,"t_artist")==0)
1510                                                                                 newInfo.track.artist = chmeta.cstr();
1511                                                                         else if (strcmp(curr,"t_album")==0)
1512                                                                                 newInfo.track.album = chmeta.cstr();
1513                                                                         else if (strcmp(curr,"t_genre")==0)
1514                                                                                 newInfo.track.genre = chmeta.cstr();
1515                                                                 }
1516                                                                 c->updateInfo(newInfo);
1517                                                                 char idstr[64];
1518                                                                 newInfo.id.toStr(idstr);
1519                                                                 sprintf(jumpStr,"/%s/relayinfo.html?id=%s",servMgr->htmlPath,idstr);
1520                                                                 jumpArg = jumpStr;
1521                                                                 break;
1522                                                         }
1523                                                 }*/
1524                                                 String chname;
1525                                                 chname.set(arg,String::T_ESC);
1526                                                 chname.convertTo(String::T_ASCII);
1527
1528                                                 Channel *c = chanMgr->findChannelByName(chname.cstr());
1529                                                 if (c && (c->isActive()) && (c->status == Channel::S_BROADCASTING)){
1530                                                         ChanInfo newInfo = c->info;
1531                                                         newInfo.ppFlags = ServMgr::bcstNone; //JP-MOD
1532                                                         while (cmd=nextCGIarg(cmd,curr,arg))
1533                                                         {
1534                                                                 String chmeta;
1535                                                                 chmeta.set(arg,String::T_ESC);
1536                                                                 chmeta.convertTo(String::T_ASCII);
1537                                                                 if (strcmp(curr,"desc")==0)
1538                                                                         newInfo.desc = chmeta.cstr();
1539                                                                 else if (strcmp(curr,"url")==0)
1540                                                                         newInfo.url = chmeta.cstr();
1541                                                                 else if (strcmp(curr,"genre")==0)
1542                                                                         newInfo.genre = chmeta.cstr();
1543                                                                 else if (strcmp(curr,"comment")==0)
1544                                                                         newInfo.comment = chmeta.cstr();
1545                                                                 else if (strcmp(curr,"bcstClap")==0) //JP-MOD
1546                                                                         newInfo.ppFlags |= ServMgr::bcstClap;
1547                                                                 else if (strcmp(curr,"t_contact")==0)
1548                                                                         newInfo.track.contact = chmeta.cstr();
1549                                                                 else if (strcmp(curr,"t_title")==0)
1550                                                                         newInfo.track.title = chmeta.cstr();
1551                                                                 else if (strcmp(curr,"t_artist")==0)
1552                                                                         newInfo.track.artist = chmeta.cstr();
1553                                                                 else if (strcmp(curr,"t_album")==0)
1554                                                                         newInfo.track.album = chmeta.cstr();
1555                                                                 else if (strcmp(curr,"t_genre")==0)
1556                                                                         newInfo.track.genre = chmeta.cstr();
1557                                                         }
1558                                                         c->updateInfo(newInfo);
1559                                                         char idstr[64];
1560                                                         newInfo.id.toStr(idstr);
1561                                                         sprintf(jumpStr,"/%s/relayinfo.html?id=%s",servMgr->htmlPath,idstr);
1562                                                         jumpArg = jumpStr;
1563                                                 }
1564                                         }
1565                                 }
1566                                 if (!jumpArg)
1567                                 {
1568                                         jumpArg = "/";
1569                                 }
1570                 
1571                         }else{
1572
1573                                 sprintf(jumpStr,"/%s/index.html",servMgr->htmlPath);                                    
1574                                 jumpArg = jumpStr;
1575                         }
1576                 }
1577
1578         }catch(StreamException &e)
1579         {
1580                 html.startTagEnd("h1","ERROR - %s",e.msg);
1581                 LOG_ERROR("html: %s",e.msg);
1582         }
1583
1584
1585         if (retHTML)
1586         {
1587                 if (jumpArg)
1588                 {
1589                         String jmp(jumpArg,String::T_HTML);
1590                         jmp.convertTo(String::T_ASCII);
1591                         html.locateTo(jmp.cstr());
1592                 }
1593         }
1594
1595
1596 }
1597 // -----------------------------------
1598 static XML::Node *createChannelXML(Channel *c)
1599 {
1600         XML::Node *n = c->info.createChannelXML();
1601         n->add(c->createRelayXML(true));
1602         n->add(c->info.createTrackXML());
1603 //      n->add(c->info.createServentXML());
1604         return n;
1605 }
1606 // -----------------------------------
1607 static XML::Node *createChannelXML(ChanHitList *chl)
1608 {
1609         XML::Node *n = chl->info.createChannelXML();
1610         n->add(chl->createXML());
1611         n->add(chl->info.createTrackXML());
1612 //      n->add(chl->info.createServentXML());
1613         return n;
1614 }
1615 // -----------------------------------
1616 void Servent::handshakeXML()
1617 {
1618         int i;
1619                                 
1620
1621
1622         XML xml;
1623
1624         XML::Node *rn = new XML::Node("peercast");
1625         xml.setRoot(rn);
1626
1627
1628         rn->add(new XML::Node("servent uptime=\"%d\"",servMgr->getUptime()));
1629
1630         rn->add(new XML::Node("bandwidth out=\"%d\" in=\"%d\"",
1631                 stats.getPerSecond(Stats::BYTESOUT)-stats.getPerSecond(Stats::LOCALBYTESOUT),
1632                 stats.getPerSecond(Stats::BYTESIN)-stats.getPerSecond(Stats::LOCALBYTESIN)
1633                 ));
1634
1635         rn->add(new XML::Node("connections total=\"%d\" relays=\"%d\" direct=\"%d\"",servMgr->totalConnected(),servMgr->numStreams(Servent::T_RELAY,true),servMgr->numStreams(Servent::T_DIRECT,true)));
1636
1637         XML::Node *an = new XML::Node("channels_relayed total=\"%d\"",chanMgr->numChannels());
1638         rn->add(an);
1639
1640         Channel *c = chanMgr->channel;
1641         while (c)
1642         {
1643                 if (c->isActive())
1644                         an->add(createChannelXML(c));
1645                 c=c->next;
1646         }
1647
1648
1649         // add public channels
1650         {
1651                 XML::Node *fn = new XML::Node("channels_found total=\"%d\"",chanMgr->numHitLists());
1652                 rn->add(fn);
1653
1654                 ChanHitList *chl = chanMgr->hitlist;
1655                 while (chl)
1656                 {
1657                         if (chl->isUsed())
1658                                 fn->add(createChannelXML(chl));
1659                         chl = chl->next;
1660                 }
1661         }
1662
1663
1664 #if 0
1665         if (servMgr->isRoot)
1666         {
1667                 // add private channels
1668                 {
1669                         XML::Node *pn = new XML::Node("priv_channels");
1670                         rn->add(pn);
1671
1672                         ChanHitList *chl = chanMgr->hitlist;
1673                         while (chl)
1674                         {
1675                                 if (chl->isUsed())
1676                                         if (chl->info.isPrivate())
1677                                                 pn->add(createChannelXML(chl));
1678                                 chl = chl->next;
1679                         }
1680                 }
1681         }
1682 #endif
1683
1684         XML::Node *hc = new XML::Node("host_cache");
1685         for(i=0; i<ServMgr::MAX_HOSTCACHE; i++)
1686         {
1687                 ServHost *sh = &servMgr->hostCache[i];
1688                 if (sh->type != ServHost::T_NONE)
1689                 {
1690                         char ipstr[64];
1691                         sh->host.toStr(ipstr);
1692
1693                         hc->add(new XML::Node("host ip=\"%s\" type=\"%s\" time=\"%d\"",ipstr,ServHost::getTypeStr(sh->type),sh->time));
1694
1695                 }
1696         }
1697         rn->add(hc);
1698
1699
1700     sock->writeLine(HTTP_SC_OK);
1701         sock->writeLineF("%s %s",HTTP_HS_SERVER,PCX_AGENT);
1702     sock->writeLineF("%s %s",HTTP_HS_CONTENT,MIME_XML);
1703         sock->writeLine("Connection: close");
1704
1705     sock->writeLine("");
1706
1707         xml.write(*sock);
1708
1709 }
1710 // -----------------------------------
1711 void Servent::readICYHeader(HTTP &http, ChanInfo &info, char *pwd, size_t szPwd)
1712 {
1713         char *arg = http.getArgStr();
1714         if (!arg) return;
1715
1716         if (http.isHeader("x-audiocast-name") || http.isHeader("icy-name") || http.isHeader("ice-name"))
1717         {
1718                 info.name.set(arg,String::T_ASCII);
1719                 info.name.convertTo(String::T_UNICODE);
1720
1721         }else if (http.isHeader("x-audiocast-url") || http.isHeader("icy-url") || http.isHeader("ice-url"))
1722                 info.url.set(arg,String::T_ASCII);
1723         else if (http.isHeader("x-audiocast-bitrate") || (http.isHeader("icy-br")) || http.isHeader("ice-bitrate") || http.isHeader("icy-bitrate"))
1724                 info.bitrate = atoi(arg);
1725         else if (http.isHeader("x-audiocast-genre") || http.isHeader("ice-genre") || http.isHeader("icy-genre"))
1726         {
1727                 info.genre.set(arg,String::T_ASCII);
1728                 info.genre.convertTo(String::T_UNICODE);
1729
1730         }else if (http.isHeader("x-audiocast-description") || http.isHeader("ice-description"))
1731         {
1732                 info.desc.set(arg,String::T_ASCII);
1733                 info.desc.convertTo(String::T_UNICODE);
1734
1735         }else if (http.isHeader("Authorization"))
1736                 http.getAuthUserPass(NULL, pwd, 0, sizeof(pwd));
1737         else if (http.isHeader(PCX_HS_CHANNELID))
1738                 info.id.fromStr(arg);
1739         else if (http.isHeader("ice-password"))
1740         {
1741                 if (pwd)
1742                         if (strlen(arg) < 64)
1743                                 strcpy(pwd,arg);
1744         }else if (http.isHeader("content-type"))
1745         {
1746                 if (stristr(arg,MIME_OGG))
1747                         info.contentType = ChanInfo::T_OGG;
1748                 else if (stristr(arg,MIME_XOGG))
1749                         info.contentType = ChanInfo::T_OGG;
1750
1751                 else if (stristr(arg,MIME_MP3))
1752                         info.contentType = ChanInfo::T_MP3;
1753                 else if (stristr(arg,MIME_XMP3))
1754                         info.contentType = ChanInfo::T_MP3;
1755
1756                 else if (stristr(arg,MIME_WMA))
1757                         info.contentType = ChanInfo::T_WMA;
1758                 else if (stristr(arg,MIME_WMV))
1759                         info.contentType = ChanInfo::T_WMV;
1760                 else if (stristr(arg,MIME_ASX))
1761                         info.contentType = ChanInfo::T_ASX;
1762
1763                 else if (stristr(arg,MIME_NSV))
1764                         info.contentType = ChanInfo::T_NSV;
1765                 else if (stristr(arg,MIME_RAW))
1766                         info.contentType = ChanInfo::T_RAW;
1767
1768                 else if (stristr(arg,MIME_MMS))
1769                         info.srcProtocol = ChanInfo::SP_MMS;
1770                 else if (stristr(arg,MIME_XPCP))
1771                         info.srcProtocol = ChanInfo::SP_PCP;
1772                 else if (stristr(arg,MIME_XPEERCAST))
1773                         info.srcProtocol = ChanInfo::SP_PEERCAST;
1774
1775                 else if (stristr(arg,MIME_XSCPLS))
1776                         info.contentType = ChanInfo::T_PLS;
1777                 else if (stristr(arg,MIME_PLS))
1778                         info.contentType = ChanInfo::T_PLS;
1779                 else if (stristr(arg,MIME_XPLS))
1780                         info.contentType = ChanInfo::T_PLS;
1781                 else if (stristr(arg,MIME_M3U))
1782                         info.contentType = ChanInfo::T_PLS;
1783                 else if (stristr(arg,MIME_MPEGURL))
1784                         info.contentType = ChanInfo::T_PLS;
1785                 else if (stristr(arg,MIME_TEXT))
1786                         info.contentType = ChanInfo::T_PLS;
1787
1788
1789         }
1790
1791 }
1792
1793 // -----------------------------------
1794 void Servent::handshakeICY(Channel::SRC_TYPE type, bool isHTTP)
1795 {
1796         ChanInfo info;
1797
1798         HTTP http(*sock);
1799
1800         // default to mp3 for shoutcast DSP (doesn`t send content-type)
1801         if (type == Channel::SRC_SHOUTCAST)
1802                 info.contentType = ChanInfo::T_MP3;
1803
1804         while (http.nextHeader())
1805         {
1806                 LOG_DEBUG("ICY %s",http.cmdLine);
1807                 readICYHeader(http, info, loginPassword.cstr(), loginPassword.MAX_LEN);
1808         }
1809
1810
1811                 
1812         // check password before anything else, if needed
1813         if (!loginPassword.isSame(servMgr->password))
1814         {
1815                 if (!sock->host.isLocalhost() || !loginPassword.isEmpty())
1816                         throw HTTPException(HTTP_SC_UNAUTHORIZED,401);
1817         }
1818
1819                 
1820         // we need a valid IP address before we start
1821         servMgr->checkFirewall();
1822
1823
1824         // attach channel ID to name, channel ID is also encoded with IP address 
1825         // to help prevent channel hijacking. 
1826
1827
1828         info.id = chanMgr->broadcastID;
1829         info.id.encode(NULL,info.name.cstr(),loginMount.cstr(),info.bitrate);
1830
1831         LOG_DEBUG("Incoming source: %s : %s",info.name.cstr(),ChanInfo::getTypeStr(info.contentType));
1832
1833
1834         if (isHTTP)
1835                 sock->writeStringF("%s\n\n",HTTP_SC_OK);
1836         else
1837                 sock->writeLine("OK");
1838
1839         Channel *c = chanMgr->findChannelByID(info.id);
1840         if (c)
1841         {
1842                 LOG_CHANNEL("ICY channel already active, closing old one");
1843                 c->thread.shutdown();
1844         }
1845
1846
1847         info.comment = chanMgr->broadcastMsg;
1848         info.bcID = chanMgr->broadcastID;
1849
1850         c = chanMgr->createChannel(info,loginMount.cstr());
1851         if (!c)
1852                 throw HTTPException(HTTP_SC_UNAVAILABLE,503);
1853
1854         c->startICY(sock,type);
1855 }
1856
1857
1858 // -----------------------------------
1859 void Servent::handshakeLocalFile(const char *fn)
1860 {
1861         HTTP http(*sock);
1862         String fileName;
1863         
1864         if (servMgr->getModulePath) //JP-EX
1865         {
1866                 peercastApp->getDirectory();
1867                 fileName = servMgr->modulePath;
1868         }else
1869                 fileName = peercastApp->getPath();
1870         
1871         fileName.append(fn);
1872
1873         LOG_DEBUG("Writing HTML file: %s",fileName.cstr());
1874
1875         HTML html("",*sock);
1876
1877         char *args = strstr(fileName.cstr(),"?");
1878         if (args)
1879                 *args++=0;
1880
1881         if (fileName.contains(".htm"))
1882         {
1883                 html.writeOK(MIME_HTML);
1884                 html.writeTemplate(fileName.cstr(),args);
1885
1886         }else if (fileName.contains(".css"))
1887         {
1888                 html.writeOK(MIME_CSS);
1889                 html.writeRawFile(fileName.cstr());
1890         }else if (fileName.contains(".jpg"))
1891         {
1892                 html.writeOK(MIME_JPEG);
1893                 html.writeRawFile(fileName.cstr());
1894         }else if (fileName.contains(".gif"))
1895         {
1896                 html.writeOK(MIME_GIF);
1897                 html.writeRawFile(fileName.cstr());
1898         }else if (fileName.contains(".png"))
1899         {
1900                 html.writeOK(MIME_PNG);
1901                 html.writeRawFile(fileName.cstr());
1902         }
1903 }
1904
1905 // -----------------------------------
1906 void Servent::handshakeRemoteFile(const char *dirName)
1907 {
1908         ClientSocket *rsock = sys->createSocket();
1909         if (!rsock)
1910                 throw HTTPException(HTTP_SC_UNAVAILABLE,503);
1911
1912
1913         const char *hostName = "www.peercast.org";      // hardwired for "security"
1914
1915         Host host;
1916         host.fromStrName(hostName,80);
1917
1918
1919         rsock->open(host);
1920         rsock->connect();
1921
1922         HTTP rhttp(*rsock);
1923
1924         rhttp.writeLineF("GET /%s HTTP/1.0",dirName);
1925         rhttp.writeLineF("%s %s",HTTP_HS_HOST,hostName);
1926         rhttp.writeLineF("%s %s",HTTP_HS_CONNECTION,"close");
1927         rhttp.writeLineF("%s %s",HTTP_HS_ACCEPT,"*/*");
1928         rhttp.writeLine("");
1929
1930         String contentType;
1931         bool isTemplate = false;
1932         while (rhttp.nextHeader())
1933         {
1934                 char *arg = rhttp.getArgStr();
1935                 if (arg) 
1936                 {
1937                         if (rhttp.isHeader("content-type"))
1938                                 contentType = arg;
1939                 }
1940         }
1941
1942         MemoryStream mem(100*1024);
1943         while (!rsock->eof())
1944         {
1945                 int len=0;
1946                 char buf[4096];
1947                 len = rsock->readUpto(buf,sizeof(buf));
1948                 if (len==0)
1949                         break;
1950                 else
1951                         mem.write(buf,len);
1952
1953         }
1954         rsock->close();
1955
1956         int fileLen = mem.getPosition();
1957         mem.len = fileLen;
1958         mem.rewind();
1959
1960
1961         if (contentType.contains(MIME_HTML))
1962                 isTemplate = true;
1963
1964         sock->writeLine(HTTP_SC_OK);
1965         sock->writeLineF("%s %s",HTTP_HS_SERVER,PCX_AGENT);
1966         sock->writeLineF("%s %s",HTTP_HS_CACHE,"no-cache");
1967         sock->writeLineF("%s %s",HTTP_HS_CONNECTION,"close");
1968         sock->writeLineF("%s %s",HTTP_HS_CONTENT,contentType.cstr());
1969
1970         sock->writeLine("");
1971
1972         if (isTemplate)
1973         {
1974                 HTML html("",*sock);
1975                 html.readTemplate(mem,sock,0);
1976         }else
1977                 sock->write(mem.buf,fileLen);
1978
1979         mem.free2();
1980 }