OSDN Git Service

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