OSDN Git Service

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