bool CWebServer::CallCGI(CWebClientSocket* pClient, CStringA& hdr, CStringA& body, CStringA& mime) { CString path = pClient->m_path, redir = path; if(!ToLocalPath(path, redir)) return false; CString ext = CPath(path).GetExtension().MakeLower(); CPath dir(path); dir.RemoveFileSpec(); CString cgi; if(!m_cgi.Lookup(ext, cgi) || !CPath(cgi).FileExists()) return false; HANDLE hProcess = GetCurrentProcess(); HANDLE hChildStdinRd, hChildStdinWr, hChildStdinWrDup = NULL; HANDLE hChildStdoutRd, hChildStdoutWr, hChildStdoutRdDup = NULL; SECURITY_ATTRIBUTES saAttr; ZeroMemory(&saAttr, sizeof(saAttr)); saAttr.nLength = sizeof(saAttr); saAttr.bInheritHandle = TRUE; if(CreatePipe(&hChildStdoutRd, &hChildStdoutWr, &saAttr, 0)) { BOOL fSuccess = DuplicateHandle(hProcess, hChildStdoutRd, hProcess, &hChildStdoutRdDup, 0, FALSE, DUPLICATE_SAME_ACCESS); CloseHandle(hChildStdoutRd); } if(CreatePipe(&hChildStdinRd, &hChildStdinWr, &saAttr, 0)) { BOOL fSuccess = DuplicateHandle(hProcess, hChildStdinWr, hProcess, &hChildStdinWrDup, 0, FALSE, DUPLICATE_SAME_ACCESS); CloseHandle(hChildStdinWr); } STARTUPINFO siStartInfo; ZeroMemory(&siStartInfo, sizeof(siStartInfo)); siStartInfo.cb = sizeof(siStartInfo); siStartInfo.hStdError = hChildStdoutWr; siStartInfo.hStdOutput = hChildStdoutWr; siStartInfo.hStdInput = hChildStdinRd; siStartInfo.dwFlags |= STARTF_USESTDHANDLES|STARTF_USESHOWWINDOW; siStartInfo.wShowWindow = SW_HIDE; PROCESS_INFORMATION piProcInfo; ZeroMemory(&piProcInfo, sizeof(piProcInfo)); CStringA envstr; if(LPVOID lpvEnv = GetEnvironmentStrings()) { CString str; CAtlList<CString> env; for(LPTSTR lpszVariable = (LPTSTR)lpvEnv; *lpszVariable; lpszVariable += _tcslen(lpszVariable)+1) if(lpszVariable != (LPTSTR)lpvEnv) env.AddTail(lpszVariable); env.AddTail(_T("GATEWAY_INTERFACE=CGI/1.1")); env.AddTail(_T("SERVER_SOFTWARE=Media Player Classic/6.4.x.y")); env.AddTail(_T("SERVER_PROTOCOL=") + pClient->m_ver); env.AddTail(_T("REQUEST_METHOD=") + pClient->m_cmd); env.AddTail(_T("PATH_INFO=") + redir); env.AddTail(_T("PATH_TRANSLATED=") + path); env.AddTail(_T("SCRIPT_NAME=") + redir); env.AddTail(_T("QUERY_STRING=") + pClient->m_query); if(pClient->m_hdrlines.Lookup(_T("content-type"), str)) env.AddTail(_T("CONTENT_TYPE=") + str); if(pClient->m_hdrlines.Lookup(_T("content-length"), str)) env.AddTail(_T("CONTENT_LENGTH=") + str); POSITION pos = pClient->m_hdrlines.GetStartPosition(); while(pos) { CString key = pClient->m_hdrlines.GetKeyAt(pos); CString value = pClient->m_hdrlines.GetNextValue(pos); key.Replace(_T("-"), _T("_")); key.MakeUpper(); env.AddTail(_T("HTTP_") + key + _T("=") + value); } CString name; UINT port; if(pClient->GetPeerName(name, port)) { str.Format(_T("%d"), port); env.AddTail(_T("REMOTE_ADDR=")+name); env.AddTail(_T("REMOTE_HOST=")+name); env.AddTail(_T("REMOTE_PORT=")+str); } if(pClient->GetSockName(name, port)) { str.Format(_T("%d"), port); env.AddTail(_T("SERVER_NAME=")+name); env.AddTail(_T("SERVER_PORT=")+str); } env.AddTail(_T("\0")); str = Implode(env, '\0'); envstr = CStringA(str, str.GetLength()); FreeEnvironmentStrings((LPTSTR)lpvEnv); } TCHAR* cmdln = new TCHAR[32768]; _sntprintf(cmdln, 32768, _T("\"%s\" \"%s\""), cgi, path); if(hChildStdinRd && hChildStdoutWr) if(CreateProcess( NULL, cmdln, NULL, NULL, TRUE, 0, envstr.GetLength() ? (LPVOID)(LPCSTR)envstr : NULL, dir, &siStartInfo, &piProcInfo)) { DWORD ThreadId; CreateThread(NULL, 0, KillCGI, (LPVOID)piProcInfo.hProcess, 0, &ThreadId); static const int BUFFSIZE = 1024; DWORD dwRead, dwWritten = 0; int i = 0, len = pClient->m_data.GetLength(); for(; i < len; i += dwWritten) if(!WriteFile(hChildStdinWrDup, (LPCSTR)pClient->m_data + i, min(len - i, BUFFSIZE), &dwWritten, NULL)) break; CloseHandle(hChildStdinWrDup); CloseHandle(hChildStdoutWr); body.Empty(); CStringA buff; while(i == len && ReadFile(hChildStdoutRdDup, buff.GetBuffer(BUFFSIZE), BUFFSIZE, &dwRead, NULL) && dwRead) { buff.ReleaseBufferSetLength(dwRead); body += buff; } int hdrend = body.Find("\r\n\r\n"); if(hdrend >= 0) { hdr = body.Left(hdrend+2); body = body.Mid(hdrend+4); } CloseHandle(hChildStdinRd); CloseHandle(hChildStdoutRdDup); CloseHandle(piProcInfo.hProcess); CloseHandle(piProcInfo.hThread); } else { body = _T("CGI Error"); } delete [] cmdln; return true; }
CWebServer::CWebServer(CMainFrame* pMainFrame, int nPort) : m_pMainFrame(pMainFrame) , m_nPort(nPort) { if(m_internalpages.IsEmpty()) { m_internalpages[_T("/")] = &CWebClientSocket::OnIndex; m_internalpages[_T("/index.html")] = &CWebClientSocket::OnIndex; m_internalpages[_T("/browser.html")] = &CWebClientSocket::OnBrowser; m_internalpages[_T("/controls.html")] = &CWebClientSocket::OnControls; m_internalpages[_T("/command.html")] = &CWebClientSocket::OnCommand; m_internalpages[_T("/status.html")] = &CWebClientSocket::OnStatus; m_internalpages[_T("/player.html")] = &CWebClientSocket::OnPlayer; m_internalpages[_T("/snapshot.jpg")] = &CWebClientSocket::OnSnapShotJpeg; m_internalpages[_T("/404.html")] = &CWebClientSocket::OnError404; m_internalpages[_T("/convres.html")] = &CWebClientSocket::OnConvRes; } if(m_downloads.IsEmpty()) { m_downloads[_T("/default.css")] = IDF_DEFAULT_CSS; m_downloads[_T("/vbg.gif")] = IDF_VBR_GIF; m_downloads[_T("/vbs.gif")] = IDF_VBS_GIF; m_downloads[_T("/sliderbar.gif")] = IDF_SLIDERBAR_GIF; m_downloads[_T("/slidergrip.gif")] = IDF_SLIDERGRIP_GIF; m_downloads[_T("/sliderback.gif")] = IDF_SLIDERBACK_GIF; m_downloads[_T("/1pix.gif")] = IDF_1PIX_GIF; m_downloads[_T("/headericon.png")] = IDF_HEADERICON_PNG; m_downloads[_T("/headerback.png")] = IDF_HEADERBACK_PNG; m_downloads[_T("/headerclose.png")] = IDF_HEADERCLOSE_PNG; m_downloads[_T("/leftside.png")] = IDF_LEFTSIDE_PNG; m_downloads[_T("/rightside.png")] = IDF_RIGHTSIDE_PNG; m_downloads[_T("/bottomside.png")] = IDF_BOTTOMSIDE_PNG; m_downloads[_T("/leftbottomside.png")] = IDF_LEFTBOTTOMSIDE_PNG; m_downloads[_T("/rightbottomside.png")] = IDF_RIGHTBOTTOMSIDE_PNG; m_downloads[_T("/seekbarleft.png")] = IDF_SEEKBARLEFT_PNG; m_downloads[_T("/seekbarmid.png")] = IDF_SEEKBARMID_PNG; m_downloads[_T("/seekbarright.png")] = IDF_SEEKBARRIGHT_PNG; m_downloads[_T("/seekbargrip.png")] = IDF_SEEKBARGRIP_PNG; m_downloads[_T("/logo.png")] = IDF_LOGO7; m_downloads[_T("/controlback.png")] = IDF_CONTROLBACK_PNG; m_downloads[_T("/controlbuttonplay.png")] = IDF_CONTROLBUTTONPLAY_PNG; m_downloads[_T("/controlbuttonpause.png")] = IDF_CONTROLBUTTONPAUSE_PNG; m_downloads[_T("/controlbuttonstop.png")] = IDF_CONTROLBUTTONSTOP_PNG; m_downloads[_T("/controlbuttonskipback.png")] = IDF_CONTROLBUTTONSKIPBACK_PNG; m_downloads[_T("/controlbuttondecrate.png")] = IDF_CONTROLBUTTONDECRATE_PNG; m_downloads[_T("/controlbuttonincrate.png")] = IDF_CONTROLBUTTONINCRATE_PNG; m_downloads[_T("/controlbuttonskipforward.png")] = IDF_CONTROLBUTTONSKIPFORWARD_PNG; m_downloads[_T("/controlbuttonstep.png")] = IDF_CONTROLBUTTONSTEP_PNG; m_downloads[_T("/controlvolumeon.png")] = IDF_CONTROLVOLUMEON_PNG; m_downloads[_T("/controlvolumeoff.png")] = IDF_CONTROLVOLUMEOFF_PNG; m_downloads[_T("/controlvolumebar.png")] = IDF_CONTROLVOLUMEBAR_PNG; m_downloads[_T("/controlvolumegrip.png")] = IDF_CONTROLVOLUMEGRIP_PNG; } CRegKey key; CString str(_T("MIME\\Database\\Content Type")); if(ERROR_SUCCESS == key.Open(HKEY_CLASSES_ROOT, str, KEY_READ)) { TCHAR buff[256]; DWORD len = countof(buff); for(int i = 0; ERROR_SUCCESS == key.EnumKey(i, buff, &len); i++, len = countof(buff)) { CRegKey mime; TCHAR ext[64]; ULONG len = countof(ext); if(ERROR_SUCCESS == mime.Open(HKEY_CLASSES_ROOT, str + _T("\\") + buff, KEY_READ) && ERROR_SUCCESS == mime.QueryStringValue(_T("Extension"), ext, &len)) m_mimes[CStringA(ext).MakeLower()] = CStringA(buff).MakeLower(); } } m_mimes[".html"] = "text/html"; m_mimes[".txt"] = "text/plain"; m_mimes[".css"] = "text/css"; m_mimes[".gif"] = "image/gif"; m_mimes[".jpeg"] = "image/jpeg"; m_mimes[".jpg"] = "image/jpeg"; m_mimes[".png"] = "image/png"; GetModuleFileName(AfxGetInstanceHandle(), str.GetBuffer(MAX_PATH), MAX_PATH); str.ReleaseBuffer(); m_webroot = CPath(str); m_webroot.RemoveFileSpec(); CString WebRoot = AfxGetAppSettings().WebRoot; WebRoot.Replace('/', '\\'); WebRoot.Trim(); CPath p(WebRoot); if(WebRoot.Find(_T(":\\")) < 0 && WebRoot.Find(_T("\\\\")) < 0) m_webroot.Append(WebRoot); else m_webroot = p; m_webroot.Canonicalize(); m_webroot.MakePretty(); if(!m_webroot.IsDirectory()) m_webroot = CPath(); CAtlList<CString> sl; Explode(AfxGetAppSettings().WebServerCGI, sl, ';'); POSITION pos = sl.GetHeadPosition(); while(pos) { CAtlList<CString> sl2; CString ext = Explode(sl.GetNext(pos), sl2, '=', 2); if(sl2.GetCount() < 2) continue; m_cgi[ext] = sl2.GetTail(); } m_ThreadId = 0; m_hThread = ::CreateThread(NULL, 0, StaticThreadProc, (LPVOID)this, 0, &m_ThreadId); }
void CWebServer::OnRequest(CWebClientSocket* pClient, CStringA& hdr, CStringA& body) { CPath p(pClient->m_path); CStringA ext = p.GetExtension().MakeLower(); CStringA mime; if(ext.IsEmpty()) mime = "text/html"; else m_mimes.Lookup(ext, mime); hdr = "HTTP/1.0 200 OK\r\n"; bool fHandled = false, fCGI = false; if(!fHandled && m_webroot.IsDirectory()) { CStringA tmphdr; fHandled = fCGI = CallCGI(pClient, tmphdr, body, mime); if(fHandled) { tmphdr.Replace("\r\n", "\n"); CAtlList<CStringA> hdrlines; ExplodeMin(tmphdr, hdrlines, '\n'); POSITION pos = hdrlines.GetHeadPosition(); while(pos) { POSITION cur = pos; CAtlList<CStringA> sl; CStringA key = Explode(hdrlines.GetNext(pos), sl, ':', 2); if(sl.GetCount() < 2) continue; key.Trim().MakeLower(); if(key == "content-type") {mime = sl.GetTail().Trim(); hdrlines.RemoveAt(cur);} else if(key == "content-length") {hdrlines.RemoveAt(cur);} } tmphdr = Implode(hdrlines, '\n'); tmphdr.Replace("\n", "\r\n"); hdr += tmphdr + "\r\n"; } } RequestHandler rh = NULL; if(!fHandled && m_internalpages.Lookup(pClient->m_path, rh) && (pClient->*rh)(hdr, body, mime)) { if(mime.IsEmpty()) mime = "text/html"; CString redir; if(pClient->m_get.Lookup(_T("redir"), redir) || pClient->m_post.Lookup(_T("redir"), redir)) { if(redir.IsEmpty()) redir = '/'; hdr = "HTTP/1.0 302 Found\r\n" "Location: " + CStringA(redir) + "\r\n"; return; } fHandled = true; } if(!fHandled && m_webroot.IsDirectory()) { fHandled = LoadPage(0, body, pClient->m_path); } UINT resid; CStringA res; if(!fHandled && m_downloads.Lookup(pClient->m_path, resid) && LoadResource(resid, res, _T("FILE"))) { if(mime.IsEmpty()) mime = "application/octet-stream"; memcpy(body.GetBufferSetLength(res.GetLength()), res.GetBuffer(), res.GetLength()); fHandled = true; } if(!fHandled) { hdr = mime == "text/html" ? "HTTP/1.0 301 Moved Permanently\r\n" "Location: /404.html\r\n" : "HTTP/1.0 404 Not Found\r\n"; return; } if(mime == "text/html" && !fCGI) { hdr += "Expires: Thu, 19 Nov 1981 08:52:00 GMT\r\n" "Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0\r\n" "Pragma: no-cache\r\n"; CStringA debug; if(AfxGetAppSettings().fWebServerPrintDebugInfo) { debug += "<hr>\r\n"; CString key, value; POSITION pos; pos = pClient->m_hdrlines.GetStartPosition(); while(pos) {pClient->m_hdrlines.GetNextAssoc(pos, key, value); debug += "HEADER[" + key + "] = " + value + "<br>\r\n";} debug += "cmd: " + pClient->m_cmd + "<br>\r\n"; debug += "path: " + pClient->m_path + "<br>\r\n"; debug += "ver: " + pClient->m_ver + "<br>\r\n"; pos = pClient->m_get.GetStartPosition(); while(pos) {pClient->m_get.GetNextAssoc(pos, key, value); debug += "GET[" + key + "] = " + value + "<br>\r\n";} pos = pClient->m_post.GetStartPosition(); while(pos) {pClient->m_post.GetNextAssoc(pos, key, value); debug += "POST[" + key + "] = " + value + "<br>\r\n";} pos = pClient->m_cookie.GetStartPosition(); while(pos) {pClient->m_cookie.GetNextAssoc(pos, key, value); debug += "COOKIE[" + key + "] = " + value + "<br>\r\n";} pos = pClient->m_request.GetStartPosition(); while(pos) {pClient->m_request.GetNextAssoc(pos, key, value); debug += "REQUEST[" + key + "] = " + value + "<br>\r\n";} } body.Replace("[path]", CStringA(pClient->m_path)); body.Replace("[indexpath]", "/index.html"); body.Replace("[commandpath]", "/command.html"); body.Replace("[browserpath]", "/browser.html"); body.Replace("[controlspath]", "/controls.html"); body.Replace("[wmcname]", "wm_command"); body.Replace("[setposcommand]", CMD_SETPOS); body.Replace("[setvolumecommand]", CMD_SETVOLUME); body.Replace("[debug]", debug); // TODO: add more general tags to replace } // gzip if(AfxGetAppSettings().fWebServerUseCompression && hdr.Find("Content-Encoding:") < 0) do { CString accept_encoding; pClient->m_hdrlines.Lookup(_T("accept-encoding"), accept_encoding); accept_encoding.MakeLower(); CAtlList<CString> sl; ExplodeMin(accept_encoding, sl, ','); if(!sl.Find(_T("gzip"))) break;; CHAR path[MAX_PATH], fn[MAX_PATH]; if(!GetTempPathA(MAX_PATH, path) || !GetTempFileNameA(path, "mpc_gz", 0, fn)) break; gzFile gf = gzopen(fn, "wb9"); if(!gf || gzwrite(gf, (LPVOID)(LPCSTR)body, body.GetLength()) != body.GetLength()) { if(gf) gzclose(gf); DeleteFileA(fn); break; } gzclose(gf); FILE* f = fopen(fn, "rb"); if(!f) {DeleteFileA(fn); break;} fseek(f, 0, 2); CHAR* s = body.GetBufferSetLength(ftell(f)); fseek(f, 0, 0); int len = fread(s, 1, body.GetLength(), f); ASSERT(len == body.GetLength()); fclose(f); DeleteFileA(fn); hdr += "Content-Encoding: gzip\r\n"; } while(0); CStringA content; content.Format( "Content-Type: %s\r\n" "Content-Length: %d\r\n", mime, body.GetLength()); hdr += content; }
bool CSubtitleDlDlg::Parse() { // Parse raw list isdb_movie m; isdb_subtitle sub; CAtlList<CStringA> sl; Explode(m_pTA->raw_list, sl, '\n'); CString str; POSITION pos = sl.GetHeadPosition(); while (pos) { str = sl.GetNext(pos); CStringA param = str.Left(max(0, str.Find('='))); CStringA value = str.Mid(str.Find('=') + 1); if (param == "ticket") { m_pTA->ticket = value; } else if (param == "movie") { m.reset(); Explode(value, m.titles, '|'); } else if (param == "subtitle") { sub.reset(); sub.id = atoi(value); } else if (param == "name") { sub.name = value; } else if (param == "discs") { sub.discs = atoi(value); } else if (param == "disc_no") { sub.disc_no = atoi(value); } else if (param == "format") { sub.format = value; } else if (param == "iso639_2") { sub.iso639_2 = value; } else if (param == "language") { sub.language = value; } else if (param == "nick") { sub.nick = value; } else if (param == "email") { sub.email = value; } else if (param == "" && value == "endsubtitle") { m.subs.AddTail(sub); } else if (param == "" && value == "endmovie") { m_pTA->raw_movies.AddTail(m); } else if (param == "" && value == "end") { break; } } // Parse movies pos = m_pTA->raw_movies.GetHeadPosition(); while (pos) { isdb_movie& raw_movie = m_pTA->raw_movies.GetNext(pos); isdb_movie_parsed p; CStringA titlesA = Implode(raw_movie.titles, '|'); titlesA.Replace("|", ", "); p.titles = UTF8To16(titlesA); p.checked = false; POSITION pos2 = raw_movie.subs.GetHeadPosition(); while (pos2) { const isdb_subtitle& s = raw_movie.subs.GetNext(pos2); p.name = UTF8To16(s.name); p.language = s.language; p.format = s.format; p.disc.Format(_T("%d/%d"), s.disc_no, s.discs); p.ptr = reinterpret_cast<DWORD_PTR>(&s); m_parsed_movies.Add(p); } } bool ret = true; if (m_parsed_movies.GetCount() == 0) { ret = false; } return ret; }