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 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; }
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; }