📄 httpsvc.cxx
字号:
/*
* httpsvc.cxx
*
* Classes for service applications using HTTP as the user interface.
*
* Portable Windows Library
*
* Copyright (c) 1993-1998 Equivalence Pty. Ltd.
*
* The contents of this file are subject to the Mozilla Public License
* Version 1.0 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
* the License for the specific language governing rights and limitations
* under the License.
*
* The Original Code is Portable Windows Library.
*
* The Initial Developer of the Original Code is Equivalence Pty. Ltd.
*
* Portions are Copyright (C) 1993 Free Software Foundation, Inc.
* All Rights Reserved.
*
* Contributor(s): ______________________________________.
*
* $Log: httpsvc.cxx,v $
* Revision 1.50 1999/08/07 06:50:52 robertj
* Removed silly (and incorrect) warning.
*
* Revision 1.49 1999/04/24 05:16:26 robertj
* Fixed incorrect date in copyright notice.
*
* Revision 1.48 1998/11/30 05:37:46 robertj
* New directory structure
*
* Revision 1.47 1998/11/24 23:05:14 robertj
* Fixed extra *** in demo message
*
* Revision 1.46 1998/11/16 07:23:15 robertj
* More PPC GNU compatibility.
*
* Revision 1.45 1998/11/16 06:50:40 robertj
* Fixed PPC GNU compiler compatibility.
*
* Revision 1.44 1998/10/31 12:49:25 robertj
* Added read/write mutex to the HTTP space variable to avoid thread crashes.
*
* Revision 1.43 1998/10/29 11:58:52 robertj
* Added ability to configure the HTTP threads stack size.
*
* Revision 1.42 1998/10/29 11:31:57 robertj
* Fixed default URL to have lower case and spaceless product name.
* Increased HTTP stack size.
*
* Revision 1.41 1998/10/15 01:53:35 robertj
* GNU compatibility.
*
* Revision 1.40 1998/10/13 14:06:24 robertj
* Complete rewrite of memory leak detection code.
*
* Revision 1.39 1998/09/23 06:22:15 robertj
* Added open source copyright license.
*
* Revision 1.38 1998/09/18 01:47:23 robertj
* Fixed bug that made files with signature on first line fail on unix systems.
*
* Revision 1.37 1998/08/20 06:01:02 robertj
* Improved internationalisation, registrationpage override.
*
* Revision 1.36 1998/04/21 02:43:40 robertj
* Fixed conditional around wrong way for requiring signature on HTML files.
*
* Revision 1.35 1998/04/01 01:55:41 robertj
* Fixed bug for automatically including GIF file in HTTP name space.
*
* Revision 1.34 1998/03/23 03:21:40 robertj
* Fixed missing invalid case in register page.
*
* Revision 1.33 1998/03/20 03:18:15 robertj
* Added special classes for specific sepahores, PMutex and PSyncPoint.
*
* Revision 1.32 1998/03/17 10:14:39 robertj
* Rewrite of registration page to allow for HTML file override.
*
* Revision 1.31 1998/03/09 07:17:48 robertj
* Added IP peer/local number macros.
* Set GetPageGraphic reference to GIF file to be at lop level directory.
*
* Revision 1.30 1998/02/16 00:14:09 robertj
* Added ProductName and BuildDate macros.
* Major rewrite of application info passed in PHTTPServiceProcess constructor.
*
* Revision 1.29 1998/02/03 06:22:45 robertj
* Allowed PHTTPServiceString to be overridden by html file after ';'.
*
* Revision 1.28 1998/01/26 02:49:19 robertj
* GNU support.
*
* Revision 1.27 1998/01/26 02:12:14 robertj
* GNU warnings.
*
* Revision 1.26 1998/01/26 00:45:44 robertj
* Added option flags to ProcessMacros to automatically load from file etc.
* Assured that all service HTTP resources are overidable with file, using ; URL field.
* Added a number of extra #equival macros.
* Added "Pty. Ltd." to company name.
*
* Revision 1.25 1997/11/10 12:40:05 robertj
* Changed SustituteEquivalSequence so can override standard macros.
*
* Revision 1.24 1997/11/04 06:02:46 robertj
* Allowed help gif file name to overridable in PServiceHTML, so can be in subdirectory.
*
* Revision 1.23 1997/10/30 10:21:26 robertj
* Added ability to customise regisration text by application.
*
* Revision 1.22 1997/08/28 14:19:40 robertj
* Fixed bug where HTTP directory was not processed for macros.
*
* Revision 1.20 1997/08/20 08:59:58 craigs
* Changed macro handling to commonise #equival sequence
*
* Revision 1.19 1997/07/26 11:38:22 robertj
* Support for overridable pages in HTTP service applications.
*
* Revision 1.18 1997/07/08 13:11:44 robertj
* Added standard header and copyright macros to service HTML.
*
* Revision 1.17 1997/06/16 13:20:15 robertj
* Fixed bug where PHTTPThread crashes on exit.
*
* Revision 1.16 1997/05/16 12:07:21 robertj
* Added operating system and version to hidden fields on registration form.
*
* Revision 1.15 1997/03/02 03:40:59 robertj
* Added error logging to standard HTTP Service HTTP Server.
*
* Revision 1.14 1997/02/05 11:54:54 robertj
* Added support for order form page overridiing.
*
* Revision 1.13 1997/01/28 11:45:19 robertj
* .
*
* Revision 1.13 1997/01/27 10:22:37 robertj
* Numerous changes to support OEM versions of products.
*
* Revision 1.12 1997/01/03 06:33:23 robertj
* Removed slash from operating system version string, so says Windows NT rather than Windows/NT
*
* Revision 1.11 1996/11/16 10:50:26 robertj
* ??
*
* Revision 1.10 1996/11/04 03:58:23 robertj
* Changed to accept separate copyright and manufacturer strings.
*
* Revision 1.8 1996/10/08 13:08:29 robertj
* Changed standard graphic to use PHTML class.
*
* Revision 1.7 1996/09/14 13:09:33 robertj
* Major upgrade:
* rearranged sockets to help support IPX.
* added indirect channel class and moved all protocols to descend from it,
* separating the protocol from the low level byte transport.
*
* Revision 1.6 1996/08/25 09:39:00 robertj
* Prevented registration if no user etc entered.
*
* Revision 1.5 1996/08/19 13:39:55 robertj
* Fixed race condition in system restart logic.
*
* Revision 1.4 1996/08/08 13:36:39 robertj
* Fixed Registation page so no longer has static link, ie can be DLLed.
*
* Revision 1.3 1996/07/15 10:36:48 robertj
* Added registration info to bottom of order form so can be faxed to us.
*
* Revision 1.2 1996/06/28 13:21:30 robertj
* Fixed nesting problem in tables.
* Fixed PConfig page always restarting.
*
* Revision 1.1 1996/06/13 13:33:34 robertj
* Initial revision
*
*/
#ifdef __GNUC__
#pragma implementation "httpsvc.h"
#endif
#include <ptlib.h>
#include <ptclib/httpsvc.h>
#include <ptlib/sockets.h>
#define new PNEW
#define HOME_PAGE "http://www.equival.com"
#define EMAIL "equival@equival.com.au"
#define EQUIVALENCE "Equivalence Pty. Ltd."
PHTTPServiceProcess::PHTTPServiceProcess(const Info & inf)
: PServiceProcess(inf.manufacturerName, inf.productName,
inf.majorVersion, inf.minorVersion, inf.buildStatus, inf.buildNumber),
productKey(inf.productKey),
securedKeys(inf.securedKeyCount, inf.securedKeys),
signatureKey(inf.signatureKey),
compilationDate(inf.compilationDate),
manufacturersHomePage(inf.manufHomePage != NULL ? inf.manufHomePage : HOME_PAGE),
manufacturersEmail(inf.email != NULL ? inf.email : EMAIL),
productNameHTML(inf.productHTML != NULL ? inf.productHTML : inf.productName)
{
if (inf.gifHTML != NULL)
gifHTML = inf.gifHTML;
else {
gifHTML = psprintf("<img src=\"/%s\" alt=\"%s!\"", inf.gifFilename, inf.productName);
if (inf.gifWidth != 0 && inf.gifHeight != 0)
gifHTML += psprintf(" width=%i height=%i", inf.gifWidth, inf.gifHeight);
gifHTML += " align=absmiddle>";
}
if (inf.gifFilename != NULL)
httpNameSpace.AddResource(new PServiceHTTPFile(inf.gifFilename, GetFile().GetDirectory()+inf.gifFilename));
restartThread = NULL;
httpListeningSocket = NULL;
}
PHTTPServiceProcess::~PHTTPServiceProcess()
{
ShutdownListener();
}
PHTTPServiceProcess & PHTTPServiceProcess::Current()
{
PHTTPServiceProcess & process = (PHTTPServiceProcess &)PProcess::Current();
PAssert(process.IsDescendant(PHTTPServiceProcess::Class()), "Not a HTTP service!");
return process;
}
BOOL PHTTPServiceProcess::ListenForHTTP(WORD port, PINDEX stackSize)
{
if (httpListeningSocket != NULL &&
httpListeningSocket->GetPort() == port &&
httpListeningSocket->IsOpen())
return TRUE;
return ListenForHTTP(new PTCPSocket(port), stackSize);
}
BOOL PHTTPServiceProcess::ListenForHTTP(PSocket * listener, PINDEX stackSize)
{
if (httpListeningSocket != NULL)
ShutdownListener();
httpListeningSocket = PAssertNULL(listener);
if (!httpListeningSocket->Listen())
return FALSE;
if (stackSize > 1000)
new PHTTPServiceThread(stackSize, *this, *httpListeningSocket, httpNameSpace);
return TRUE;
}
void PHTTPServiceProcess::ShutdownListener()
{
if (httpListeningSocket == NULL)
return;
if (!httpListeningSocket->IsOpen())
return;
httpListeningSocket->Close();
httpThreadClosed.Wait();
delete httpListeningSocket;
httpListeningSocket = NULL;
}
PString PHTTPServiceProcess::GetCopyrightText()
{
PHTML html(PHTML::InBody);
html << "Copyright ©"
<< compilationDate.AsString("yyyy") << " by "
<< PHTML::HotLink(HOME_PAGE)
<< EQUIVALENCE
<< PHTML::HotLink()
<< ", "
<< PHTML::HotLink("mailto:" EMAIL)
<< EMAIL
<< PHTML::HotLink();
return html;
}
PString PHTTPServiceProcess::GetPageGraphic()
{
PHTML html(PHTML::InBody);
html << PHTML::TableStart()
<< PHTML::TableRow()
<< PHTML::TableData()
<< gifHTML
<< PHTML::TableData()
<< GetOSClass() << ' ' << GetOSName()
<< " Version " << GetVersion(TRUE)
<< PHTML::BreakLine()
<< "By "
<< PHTML::HotLink(manufacturersHomePage) << GetManufacturer() << PHTML::HotLink()
<< ", "
<< PHTML::HotLink("mailto:" + manufacturersEmail) << manufacturersEmail << PHTML::HotLink()
<< PHTML::TableEnd();
return html;
}
void PHTTPServiceProcess::GetPageHeader(PHTML & html)
{
GetPageHeader(html, GetName());
}
void PHTTPServiceProcess::GetPageHeader(PHTML & html, const PString & title)
{
html << PHTML::Title(title)
<< PHTML::Body()
<< GetPageGraphic();
}
void PHTTPServiceProcess::BeginRestartSystem()
{
if (restartThread == NULL) {
restartThread = PThread::Current();
OnConfigChanged();
}
}
void PHTTPServiceProcess::CompleteRestartSystem()
{
if (restartThread == NULL)
return;
if (restartThread != PThread::Current())
return;
httpNameSpace.StartWrite();
if (Initialise("Restart\tInitialisation"))
restartThread = NULL;
httpNameSpace.EndWrite();
if (restartThread != NULL)
Terminate();
}
void PHTTPServiceProcess::AddRegisteredText(PHTML &)
{
}
void PHTTPServiceProcess::AddUnregisteredText(PHTML &)
{
}
BOOL PHTTPServiceProcess::SubstituteEquivalSequence(PHTTPRequest &, const PString &, PString &)
{
return FALSE;
}
//////////////////////////////////////////////////////////////
PHTTPServiceThread::PHTTPServiceThread(PINDEX stackSize,
PHTTPServiceProcess & app,
PSocket & listeningSocket,
PHTTPSpace & http)
: PThread(stackSize, AutoDeleteThread),
process(app),
listener(listeningSocket),
httpNameSpace(http)
{
myStackSize = stackSize;
Resume();
}
void PHTTPServiceThread::Main()
{
if (!listener.IsOpen()) {
process.httpThreadClosed.Signal();
return;
}
// get a socket when a client connects
PHTTPServer server(httpNameSpace);
if (!server.Accept(listener)) {
if (server.GetErrorCode() != PChannel::Interrupted)
PSYSTEMLOG(Error, "Accept failed for HTTP: " << server.GetErrorText());
if (listener.IsOpen())
new PHTTPServiceThread(myStackSize, process, listener, httpNameSpace);
else
process.httpThreadClosed.Signal();
return;
}
new PHTTPServiceThread(myStackSize, process, listener, httpNameSpace);
// process requests
while (server.ProcessCommand())
;
// always close after the response has been sent
server.Close();
// if a restart was requested, then do it
process.CompleteRestartSystem();
}
//////////////////////////////////////////////////////////////
PConfigPage::PConfigPage(PHTTPServiceProcess & app,
const PString & title,
const PString & section,
const PHTTPAuthority & auth)
: PHTTPConfig(title, section, auth),
process(app)
{
}
PConfigPage::PConfigPage(PHTTPServiceProcess & app,
const PString & section,
const PHTTPAuthority & auth)
: PHTTPConfig(section.ToLower() + ".html", section, auth),
process(app)
{
}
void PConfigPage::OnLoadedText(PHTTPRequest & request, PString & text)
{
PServiceHTML::ProcessMacros(request, text,
baseURL.AsString(PURL::PathOnly).Mid(1),
PServiceHTML::LoadFromFile);
PHTTPConfig::OnLoadedText(request, text);
PServiceHTML::ProcessMacros(request, text, "", PServiceHTML::NoOptions);
}
BOOL PConfigPage::OnPOST(PHTTPServer & server,
const PURL & url,
const PMIMEInfo & info,
const PStringToString & data,
const PHTTPConnectionInfo & connectInfo)
{
PHTTPConfig::OnPOST(server, url, info, data, connectInfo);
return FALSE; // Make sure we break any persistent connections
}
BOOL PConfigPage::Post(PHTTPRequest & request,
const PStringToString & data,
PHTML & reply)
{
PServiceHTML::ProcessMacros(request, reply,
baseURL.AsString(PURL::PathOnly).Mid(1),
PServiceHTML::LoadFromFile);
PSYSTEMLOG(Debug3, "Post to " << request.url << '\n' << data);
BOOL retval = PHTTPConfig::Post(request, data, reply);
OnLoadedText(request, reply);
if (request.code == PHTTP::OK)
process.BeginRestartSystem();
return retval;
}
BOOL PConfigPage::GetExpirationDate(PTime & when)
{
// Well and truly before now....
when = PTime(0, 0, 0, 1, 1, 1980);
return TRUE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -