Пример #1
0
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;
}
Пример #2
0
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;
}
Пример #3
0
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;
}