📄 httpform.cxx
字号:
/*
* httpform.cxx
*
* Forms using HTTP 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: httpform.cxx,v $
* 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(obj.IsDescendant(PHTTPField::Class()), 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))
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]+[^-]+[ \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::IgnoreCase);
while (FindSpliceBlock(StartOption, EndOption, text, pos+len, pos, len, start, finish) && pos < end) {
PCaselessString option = text(pos, start-1);
PINDEX before, after;
if (FindInputValue(option, before, after)) {
start = pos + before + 1;
finish = pos + after - 1;
}
PINDEX selpos = option.Find("selected");
PString thisValue = text(start, finish);
if (thisValue == myValue) {
if (selpos == P_MAX_INDEX) {
text.Splice(" selected", pos+7, 0);
if (finishAdjust != P_MAX_INDEX)
finishAdjust += 9;
if (end != P_MAX_INDEX)
end += 9;
len += 9;
}
}
else {
if (validValues.GetSize() > 0) {
PINDEX valid;
for (valid = 0; valid < validValues.GetSize(); valid++) {
if (thisValue == validValues[valid])
break;
}
if (valid >= validValues.GetSize()) {
text.Delete(pos, len);
selpos = P_MAX_INDEX;
if (finishAdjust != P_MAX_INDEX)
finishAdjust -= len;
if (end != P_MAX_INDEX)
end -= len;
len = 0;
}
}
if (selpos != P_MAX_INDEX) {
selpos += pos;
PINDEX sellen = 8;
if (text[selpos-1] == ' ') {
selpos--;
sellen++;
}
text.Delete(selpos, sellen);
if (finishAdjust != P_MAX_INDEX)
finishAdjust -= sellen;
if (end != P_MAX_INDEX)
end -= sellen;
len -= sellen;
}
}
}
}
PString PHTTPField::GetHTMLSelect(const PString & selection) const
{
PString text = selection;
PStringList dummy1;
PINDEX dummy2 = P_MAX_INDEX;
AdjustSelectOptions(text, 0, P_MAX_INDEX, GetValue(FALSE), dummy1, dummy2);
return text;
}
void PHTTPField::GetHTMLHeading(PHTML &) const
{
}
static int SplitConfigKey(const PString & fullName,
PString & section, PString & key)
{
if (fullName.IsEmpty())
return 0;
PINDEX slash = fullName.FindLast('\\');
if (slash == 0 || slash >= fullName.GetLength()-1) {
key = fullName;
return 1;
}
section = fullName.Left(slash);
key = fullName.Mid(slash+1);
if (section.IsEmpty() || key.IsEmpty())
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -