/* * 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.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 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 #include #include ////////////////////////////////////////////////////////////////////////////// // 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 = "" + linkText + "\r\n"; } void PHTTPField::SetHelp(const PString & hotLinkURL, const PString & imageURL, const PString & imageText) { help = "\""\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("?", 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 ?" "|" "<[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 "]*>", 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 but another