1 // 2 // This file is part of the aMule Project. 3 // 4 // Copyright (c) 2003-2011 Angel Vidal ( kry@amule.org ) 5 // Copyright (c) 2003-2011 aMule Team ( admin@amule.org / http://www.amule.org ) 6 // Copyright (c) 2002-2011 Merkur ( devs@emule-project.net / http://www.emule-project.net ) 7 // 8 // Any parts of this program derived from the xMule, lMule or eMule project, 9 // or contributed by third-party developers are copyrighted by their 10 // respective authors. 11 // 12 // This program is free software; you can redistribute it and/or modify 13 // it under the terms of the GNU General Public License as published by 14 // the Free Software Foundation; either version 2 of the License, or 15 // (at your option) any later version. 16 // 17 // This program is distributed in the hope that it will be useful, 18 // but WITHOUT ANY WARRANTY; without even the implied warranty of 19 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 // GNU General Public License for more details. 21 // 22 // You should have received a copy of the GNU General Public License 23 // along with this program; if not, write to the Free Software 24 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 25 // 26 27 #ifndef WEBSERVER_H 28 #define WEBSERVER_H 29 30 #include "config.h" // Needed for ASIO_SOCKETS 31 32 #ifdef WITH_LIBPNG 33 #include <png.h> 34 #endif 35 36 #include "WebInterface.h" 37 #include <map> // Needed for std::map 38 #include <set> // Needed for std::set 39 #include "RLE.h" 40 #include "OtherStructs.h" 41 #include <ec/cpp/ECID.h> // Needed for CECID 42 43 #ifdef ENABLE_UPNP 44 # include "UPnPBase.h" 45 #endif 46 47 #include <wx/datetime.h> // For DownloadFile::wxtLastSeenComplete 48 49 #ifdef _MSC_VER 50 #define strncasecmp _strnicmp 51 #define snprintf sprintf_s 52 #define atoll _atoi64 53 #define strdup _strdup 54 #endif 55 56 class CWebSocket; 57 class CMD4Hash; 58 59 #define SESSION_TIMEOUT_SECS 300 // 5 minutes session expiration 60 #define SHORT_FILENAME_LENGTH 40 // Max size of file name. 61 62 wxString _SpecialChars(wxString str); 63 64 class CEC_PartFile_Tag; 65 class CEC_SharedFile_Tag; 66 class CEC_UpDownClient_Tag; 67 class CEC_SearchFile_Tag; 68 class CProgressImage; 69 class CEC_KadNode_Tag; 70 71 class CURLDecoder 72 { 73 public: 74 static wxString Decode(const wxString& url); 75 }; 76 77 class DownloadFile : public CECID { 78 public: 79 wxString sFileName; 80 uint8 nFileStatus; 81 uint64 lFileSize; 82 uint64 lFileCompleted; 83 uint64 lFileTransferred; 84 unsigned long lFileSpeed; 85 long lSourceCount; 86 long lNotCurrentSourceCount; 87 long lTransferringSourceCount; 88 long lSourceCountA4AF; 89 double fCompleted; 90 uint32 lFilePrio; 91 bool bFileAutoPriority; 92 wxString sFileHash; 93 wxString sED2kLink; 94 uint8 nCat; 95 wxDateTime wxtLastSeenComplete; 96 97 CMD4Hash nHash; 98 99 CProgressImage *m_Image; 100 PartFileEncoderData m_Encoder; 101 ArrayOfUInts16 m_PartInfo; 102 std::vector<Gap_Struct> m_ReqParts; 103 ArrayOfUInts64 m_Gaps; 104 105 // container require this 106 static class DownloadFileInfo *GetContainerInstance(); 107 DownloadFile(CEC_PartFile_Tag *); 108 void ProcessUpdate(CEC_PartFile_Tag *); ID()109 uint32 ID() { return ECID(); } 110 }; 111 112 class SharedFile : public CECID { 113 public: 114 wxString sFileName; 115 uint64 lFileSize; 116 uint64 nFileTransferred; 117 uint64 nFileAllTimeTransferred; 118 uint16 nFileRequests; 119 uint32 nFileAllTimeRequests; 120 uint16 nFileAccepts; 121 uint32 nFileAllTimeAccepts; 122 uint8 nFilePriority; 123 bool bFileAutoPriority; 124 wxString sFileHash; 125 wxString sED2kLink; 126 127 CMD4Hash nHash; 128 129 static class SharedFileInfo *GetContainerInstance(); 130 SharedFile(CEC_SharedFile_Tag *); 131 void ProcessUpdate(CEC_SharedFile_Tag *); ID()132 uint32 ID() { return ECID(); } 133 }; 134 135 class ServerEntry { 136 public: 137 wxString sServerName; 138 wxString sServerDescription; 139 uint32 nServerIP; 140 uint16 nServerPort; 141 wxString sServerIP; 142 int nServerUsers; 143 int nServerMaxUsers; 144 int nServerFiles; 145 146 static class ServersInfo *GetContainerInstance(); ID()147 uint32 ID() { return nServerIP; } 148 }; 149 150 // This is a client we are uploading to, not a file 151 class UploadFile : public CECID { 152 public: 153 wxString sUserName; 154 uint32 nTransferredUp; 155 uint32 nTransferredDown; 156 uint32 nSpeed; 157 uint32 nUploadFile; // ECID of shared file uploading to client 158 159 UploadFile(CEC_UpDownClient_Tag *tag); 160 161 static class UploadsInfo *GetContainerInstance(); ID()162 uint32 ID() { return ECID(); } 163 }; 164 165 class SearchFile : public CECID { 166 public: 167 wxString sFileName; 168 uint64 lFileSize; 169 CMD4Hash nHash; 170 wxString sHash; 171 long lSourceCount; 172 bool bPresent; 173 174 SearchFile(CEC_SearchFile_Tag *); 175 176 void ProcessUpdate(CEC_SearchFile_Tag *); 177 static class SearchInfo *GetContainerInstance(); ID()178 uint32 ID() { return ECID(); } 179 }; 180 181 182 /*! 183 * T - type of items in container 184 */ 185 template <class T> 186 class ItemsContainer { 187 protected: 188 CamulewebApp *m_webApp; 189 std::list<T> m_items; 190 191 EraseAll()192 void EraseAll() 193 { 194 m_items.erase(m_items.begin(), m_items.end()); 195 } 196 public: ItemsContainer(CamulewebApp * webApp)197 ItemsContainer(CamulewebApp *webApp) 198 { 199 m_webApp = webApp; 200 } ~ItemsContainer()201 virtual ~ItemsContainer() { } 202 203 ItemCount()204 int ItemCount() 205 { 206 return m_items.size(); 207 } 208 209 AddItem(T & item)210 T *AddItem(T &item) 211 { 212 m_items.push_back(item); 213 T *real_ptr = &(m_items.back()); 214 return real_ptr; 215 } 216 217 /*! 218 * Re-query server: refresh all dataset 219 */ 220 virtual bool ReQuery() = 0; 221 222 typedef typename std::list<T>::iterator ItemIterator; GetBeginIterator()223 ItemIterator GetBeginIterator() 224 { 225 return m_items.begin(); 226 } GetEndIterator()227 ItemIterator GetEndIterator() 228 { 229 return m_items.end(); 230 } 231 }; 232 233 /*! 234 * T - type of items in container 235 * I - type of item ID 236 * G - type of tag in EC 237 */ 238 template <class T, class G, class I> 239 class UpdatableItemsContainer : public ItemsContainer<T> { 240 protected: 241 // need duplicate list with a map, so check "do we already have" 242 // will take O(log(n)) instead of O(n) 243 // map will contain pointers to items in list 244 std::map<I, T *> m_items_hash; 245 public: UpdatableItemsContainer(CamulewebApp * webApp)246 UpdatableItemsContainer(CamulewebApp *webApp) : ItemsContainer<T>(webApp) 247 { 248 } 249 AddItem(T & item)250 T *AddItem(T &item) 251 { 252 T *real_ptr = ItemsContainer<T>::AddItem(item); 253 m_items_hash[item.ID()] = real_ptr; 254 return real_ptr; 255 } 256 GetByID(I id)257 T *GetByID(I id) 258 { 259 // avoid creating nodes 260 return m_items_hash.count(id) ? m_items_hash[id] : NULL; 261 } 262 GetByHash(const CMD4Hash & fileHash)263 T * GetByHash(const CMD4Hash &fileHash) 264 { 265 T * ret = 0; 266 for (typename std::map<I, T *>::iterator it = m_items_hash.begin(); it != m_items_hash.end(); ++it) { 267 if (it->second->nHash == fileHash) { 268 ret = it->second; 269 break; 270 } 271 } 272 return ret; 273 } 274 275 /*! 276 * Process answer of update request, create list of new items for 277 * full request later. Also remove items that no longer exist in core 278 */ ProcessUpdate(const CECPacket * reply,CECPacket * full_req,int req_type)279 void ProcessUpdate(const CECPacket *reply, CECPacket *full_req, int req_type) 280 { 281 std::set<I> core_files; 282 for (CECPacket::const_iterator it = reply->begin(); it != reply->end(); ++it) { 283 G *tag = (G *) & *it; 284 285 core_files.insert(tag->ID()); 286 if ( m_items_hash.count(tag->ID()) ) { 287 T *item = m_items_hash[tag->ID()]; 288 item->ProcessUpdate(tag); 289 } else { 290 full_req->AddTag(CECTag(req_type, tag->ID())); 291 } 292 } 293 std::list<I> del_ids; 294 for(typename std::list<T>::iterator j = this->m_items.begin(); j != this->m_items.end(); ++j) { 295 if ( core_files.count(j->ID()) == 0 ) { 296 // item may contain data that need to be freed externally, before 297 // dtor is called and memory freed 298 299 T *real_ptr = &*j; 300 this->ItemDeleted(real_ptr); 301 302 del_ids.push_back(j->ID()); 303 } 304 } 305 for(typename std::list<I>::iterator j = del_ids.begin(); j != del_ids.end(); ++j) { 306 m_items_hash.erase(*j); 307 for(typename std::list<T>::iterator k = this->m_items.begin(); k != this->m_items.end(); ++k) { 308 if ( *j == k->ID() ) { 309 this->m_items.erase(k); 310 break; 311 } 312 } 313 } 314 } 315 ProcessFull(const CECPacket * reply)316 void ProcessFull(const CECPacket *reply) 317 { 318 for (CECPacket::const_iterator it = reply->begin(); it != reply->end(); ++it) { 319 G *tag = (G *) & *it; 320 // initialize item data from EC tag 321 T item(tag); 322 T *real_ptr = AddItem(item); 323 // initialize any external data that may depend on this item 324 this->ItemInserted(real_ptr); 325 } 326 } 327 DoRequery(int cmd,int tag)328 bool DoRequery(int cmd, int tag) 329 { 330 CECPacket req_sts(cmd, EC_DETAIL_UPDATE); 331 332 // 333 // Phase 1: request status 334 const CECPacket *reply = this->m_webApp->SendRecvMsg_v2(&req_sts); 335 if ( !reply ) { 336 return false; 337 } 338 339 // 340 // Phase 2: update status, mark new files for subsequent query 341 CECPacket req_full(cmd); 342 343 ProcessUpdate(reply, &req_full, tag); 344 345 delete reply; 346 347 // Phase 3: request full info about files we don't have yet 348 if ( req_full.HasChildTags() ) { 349 reply = this->m_webApp->SendRecvMsg_v2(&req_full); 350 if ( !reply ) { 351 return false; 352 } 353 ProcessFull(reply); 354 delete reply; 355 } 356 return true; 357 } 358 ItemDeleted(T *)359 virtual void ItemDeleted(T *) { } ItemInserted(T *)360 virtual void ItemInserted(T *) { } 361 }; 362 363 class UploadsInfo : public ItemsContainer<UploadFile> { 364 public: 365 // can be only one instance. 366 static UploadsInfo *m_This; 367 368 UploadsInfo(CamulewebApp *webApp); 369 370 virtual bool ReQuery(); 371 }; 372 373 class ServersInfo : public ItemsContainer<ServerEntry> { 374 public: 375 // can be only one instance. 376 static ServersInfo *m_This; 377 378 ServersInfo(CamulewebApp *webApp); 379 380 virtual bool ReQuery(); 381 382 }; 383 384 385 class SharedFileInfo : public UpdatableItemsContainer<SharedFile, CEC_SharedFile_Tag, uint32> { 386 public: 387 // can be only one instance. 388 static SharedFileInfo *m_This; 389 390 SharedFileInfo(CamulewebApp *webApp); 391 392 virtual bool ReQuery(); 393 394 }; 395 396 class SearchInfo : public UpdatableItemsContainer<SearchFile, CEC_SearchFile_Tag, uint32> { 397 public: 398 static SearchInfo *m_This; 399 400 SearchInfo(CamulewebApp *webApp); 401 402 virtual bool ReQuery(); 403 404 }; 405 406 407 class CImageLib; 408 class DownloadFileInfo : public UpdatableItemsContainer<DownloadFile, CEC_PartFile_Tag, uint32> { 409 CImageLib *m_ImageLib; 410 411 // parameters of progress images 412 wxString m_Template; 413 int m_width, m_height; 414 public: 415 // can be only one instance. 416 static DownloadFileInfo *m_This; 417 418 DownloadFileInfo(CamulewebApp *webApp, CImageLib *imlib); 419 420 void LoadImageParams(wxString &tpl, int width, int height); 421 422 virtual bool ReQuery(); 423 424 // container requirements 425 void ItemInserted(DownloadFile *item); 426 void ItemDeleted(DownloadFile *item); 427 }; 428 429 class CAnyImage { 430 protected: 431 unsigned char *m_data; 432 433 int m_width, m_height; 434 wxString m_name; 435 436 int m_size, m_alloc_size; 437 wxString m_Http; 438 439 void Realloc(int size); 440 441 void SetHttpType(wxString ext); 442 public: 443 CAnyImage(int size); 444 CAnyImage(int width, int height); 445 virtual ~CAnyImage(); 446 GetHTTP()447 const wxString& GetHTTP() const { return m_Http; } 448 449 virtual unsigned char *RequestData(int &size); 450 }; 451 452 class CFileImage : public virtual CAnyImage { 453 public: 454 CFileImage(const wxString& name); 455 OpenOk()456 bool OpenOk() { return m_size != 0; } 457 }; 458 459 class CImage3D_Modifiers { 460 unsigned char *m_modifiers; 461 int m_width; 462 public: 463 CImage3D_Modifiers(int width); 464 ~CImage3D_Modifiers(); 465 466 unsigned char operator[](int i) 467 { 468 return (i < m_width) ? m_modifiers[i] : 0; 469 } 470 }; 471 472 class CProgressImage : public virtual CAnyImage { 473 protected: 474 DownloadFile *m_file; 475 476 wxString m_template; 477 478 // 479 // Turn list of gaps, partstatus into array of color strips 480 typedef struct Color_Gap_Struct : public Gap_Struct { 481 uint32 color; 482 } Color_Gap_Struct; 483 484 // result of rendering - single line 485 uint32 *m_ColorLine; 486 void CreateSpan(); 487 public: 488 CProgressImage(int w, int h, wxString &tmpl, DownloadFile *file); 489 490 ~CProgressImage(); 491 Name()492 const wxString &Name() { return m_name; } 493 494 virtual wxString GetHTML() = 0; 495 }; 496 497 #ifdef WITH_LIBPNG 498 499 // 500 // Dynamic png image generation 501 // 502 class CDynPngImage : public virtual CAnyImage { 503 504 public: 505 CDynPngImage(int w, int h); 506 ~CDynPngImage(); 507 508 virtual unsigned char *RequestData(int &size); 509 510 protected: 511 png_bytep m_img_data; 512 png_bytep *m_row_ptrs; 513 514 static void png_write_fn(png_structp png_ptr, png_bytep data, png_size_t length); 515 516 }; 517 518 // 519 // Dynamic png image generation from gap info 520 class CDynProgressImage : public virtual CProgressImage, public virtual CDynPngImage { 521 CImage3D_Modifiers m_modifiers; 522 523 void DrawImage(); 524 public: 525 CDynProgressImage(int w, int h, wxString &tmpl, DownloadFile *file); 526 ~CDynProgressImage(); 527 528 virtual unsigned char *RequestData(int &size); 529 virtual wxString GetHTML(); 530 }; 531 532 #else 533 534 535 // 536 // Fallback to original implementation 537 class CDynProgressImage : public virtual CProgressImage { 538 public: 539 CDynProgressImage(int w, int h, wxString &tmpl, DownloadFile *file); 540 541 virtual wxString GetHTML(); 542 }; 543 544 #endif 545 546 // 547 // Representing statistical sample for some parameter. Circular buffer 548 // inside to avoid rellocations 549 // 550 class CStatsData { 551 uint32 *m_data; 552 uint32 m_max_value; 553 int m_size; 554 int m_start_index, m_end_index, m_curr_index; 555 public: 556 CStatsData(int size); 557 ~CStatsData(); 558 Size()559 int Size() const { return m_size; } Max()560 uint32 Max() const { return m_max_value; } 561 uint32 GetFirst(); 562 uint32 GetNext(); 563 564 void PushSample(uint32 sample); 565 }; 566 567 class CStatsCollection { 568 CStatsData *m_down_speed, *m_up_speed, 569 *m_conn_number, *m_kad_count; 570 571 CamulewebApp *m_iface; 572 double m_LastTimeStamp; 573 int m_size; 574 public: 575 CStatsCollection(int size, CamulewebApp *iface); 576 ~CStatsCollection(); 577 DownloadSpeed()578 CStatsData *DownloadSpeed() { return m_down_speed; } UploadSpeed()579 CStatsData *UploadSpeed() { return m_up_speed; } ConnCount()580 CStatsData *ConnCount() { return m_conn_number; } KadCount()581 CStatsData *KadCount() { return m_kad_count; } 582 583 void ReQuery(); 584 }; 585 586 #ifdef WITH_LIBPNG 587 588 // 589 // This gonna to represent data used to "write" numbers on 590 // dynamically generated images. 591 // Easiest way to represt numbers: 7-segments model 592 // 593 class CNumImageMask { 594 png_bytep *m_row_mask_ptrs; 595 int m_width, m_height; 596 int m_v_segsize, m_h_segsize; 597 598 // mask generation 599 void DrawHorzLine(int off); 600 void DrawVertLine(int offx, int offy); 601 void DrawSegment(int id); 602 603 static const int m_num_to_7_decode[10]; 604 public: 605 CNumImageMask(int number, int width, int height); 606 ~CNumImageMask(); 607 608 void Apply(png_bytep *image, int offx, int offy); 609 }; 610 611 class CDynStatisticImage : public virtual CDynPngImage { 612 CStatsData *m_data; 613 614 // size of "font" of imprinted numbers 615 int m_num_font_w_size, m_num_font_h_size; 616 617 int m_left_margin, m_bottom_margin; 618 int m_y_axis_size; 619 620 // hope nobody needs "define" for 10 ! 621 CNumImageMask *m_digits[10]; 622 623 // indicates whether data should be divided on 1024 before 624 // drawing graph. 625 bool m_scale1024; 626 627 // 628 // Prepared background 629 // 630 png_bytep m_background; 631 png_bytep *m_row_bg_ptrs; 632 633 void DrawImage(); 634 public: 635 CDynStatisticImage(int height, bool scale1024, CStatsData *data); 636 ~CDynStatisticImage(); 637 638 virtual unsigned char *RequestData(int &size); 639 virtual wxString GetHTML(); 640 }; 641 642 #endif 643 644 class CImageLib { 645 typedef std::map<wxString, CAnyImage *> ImageMap; 646 ImageMap m_image_map; 647 wxString m_image_dir; 648 public: 649 CImageLib(wxString image_dir); 650 ~CImageLib(); 651 652 CAnyImage *GetImage(const wxString &name); 653 void AddImage(CAnyImage *img, const wxString &name); 654 void RemoveImage(const wxString &name); 655 }; 656 657 class CParsedUrl { 658 wxString m_path, m_file; 659 std::map<wxString, wxString> m_params; 660 public: 661 CParsedUrl(const wxString &url); 662 Path()663 const wxString &Path() { return m_path; } File()664 const wxString &File() { return m_file; } 665 Param(const wxString & key)666 const wxString &Param(const wxString &key) 667 { 668 return m_params[key]; 669 } 670 671 void ConvertParams(std::map<std::string, std::string> &); 672 }; 673 674 // Changing this to a typedef struct{} makes egcs compiler do it all wrong and crash on run 675 struct ThreadData { 676 CParsedUrl parsedURL; 677 wxString sURL; 678 int SessionID; 679 CWebSocket *pSocket; 680 }; 681 682 #ifndef ASIO_SOCKETS 683 enum { 684 // Socket handlers 685 ID_WEBLISTENSOCKET_EVENT = wxID_HIGHEST+123, // random safe ID 686 ID_WEBCLIENTSOCKET_EVENT, 687 }; 688 #endif 689 690 #ifdef ENABLE_UPNP 691 class CUPnPControlPoint; 692 class CUPnPPortMapping; 693 #endif 694 695 class CWebLibSocketServer : public CLibSocketServer { 696 public: 697 CWebLibSocketServer(const class amuleIPV4Address& adr, int flags, CWebServerBase * webServerBase); 698 699 virtual void OnAccept(); 700 private: 701 CWebServerBase * m_webServerBase; 702 }; 703 704 class CWebServerBase : public wxEvtHandler { 705 protected: 706 CWebLibSocketServer *m_webserver_socket; 707 708 ServersInfo m_ServersInfo; 709 SharedFileInfo m_SharedFileInfo; 710 DownloadFileInfo m_DownloadFileInfo; 711 UploadsInfo m_UploadsInfo; 712 SearchInfo m_SearchInfo; 713 714 CStatsCollection m_Stats; 715 716 CImageLib m_ImageLib; 717 718 virtual void ProcessURL(ThreadData) = 0; 719 virtual void ProcessImgFileReq(ThreadData) = 0; 720 721 int GzipCompress(Bytef *dest, uLongf *destLen, 722 const Bytef *source, uLong sourceLen, int level); 723 724 friend class CWebSocket; 725 friend class CPhPLibContext; 726 727 bool m_upnpEnabled; 728 int m_upnpTCPPort; 729 #ifdef ENABLE_UPNP 730 CUPnPControlPoint *m_upnp; 731 std::vector<CUPnPPortMapping> m_upnpMappings; 732 #endif 733 #ifdef ASIO_SOCKETS 734 CAsioService *m_AsioService; 735 #else 736 void OnWebSocketServerEvent(wxSocketEvent& event); 737 void OnWebSocketEvent(wxSocketEvent& event); 738 DECLARE_EVENT_TABLE(); 739 #endif 740 public: 741 CWebServerBase(CamulewebApp *webApp, const wxString& templateDir); 742 virtual ~CWebServerBase(); 743 744 void Send_Discard_V2_Request(CECPacket *request); 745 746 void StartServer(); 747 void StopServer(); 748 749 void Print(const wxString &s); 750 751 long GetWSPrefs(); 752 753 // 754 // Command interface 755 // 756 void Send_ReloadSharedFile_Cmd(); 757 758 void Send_SharedFile_Cmd(wxString file_hash, wxString cmd, uint32 opt_arg = 0); 759 void Send_DownloadFile_Cmd(wxString file_hash, wxString cmd, uint32 opt_arg = 0); 760 761 void Send_DownloadSearchFile_Cmd(wxString file_hash, uint8 cat); 762 763 void Send_Server_Cmd(uint32 ip, uint16 port, wxString cmd); 764 void Send_AddServer_Cmd(wxString addr, wxString port, wxString name); 765 766 void Send_Search_Cmd(wxString search, wxString extention, wxString type, 767 EC_SEARCH_TYPE search_type, uint32 avail, uint32 min_size, uint32 max_size); 768 769 bool Send_DownloadEd2k_Cmd(wxString link, uint8 cat); 770 Reload_Stats()771 void Reload_Stats() 772 { 773 m_Stats.ReQuery(); 774 } 775 776 CamulewebApp *webInterface; 777 778 }; 779 780 class CSession { 781 public: 782 bool m_loggedin; 783 time_t m_last_access; 784 std::map<std::string, std::string> m_vars, m_get_vars; 785 786 void LoadVars(CParsedUrl &url); 787 }; 788 789 /* 790 * Script based webserver 791 */ 792 class CScriptWebServer : public CWebServerBase { 793 wxString m_wwwroot; 794 wxString m_index; 795 796 char *ProcessHtmlRequest(const char *filename, long &size); 797 char *ProcessPhpRequest(const char *filename, CSession *sess, long &size); 798 799 char *GetErrorPage(const char *message, long &size); 800 char *Get_404_Page(long &size); 801 802 std::map<int, CSession> m_sessions; 803 804 CSession *CheckLoggedin(ThreadData &); 805 protected: 806 virtual void ProcessURL(ThreadData); 807 virtual void ProcessImgFileReq(ThreadData); 808 public: 809 CScriptWebServer(CamulewebApp *webApp, const wxString& templateDir); 810 ~CScriptWebServer(); 811 812 }; 813 814 class CNoTemplateWebServer : public CScriptWebServer { 815 protected: 816 virtual void ProcessURL(ThreadData); 817 public: 818 CNoTemplateWebServer(CamulewebApp *webApp); 819 ~CNoTemplateWebServer(); 820 }; 821 822 #endif // WEBSERVER_H 823 // File_checked_for_headers 824