📄 httpform.cxx
字号:
/*
* httpform.cxx
*
* Forms using HTTP user interface.
*
* Portable Windows Library
*
* Copyright (c) 1993-2002 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.
*
* Contributor(s): ______________________________________.
*
* $Log: httpform.cxx,v $
* Revision 1.2 2007/06/17 02:49:35 joegenbaclor
* Introduced Global lock to PHTTPConfig
*
* Revision 1.1 2006/06/29 04:18:02 joegenbaclor
* *** empty log message ***
*
* Revision 1.49 2004/04/24 06:27:56 rjongbloed
* Fixed GCC 3.4.0 warnings about PAssertNULL and improved recoverability on
* NULL pointer usage in various bits of code.
*
* Revision 1.48 2004/04/03 08:22:20 csoutheren
* Remove pseudo-RTTI and replaced with real RTTI
*
* Revision 1.47 2003/03/24 04:31:03 robertj
* Added function to set and get strings from PConfig in correct format for
* use with HTTP form array contsructs.
*
* Revision 1.46 2002/11/22 06:20:26 robertj
* Added extra space around data entry fields.
* Added borders around arrays and composite fields.
* Added multi-line data entry for HTTPStringField > 128 characters.
*
* Revision 1.45 2002/11/06 22:47:25 robertj
* Fixed header comment (copyright etc)
*
* Revision 1.44 2002/10/10 04:43:44 robertj
* VxWorks port, thanks Martijn Roest
*
* Revision 1.43 2002/07/17 08:44:58 robertj
* Added links back to page and home page on accepted data html.
* Fixed display of validation error text if page not accepted.
*
* Revision 1.42 2001/10/10 08:07:48 robertj
* Fixed large memory leak of strings when doing POST to a form.
*
* Revision 1.41 2001/05/16 06:03:14 craigs
* Changed to allow access to absolute registry paths from within subforms
*
* Revision 1.40 2001/02/07 04:44:47 robertj
* Added ability to use check box to add/delete fields from arrays.
*
* Revision 1.39 2001/01/08 04:13:23 robertj
* Fixed bug with skipping every second option in determining the selected
* option in a SELECT field. No longer requires a </option> to work.
*
* Revision 1.38 2000/12/20 02:23:39 robertj
* Fixed variable array size value (caused extra blank entry ever commit).
*
* Revision 1.37 2000/12/18 12:13:08 robertj
* Fixed bug in auto-generated HTML in fixed size arrays, should not have add/delete box.
*
* Revision 1.36 2000/12/18 11:41:01 robertj
* Fixed bug in auto-generated HTML in non-array composite fields
*
* Revision 1.35 2000/12/18 07:14:30 robertj
* Added ability to have fixed length array fields.
* Fixed regular expressions so can have single '-' in field name.
* Fixed use of non-array subforprefix based compsite fields.
*
* Revision 1.34 2000/12/12 07:21:35 robertj
* Added ability to expand fields based on regex into repeated chunks of HTML.
*
* Revision 1.33 2000/11/02 21:55:28 craigs
* Added extra constructor
*
* Revision 1.32 2000/09/05 09:52:24 robertj
* Fixed bug in HTTP form updating SELECT fields from registry.
*
* Revision 1.31 2000/06/19 11:35:01 robertj
* Fixed bug in setting current value of options in select form fields.
*
* Revision 1.30 1999/02/10 13:19:45 robertj
* Fixed PConfig update problem when POSTing to the form. Especiall with arrays.
*
* Revision 1.29 1998/11/30 04:51:57 robertj
* New directory structure
*
* Revision 1.28 1998/11/14 11:11:06 robertj
* PPC GNU compiler compatibility.
*
* Revision 1.27 1998/10/01 09:05:11 robertj
* Fixed bug in nested composite field names, array indexes not being set correctly.
*
* Revision 1.26 1998/09/23 06:22:11 robertj
* Added open source copyright license.
*
* Revision 1.25 1998/08/20 05:51:06 robertj
* Fixed bug where substitutions did not always occur if near end of macro block.
* Improved internationalisation. Allow HTML override of strings in macros.
*
* Revision 1.24 1998/08/09 11:25:51 robertj
* GNU C++ warning removal.
*
* Revision 1.23 1998/08/09 10:35:11 robertj
* Changed array control so can have language override.
*
* Revision 1.22 1998/07/24 06:56:05 robertj
* Fixed case significance problem in HTTP forms.
* Improved detection of VALUE= fields with and without quotes.
*
* Revision 1.21 1998/03/20 03:16:43 robertj
* Fixed bug in beaing able to reset a check box field.
*
* Revision 1.20 1998/02/03 06:26:09 robertj
* Fixed propagation of inital values in arrays subfields.
* Fixed problem where hidden fields were being relaced with default values from PHTTPForm.
*
* Revision 1.19 1998/01/26 02:49:17 robertj
* GNU support.
*
* Revision 1.18 1998/01/26 01:51:37 robertj
* Fixed uninitialised variable.
*
* Revision 1.17 1998/01/26 00:25:25 robertj
* Major rewrite of HTTP forms management.
*
* Revision 1.16 1997/12/18 05:06:51 robertj
* Added missing braces to kill GNU compiler warning.
*
* Revision 1.15 1997/10/10 10:43:43 robertj
* Fixed bug in password encryption, missing string terminator.
*
* Revision 1.14 1997/08/28 12:48:29 robertj
* Changed array fields to allow for reordering.
*
* Revision 1.13 1997/08/21 12:44:10 robertj
* Fixed bug in HTTP form array size field.
* Fixed bug where section list was only replacing first instance of macro.
*
* Revision 1.12 1997/08/09 07:46:52 robertj
* Fixed problems with value of SELECT fields in form
*
* Revision 1.11 1997/08/04 10:41:13 robertj
* Fixed bug in new section list page for names with special characters in them.
*
* Revision 1.10 1997/07/26 11:38:20 robertj
* Support for overridable pages in HTTP service applications.
*
* Revision 1.9 1997/07/14 11:49:51 robertj
* Put "Add" and "Keep" on check boxes in array fields.
*
* Revision 1.8 1997/07/08 13:12:29 robertj
* Major HTTP form enhancements for lists and arrays of fields.
*
* Revision 1.7 1997/06/08 04:47:27 robertj
* Adding new llist based form field.
*
* Revision 1.6 1997/04/12 02:07:26 robertj
* Fixed boolean check boxes being more flexible on string values.
*
* Revision 1.5 1997/04/01 06:00:53 robertj
* Changed PHTTPConfig so if section empty string, does not write PConfig parameters.
*
* Revision 1.4 1996/10/08 13:10:34 robertj
* Fixed bug in boolean (checkbox) html forms, cannot be reset.
*
* Revision 1.3 1996/09/14 13:09:31 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.2 1996/08/08 13:34:10 robertj
* Removed redundent call.
*
* Revision 1.1 1996/06/28 12:56:20 robertj
* Initial revision
*
*/
#ifdef __GNUC__
#pragma implementation "httpform.h"
#endif
#include <ptlib.h>
#include <ptclib/httpform.h>
#include <ptclib/cypher.h>
//////////////////////////////////////////////////////////////////////////////
// PHTTPField
PHTTPField::PHTTPField(const char * nam, const char * titl, const char * hlp)
: baseName(nam), fullName(nam),
title(titl != NULL ? titl : nam),
help(hlp != NULL ? hlp : "")
{
notInHTML = TRUE;
}
PObject::Comparison PHTTPField::Compare(const PObject & obj) const
{
PAssert(PIsDescendant(&obj, PHTTPField), PInvalidCast);
return fullName.Compare(((const PHTTPField &)obj).fullName);
}
void PHTTPField::SetName(const PString & newName)
{
fullName = newName;
}
const PHTTPField * PHTTPField::LocateName(const PString & name) const
{
if (fullName == name)
return this;
return NULL;
}
void PHTTPField::SetHelp(const PString & hotLinkURL,
const PString & linkText)
{
help = "<A HREF=\"" + hotLinkURL + "\">" + linkText + "</A>\r\n";
}
void PHTTPField::SetHelp(const PString & hotLinkURL,
const PString & imageURL,
const PString & imageText)
{
help = "<A HREF=\"" + hotLinkURL + "\"><IMG SRC=\"" +
imageURL + "\" ALT=\"" + imageText + "\" ALIGN=absmiddle></A>\r\n";
}
static BOOL FindSpliceBlock(const PRegularExpression & startExpr,
const PRegularExpression & endExpr,
const PString & text,
PINDEX offset,
PINDEX & pos,
PINDEX & len,
PINDEX & start,
PINDEX & finish)
{
start = finish = P_MAX_INDEX;
if (!text.FindRegEx(startExpr, pos, len, offset))
return FALSE;
PINDEX endpos, endlen;
if (!text.FindRegEx(endExpr, endpos, endlen, pos+len))
return TRUE;
start = pos + len;
finish = endpos - 1;
len = endpos - pos + endlen;
return TRUE;
}
static BOOL FindSpliceBlock(const PRegularExpression & startExpr,
const PString & text,
PINDEX offset,
PINDEX & pos,
PINDEX & len,
PINDEX & start,
PINDEX & finish)
{
static PRegularExpression EndBlock("<?!--#form[ \t\r\n]+end[ \t\r\n]*-->?",
PRegularExpression::Extended|PRegularExpression::IgnoreCase);
return FindSpliceBlock(startExpr, EndBlock, text, offset, pos, len, start, finish);
}
static BOOL FindSpliceName(const PCaselessString & text,
PINDEX start,
PINDEX finish,
PINDEX & pos,
PINDEX & end)
{
if (text[start+1] != '!') {
static PRegularExpression NameExpr("name[ \t\r\n]*=[ \t\r\n]*\"[^\"]*\"",
PRegularExpression::Extended|PRegularExpression::IgnoreCase);
if ((pos = text.FindRegEx(NameExpr, start)) == P_MAX_INDEX)
return FALSE;
if (pos >= finish)
return FALSE;
pos = text.Find('"', pos) + 1;
end = text.Find('"', pos) - 1;
}
else {
pos = start + 9; // Skip over the <!--#form
while (isspace(text[pos])) // Skip over blanks
pos++;
while (pos < finish && !isspace(text[pos])) // Skip over keyword
pos++;
while (isspace(text[pos])) // Skip over more blanks
pos++;
end = text.Find("--", pos) - 1;
}
return end < finish;
}
static BOOL FindSpliceFieldName(const PString & text,
PINDEX offset,
PINDEX & pos,
PINDEX & len,
PString & name)
{
static PRegularExpression FieldName("<?!--#form[ \t\r\n]+[a-z0-9]+[ \t\r\n]+(-?[^-])+-->?"
"|"
"<[a-z]+[ \t\r\n][^>]*name[ \t\r\n]*=[ \t\r\n]*\"[^\"]*\"[^>]*>",
PRegularExpression::Extended|PRegularExpression::IgnoreCase);
if (!text.FindRegEx(FieldName, pos, len, offset))
return FALSE;
PINDEX nameStart, nameEnd;
if (!FindSpliceName(text, pos, pos+len-1, nameStart, nameEnd))
return FALSE;
name = text(nameStart, nameEnd);
pos = nameStart;
len = nameEnd - nameStart + 1;
return TRUE;
}
static void SpliceAdjust(const PString & str,
PString & text,
PINDEX pos,
PINDEX & len,
PINDEX & finish)
{
text.Splice(str, pos, len);
PINDEX newLen = str.GetLength();
if (finish != P_MAX_INDEX)
finish += newLen - len;
len = newLen;
}
void PHTTPField::ExpandFieldNames(PString & text, PINDEX start, PINDEX & finish) const
{
PString name;
PINDEX pos, len;
while (start < finish && FindSpliceFieldName(text, start, pos, len, name)) {
if (pos > finish)
break;
if (baseName == name)
SpliceAdjust(fullName, text, pos, len, finish);
start = pos + len;
}
}
static BOOL FindInputValue(const PString & text, PINDEX & before, PINDEX & after)
{
static PRegularExpression Value("value[ \t\r\n]*=[ \t\r\n]*(\"[^\"]*\"|[^> \t\r\n]+)",
PRegularExpression::Extended|PRegularExpression::IgnoreCase);
PINDEX pos = text.FindRegEx(Value);
if (pos == P_MAX_INDEX)
return FALSE;
before = text.Find('"', pos);
if (before != P_MAX_INDEX)
after = text.Find('"', before+1);
else {
before = text.Find('=', pos);
while (isspace(text[before+1]))
before++;
after = before + 1;
while (text[after] != '\0' && text[after] != '>' && !isspace(text[after]))
after++;
}
return TRUE;
}
PString PHTTPField::GetHTMLInput(const PString & input) const
{
PINDEX before, after;
if (FindInputValue(input, before, after))
return input(0, before) + GetValue(FALSE) + input.Mid(after);
return "<input value=\"" + GetValue(FALSE) + "\"" + input.Mid(6);
}
static void AdjustSelectOptions(PString & text, PINDEX begin, PINDEX end,
const PString & myValue, PStringList & validValues,
PINDEX & finishAdjust)
{
PINDEX start, finish;
PINDEX pos = begin;
PINDEX len = 0;
static PRegularExpression StartOption("<[ \t\r\n]*option[^>]*>",
PRegularExpression::IgnoreCase);
static PRegularExpression EndOption("<[ \t\r\n]*/?option[^>]*>",
PRegularExpression::Extended|PRegularExpression::IgnoreCase);
while (FindSpliceBlock(StartOption, EndOption, text, pos+len, pos, len, start, finish) && pos < end) {
if (start == P_MAX_INDEX)
start = text.Find('>', pos)+1;
else {
// Check for if option was not closed by </option> but another <option>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -