|
From: creedon <icr...@us...> - 2005-07-28 06:59:41
|
Update of /cvsroot/frontierkernel/odbs/prefsRoot/prefsSuite In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv9570 Modified Files: browser Log Message: reworked 4/18/04; 7:58:37 PM code for upload a picture or any kind of file PNG support, store height and width of pictures we recognize upload any kind of file, need to add interface to link to file display picture, code looks for displayPicture attribute; if false don't display; default is true, contructs url that points into pta^.responderAttributes.urls^.prefsHome + "picture"; expects script to be there to deal with picture request Index: browser =================================================================== RCS file: /cvsroot/frontierkernel/odbs/prefsRoot/prefsSuite/browser,v retrieving revision 1.1.1.1 retrieving revision 1.2 diff -C2 -d -r1.1.1.1 -r1.2 *** browser 2 Apr 2005 23:09:51 -0000 1.1.1.1 --- browser 28 Jul 2005 06:59:33 -0000 1.2 *************** *** 1,3 **** FrontierVcsFile:1:scpt:prefsSuite.browser ! on browser (flSignupForm=false, flIncludeTitle=true, adrSignupCallback=nil, inputPanel=nil, action=nil, adrError=nil, flHandleRequiredFields=true, pta=nil, flRequiresRedo=false, flSetTitle=true, separatorColor=nil, separatorTextColor=nil) { ÇChanges: Ç7/14/03; 5:24:12 PM by JES ÇAdded support for includeItem callback. Called with the value of the adr attribute of a prefs item, if the callback returns false, the item is skipped. Ç2002: Ç1/25/02; 6:11:51 PM by PBS ÇPerformance enhancements in the local "add" routine -- add a trailing semicolon; use parentheses to get the expression in x = x + y form (which is optimized by the kernel). Ç1/21/02; 9:00:32 PM by PBS ÇBug fix -- if a title is empty, the item is supposed to span both columns. This feature had been broken. Ç2000: Ç11/25/00; 8:23:57 PM by PBS ÇIf the title of an item is "", don't add a colon. This way we don't get colons before edit-in-Pike buttons. Ç03/31/00; 5:08:00 PM by PBS ÇWhen a sign-up form includes a picture, sometimes the browser would send empty data which got interpreted as a Frontier table. Then when building the form an implicit attempt was made to coerce the table to a string, which failed. Ç1999: Ç11/16/1999; 10:09:08 AM by AR ÇPurged all instances of xml.getAddressList in favor of our own looping code so that this script will work with arbitrarily deeply nested table structures. Ç10/30/99; 12:10:59 PM by PBS ÇImplemented workaround for 302 FOUND browser bug when redirecting to the same page you just posted to. Now the redirect happens to a different URL. If you were on a $panelName URL, you're redirected to a $panelNum URL, and vice versa. Ç10/30/99; 12:02:48 AM by PBS ÇManila sites need to be able to specify the color of separators and the text inside. If colors are not specified, the default is black for the separator and pta^.bgcolor for the text inside. Ç9/22/99; 8:39:27 PM by DW ÇWe used to always generate a form with an enctype="multipart/form-data" in its header. Now we only do so if the form contains a picture, or if there is a panel attribute named multiPart with a value of true. So in most circumstances we will not have a multipart form, in the past we would *always* have a multipart form. Ç9/16/99; 9:47:26 AM by DW ÇAdded link attribute on items, if present, the whole item links to the URL provided in the attribute. Search for "linkattribute" for implementation. Ç9/13/99; 12:37:43 PM by PBS ÇSign-ups and changed passwords weren't getting propagated. Now they are. Ç9/8/99; 12:40:57 AM by PBS ÇIf this is a sign up form, check that the two passwords match before creating the membership record. There was a bug -- the passwords might not match, but a membership record that didn't include a password would be created. Then the person signing up has no password -- but they can't sign up again because they're now a member. Ç8/19/99; 2:23:47 PM by PBS ÇNew optional parameter flSetTitle. If false, prefsSuite.browser does not set pta^.title, so the calling page can use a different title than the title of the panel. This was needed for the store -- which uses one panel for all order forms, but the titles are different depending on whether you're at the standard page or the Academic page. ÇDefault is standard behavior -- prefsSuite.browser sets pta^.title automatically. Ç8/18/99; 7:59:48 PM by PBS ÇIf you place a | character in a title, it will be replaced by a <br> tag so the title will wrap to the next line. Ç8/17/99; 11:24:53 AM by PBS ÇThe sendRpcMessages routine was moved to the top level of prefsSuite. The routine in this script now calls prefsSuite.sendRpcMessages. ÇThis was done so prefs broadcasting could happen outside of the context of this script or the page rendering process, so other scripts could broadcast prefs at will. Ç8/15/99; 3:59:30 PM by PBS ÇflRequiresRedo is no an optional parameter: if true, then the values will be taked from the post args. Ç8/14/99; 9:12:40 PM by PBS ÇMake sure content-type is defined before checking its value. This was causing errors with some browser on the main prefs page. Ç8/13/99; 3:53:13 PM by PBS ÇNew optional parameter pta. (Useful when debugging, also a small optimization.) Ç8/10/99; 10:24:06 PM by PBS ÇIf the person signing up uses an email address of an existing member, the error is reported in red text, and the user has a chance to re-fill out the form or go to the sign up page. ÇCheck that config.prefsServer.prefsDistributorFolder exists, so machines that aren't prefs distributors can run this script without generating errors. Ç8/10/99; 6:27:53 PM by PBS ÇNew parameter, flHandleRequiredFields, allows one to disable the automatic handling of required fields. Ç7/28/99; 9:05:00 by RAB Çadded action parameter Çadded adrError parameter Ç7/27/99; 17:35:00 by RAB ÇIf you specify a null title, then the field spans 2 columns. ÇAdded new pref alignNonRequired which keeps the titles better aligned Ç7/12/99; 2:59:44 by PBS ÇSupport for default values. An item can have a default attribute. If the item is not already in the user's member record, or it's a sign up form, then the item will get this default value. ÇAs in: <item title="Formatted in HTML?" type="boolean" adr="bulletins.inHtml" default="true"> Ç7/8/99; 10:03:09 AM by DW ÇImplement the XML-RPC-based prefs distribution system. Ç7/6/99; 8:41:39 AM by DW ÇAllow the pathargs to be a non-numeric string, it can contain the name of the panel, we'll transition to this form of pointing because it allows us to move things around. Ç6/27/99; 7:05:00 PM by RAB ÇSupport for static fields. ÇSupport for hidden fields. ÇSupport for checkbox fields. ÇOptional parameter for inputPanel number (rather then pathArgs) Ç6/12/99; 3:35:03 PM by PBS ÇSupport for required fields. ÇIf an item in the XML outline has a required="true" attribute, then it's a required field. ÇThe system will prompt you to enter any required fields you didn't enter. Ç6/5/99; 1:51:25 AM by PBS ÇadrSignupCallback is the address of a callback to be used when handling the POST request from a signup form. ÇThe callback is called after the POST args are processed, but before the form is built. ÇIf the callback returns anything but "", then the results of the callback are displayed in the page rather than the form. ÇThe callback thus has the chance to send email, for instance, when adding a member. And it has the chance to build a welcome page. Ç6/4/99; 4:15:27 PM by PBS ÇIf it's a signup form, and the member already exists, it's an error. ÇText in separators is now bold. Ç6/3/99; 12:37:55 PM by DW ÇAdded optional boolean parameter, flSignupForm, defaults false. If true, we don't require that pta^.adrmemberinfo be defined. ÇAdded optional boolean parameter, flIncludeTitle, defaults true. If false, we don't include the title, assume the page already has a title. Ç6/4/99; 10:38:22 AM by DW ÇAdd separator <item>s, that allow the author to separate items into groups. ÇAllow <item>s to be required, if the value has not been set, reject the submission. if pta == nil { pta = html.getPageTableAddress ()}; local (adrWizard = pta^.wizard); local (adrCallbacks = @adrwizard^.callbacks, flCallbacks = defined (adrCallbacks^)); local (pathArgs = pta^.pathArgs); local (pageName = nameOf (pta^.adrobject^)); Çlocal (flRequiresRedo = false) //it becomes true if required fields were missing local (emptyList = {}); local (flOneRequired = false); if adrError != nil { adrError^ = false}; local (rpcParamTable); new (tabletype, @rpcParamTable); on addPrefToRpcParamTable (partialaddress, adrval) { //7/8/99; 10:03:09 AM by DW if typeof (adrval^) == tabletype { local (i, adritem); for i = 1 to sizeof (adrval^) { adritem = @adrval^ [i]; if typeof (adritem^) == binarytype { adritem^ = base64.encode (adritem^, infinity)}}}; rpcParamTable.[partialaddress] = adrval^}; on sendRpcMessages () { if defined (pta^.adrMemberInfo) { //PBS 9/2/99: this person may not be a member prefsSuite.sendRpcMessages (@rpcParamTable, pta^.adrMemberInfo)}; //PBS 8/17/99: routine moved to top level of prefsSuite Çlocal (xmltext) Çbundle //build the XML representation Çon add (s) Çxmltext = xmltext + s + "\r" Çadd ("<?xml version=\"1.0\"?>") Çadd ("<prefsUpdate>") Çadd ("<group>" + "default" + "</group>") Çadd ("<memberKey>" + nameof (pta^.adrmemberinfo^) + "</memberKey>") Çadd ("<value>" + xml.coercions.frontierValueToTaggedText (@rpcParamTable, 0) + "</value>") Çadd ("</prefsUpdate>") Çbundle //write the file Çif defined (config.prefsServer.prefsDistributorFolder) //PBS 8/10/99: make sure this machine is a prefs distributor Çlocal (folder = config.prefsServer.prefsDistributorFolder) Çloop //get a unique name, write the file Çlocal (f = folder + clock.ticks () + ".xml") Çfile.surefilepath (f) Çif not file.exists (f) Çfile.writewholefile (f, xmltext) Çbreak ÇprefsSuite.init () Çlocal (i, ct = sizeof (config.prefsServer.subscribers), adrsubscriber) Çlocal (params = {"default", nameof (pta^.adrmemberinfo^), rpcParamTable}) Çfor i = 1 to ct Çadrsubscriber = @config.prefsServer.subscribers [i] Çbetty.rpc.client (nameof (adrsubscriber^), adrsubscriber^.port, adrsubscriber^.procedureName, @params, rpcpath:adrsubscriber^.rpcPath, flAsynch:true) Ç<panel title="Register"> Ç<description>This is an experimental feature. If you have a server that can do something interesting with preferences, and if your server can receive XML-RPC messages, you can hook into the preference system at UserLand.Com. We need three pieces of information: a domain name for your server (an IP address will also work), the port that server is running on, and the name of the XML-RPC procedure you want us to call. This routine will be called every time every user updates, so please don't register unless you're serious.</description> Ç<item title="Domain" type="string" adr="prefsRpcHandler.domain"/> Ç<item title="Port" type="string" adr="prefsRpcHandler.port"/> Ç<item title="Procedure name" type="string" adr="prefsRpcHandler.procedureName"/> Ç</panel> return (true)}; local (htmlText = "", indentLevel = 0); on add (s) { htmlText = htmlText + (string.filledString ("\t", indentLevel) + s + "\r");}; prefsSuite.compileIfDirty (); //compile the XML if needed local (panelNum, adrPanel); bundle { //get the number of the panel, the address of its descriptor in the XML structure, set flPrivate page attribute if inputPanel != nil { //caller supplied the panel num panelNum = number (inputPanel); local (i, ctpanels = 0, adritem, adrtable = @adrWizard^.structure [1]); for i = 1 to sizeOf (adrtable^) { adritem = @adrtable^[i]; if xml.convertToDisplayName (nameOf (adritem^)) == "panel" { ++ctpanels; if ctpanels == panelNum { //found it! adrPanel = adritem; break}}}; if ctpanels < panelNum { scripterror ("Can't display the panel because the wizard doesn't have a panel #" + panelNum + ".")}} else { panelNum = prefsSuite.pathArgsToPanelNum (pathargs, @adrpanel)}; local (flPrivate = false); try { flPrivate = boolean (xml.getAttribute (adrPanel, "private")^)}; pta^.flPrivate = flPrivate}; local (panelTitle, description); bundle { //get the title and description panelTitle = xml.getAttribute (adrPanel, "title")^; if flSetTitle { //PBS 8/19/99: if flSetTitle is false, then the calling page is responsible for setting pta^.title pta^.title = panelTitle}; description = xml.getValue (adrPanel, "description"); description = string.replaceAll (description, "\t", ""); description = string.replaceAll (description, "\r", "<p>")}; on getPrefAddress (partialAddress) { //takes a partial address, returns an address into user's member table local (nomad = pta^.adrMemberInfo, s); loop { if not (partialAddress contains ".") { nomad = @nomad^.[partialAddress]; break}; s = string.nthField (partialAddress, '.', 1); nomad = @nomad^.[s]; if not defined (nomad^) { new (tableType, nomad)}; partialAddress = string.delete (partialAddress, 1, sizeOf (s) + 1)}; return (nomad)}; if pta^.method == "POST" { //PBS 6/12/99: check that required fields are non-empty if flHandleRequiredFields { //PBS 8/10/99: required fields handling can be turned off local (i, adrOneItem, emptyFieldNames = {}); for i = 1 to sizeOf (adrPanel^) { //check whether there are required fields that have not been filled out adrOneItem = @adrPanel^ [i]; if xml.convertToDisplayName (nameOf (adrOneItem^)) == "item" { local (flRequired = false); try { flRequired = boolean (xml.getAttributeValue (adrOneItem, "required"))}; if flRequired { //make sure it exists and is non-empty local (adr = xml.getAttributeValue (adrOneItem, "adr"), flEmpty = false); if not defined (pta^.postArgs.[adr]) { flEmpty = true} else { if sizeOf (pta^.postArgs.[adr]) == 0 { flEmpty = true}}; if flEmpty { emptyFieldNames = emptyFieldNames + xml.getAttributeValue (adrOneItem, "title")}}}}; if emptyFieldNames != {} { //if the emptyFieldNames list contains items, then display errors local (errorMessage = "Please enter the required field"); local (i, ctEmpties); bundle { //build the top error message ctEmpties = sizeOf (emptyFieldNames); if sizeOf (emptyFieldNames) > 1 { errorMessage = errorMessage + "s"}; errorMessage = errorMessage + " "; for i = 1 to sizeOf (emptyFieldNames) { errorMessage = errorMessage + "<b>" + emptyFieldNames [i] + "</b>"; if i < ctEmpties { if ctEmpties > 2 { errorMessage = errorMessage + ", "} else { errorMessage = errorMessage + " "}; if ctEmpties == 2 or i == ctEmpties - 1 { errorMessage = errorMessage + "and "}}}; if ctEmpties < 2 { errorMessage = errorMessage + "."} //" is required." else { errorMessage = errorMessage + "."}; //" are required." add ("<font color=\"red\">" + errorMessage + "</font>")}; flRequiresRedo = true; if adrError != nil { //PBS 8/9/99 -- adrError is optional: make sure it's not nil before trying to deference it. adrError^ = true}}}}; if pta^.method == "POST" and not flRequiresRedo { //process the POSTed data Çscratchpad.postargs = pta^.postargs; edit (@scratchpad.postargs) ÇCreate a new membership table if needed. if not defined (pta^.adrMemberInfo) and flSignupForm { if defined (pta^.postArgs.["personalInfo.email"]) { local (memberKey = pta^.postArgs.["personalInfo.email"]); try { //validate the email address mainResponder.members.validMailAddress (memberKey)} else { scriptError ("Can't create a membership record because the email address is invalid.")}; local (adrMember = mainResponder.members.getMemberTable (pta^.defaultMembershipGroup, memberKey)); if not defined (adrMember^) { ÇFirst check the password. PBS 9/7/99 if defined (pta^.postArgs.["scratchpassword1"]) { if defined (pta^.postArgs.["scratchpassword2"]) { if pta^.postArgs.["scratchpassword1"] != pta^.postArgs.["scratchpassword2"] { add ("<p><font color=\"red\">Can't sign you up because the two passwords you entered do not match.</font>"); flRequiresRedo = true}}}; if not flRequiresRedo { new (tableType, adrMember); pta^.adrMemberInfo = adrMember; pta^.memberGroupName = pta^.defaultMembershipGroup}} else { //PBS 6/4/99: member already exists, it's an error flRequiresRedo = true; add ("<font color=\"red\">Can't sign up \"" + memberKey + "\" because \"" + memberKey + "\" is already a member.</font>"); if defined (pta^.urls^.memberLogon) { add ("<p><font color=\"red\">If you want to login, even if you forgot your password, go to the " + html.getLink ("Login", pta^.urls^.memberLogon) + " page.</font>")}}}}; if not flRequiresRedo { //PBS 8/10/99: it may have been set false, even though it was false when entering this block local (refreshAfterPost = false); if defined (pta^.postargs.refreshAfterPost) { refreshAfterPost = true; delete (@pta^.postargs.refreshAfterPost)}; local (adrtable = @pta^.postargs, ct = sizeof (adrtable^), i, adritem, val); for i = 1 to ct { adritem = @adrtable^ [i]; local (nomad); if defined (pta^.adrMemberInfo) { nomad = pta^.adrMemberInfo}; local (partialaddress = nameof (adritem^), s); if partialaddress beginswith "scratchpassword" { if partialaddress == "scratchpassword1" { local (otherpassword = adrtable^.["scratchpassword2"]); if adrtable^.["scratchpassword1"] != otherpassword { scriptError ("Can't set the password because the two passwords you entered are not equal.")}; if not (otherpassword == "") { pta^.adrmemberinfo^.password = otherpassword; addPrefToRpcParamTable ("password", @pta^.adrmemberinfo^.password ); //PBS 9/13/99: propagate passwords local (mailaddress = nameof (pta^.adrmemberinfo^)); mainresponder.members.setcookie (mailaddress, otherpassword)}}} else { on setValueCallback (adrval) { //5/22/99; 8:46:15 AM by DW if flcallbacks { local (adrcallback = @adrcallbacks^.setValue); if defined (adrcallback^) { adrcallback^ (partialaddress, adrval)}}; addPrefToRpcParamTable (partialaddress, adrval)}; //7/8/99; 10:03:09 AM by DW //PBS 9/13/99: promoted this line if defined (pta^.adrMemberInfo) { nomad = getPrefAddress (partialaddress); if typeof (adritem^) == tabletype { //it's a multi-part object local (datasize = sizeof (adritem^.data)); local (contenttype); if defined (adritem^.["Content-Type"]) { //PBS 8/14/99: make sure Content-Type is defined before checking its value contenttype = string.lower (adritem^.["Content-Type"])}; if datasize > 0 { //this is what you get if you don't specify an image if not contenttype beginswith "image" { scriptError ("Can't accept the file because it is not an image.")}; local (maxbytes = pta^.wizard^.prefs.maxPictureBytes); if datasize > maxbytes { scriptError ("Can't accept the file because it is too large. Maximum is " + string.kBytes (maxbytes) + ".")}; bundle { //set the type attribute of the data local (bt = nil); if contenttype == "image/gif" { bt = "GIFf"}; if contenttype == "image/jpeg" { bt = "JPEG"}; if bt != nil { adritem^.data = binary (adritem^.data); setBinaryType (@adritem^.data, bt)}}; nomad^ = adritem^; //copy the table into storage setValueCallback (adritem)}} else { val = adritem^; if (val == "true") or (val == "false") { val = boolean (val)}; nomad^ = val; setValueCallback (@val)}}}}; sendRpcMessages (); //7/8/99; 10:03:09 AM by DW if refreshAfterPost { ÇPBS 10/30/99: redirect to a different URL by choosing an alternate pathArgs form. ÇIf number, use title; if title, use number. ÇThis works around the 302 FOUND Netscape browser bug. local (panelIdentifier, newPathArgs); try { panelIdentifier = number (pta^.pathArgs); newPathArgs = string.innerCaseName (panelTitle)} else { newPathArgs = panelNum}; Çmainresponder.redirect (pta^.uri + "$" + pta^.pathargs) mainresponder.redirect (pta^.uri + "$" + newPathArgs)}; ÇCall the signup callback, if applicable. PBS 6/5/99 ÇThe signup callback can send email and do similar operations. ÇIf it returns an empty string, then build the form as normal. ÇIf it returns text, then return that text -- the signup callback can control what gets displayed on the page. if flSignupForm and adrSignupCallback != nil { htmlText = adrSignupCallback^ (); if htmlText != "" { return (htmlText)}}}}; bundle { //add the form with the items local (flRequiresMultiPart = false); try {flRequiresMultiPart = boolean (xml.getattribute (adrpanel, "multiPart"))^}; //multiPart attribute is optional if action == nil { action = pagename + "$" + panelnum}; add ("<form name=\"" + paneltitle + "\" action=\"" + action + "\" method=\"POST\"<<xxx>>>"); indentlevel++; bundle { //add hidden item if it has refreshAfterPost attribute try { local (refreshAfterPost = boolean (xml.getattribute (adrpanel, "refreshAfterPost")^)); if refreshAfterPost { add ("<input type=\"hidden\" name=\"refreshAfterPost\" value=\"1\">")}}}; if flIncludeTitle { add ("<h2>" + paneltitle + "</h2>")}; add (description + "<p>"); add ("<table cellpadding=\"7\" cellspacing=\"0\" border=\"0\">"); indentlevel++; local (flShowSubmitButton = false); local (i, adritem, adr, title, type, popuptext, linkattribute, defaultvalue, flspan, ixitem = 0); for i = 1 to sizeOf (adrPanel^) { adritem = @adrPanel^ [i]; adr = ""; if xml.convertToDisplayName (nameOf (adritem^)) == "item" { ixitem++; flShowSubmitButton = true; defaultValue = ""; //PBS 7/12/99: clear out previous default value bundle { //set title title = xml.getattribute (adritem, "title")^; local (flAddColon = true); if title endswith "?" { flAddColon = false}; if string.trimWhiteSpace (title) == "" { flAddColon = false}; if flAddColon { title = title + ":"}}; type = string.lower (xml.getattribute (adritem, "type")^); //types are unicase try {adr = xml.getattribute (adritem, "adr")^}; //adr attribute is optional, for example separators don't have adrs if adr != "" { //JES 7/14/: call callbacks if they exist -- determine if this item should be included if flCallbacks { if defined (adrCallbacks^.includeItem) { try { if not adrCallbacks^.includeItem (adr) { continue}}}}}; if type == "separator" { //very special case if separatorColor == nil { //PBS 10/30/99: Manila sites need to be able to specify separator and separator text color separatorColor = "black"}; if separatorTextColor == nil { separatorTextColor = pta^.bgcolor}; add ("<tr><td colspan=\"2\"><table cellpadding=\"2\" cellspacing=\"0\" width=\"100%\"><tr>"); indentlevel++; add ("<td bgcolor=\"" + separatorColor + "\"><font color=\"" + separatorTextColor + "\"><b>" + title + "</b></font></td>"); //PBS 6/4/99: text in separators is bold add ("</tr></table></td></tr>"); indentlevel--; continue}; bundle { //get popuptext if it's present try { popuptext = xml.getvalue (adritem, "popuptext")} else { popuptext = ""}}; bundle { //get link attribute if it's present try { linkattribute = xml.getattribute (adritem, "link")^} else { linkattribute = ""}}; add ("<tr>"); indentlevel++; ÇIf this is a re-do, and this is an empty required field, then ask the user to fill it in. Çif flRequiresRedo and emptyList contains adrItem Çlocal (fieldName = xml.getAttribute (adrItem, "title")^) Çadd ("<td colspan=\"2\"><font color=\"red\"><b>" + fieldName + "</b> is empty. Please fill it in.</font></td></tr>") Çadd ("<tr>") bundle { //set defaultvalue if flRequiresRedo { //PBS 6/12/99: get the value from the POST args if it's a redo defaultValue = pta^.postArgs.[adr]} else { ÇHandle default values. PBS 7/12/99 try { defaultValue = xml.getAttributeValue (adrItem, "default")}; //PBS 7/12/99: get default value from outline if not flSignupForm { if defined (pta^.adrMemberInfo) { with pta^.adrmemberinfo^ { Çdefaultvalue = "" try { local (adrobject = getPrefAddress (adr)); if typeof (adrobject^) == tabletype { //it's a multi-part object defaultvalue = adrobject^.filename} else { defaultvalue = adrobject^}}; bundle { //5/22/99; 7:31:16 AM by DW, call the callback if one is present if flcallbacks { local (adrcallback = @adrcallbacks^.getValue); if defined (adrcallback^) { defaultvalue = adrcallback^ (adr, defaultvalue)}}}}}}}}; //adr is the partial address, the callback should be a big case statement, based on which value is being asked for bundle { //add title local (s); if popuptext != "" { local (shortaddress = panelnum + "," + ixitem); local (href = "href=\"JavaScript: newWindow=openWin( '" + adrwizard^.prefs.popupPageName + "$" + shortaddress + "', 'prefsPopup', '" + string (adrwizard^.prefs.popupWindowAttributes) + "' );newWindow.focus()\""); s = "<a " + href + " title=\"" + string.firstsentence (popuptext) + "..\">" + title + "</a>"} else { Çif string.lower (type) == "picture" Çlocal (s = "<a href=\"" + adrwizard^.prefs.picturePageName + "$" + adr + "\">" + title + "</a>") Çadd ("<td valign=\"top\">" + s + "</td>") if linkattribute != "" { s = "<a href=\"" + linkattribute + "\">" + title + "</a>"} else { s = title}}; s = string.replaceAll (s, "|", "<br><font color=\"" + pta^.bgcolor + "\">*</font> "); //PBS 8/18/99: replace | with <br> local (flRequired = false); try { flRequired = boolean (xml.getAttributeValue (adrItem, "required"))}; if flRequired and not (flRequiresRedo and not (emptyList contains adrItem)) and flHandleRequiredFields { //PBS 8/10/99: required fields handling can be turned off s = "<b><font color=\"red\">*</font></b> " + s; flOneRequired = true} else { if defined (adrwizard^.prefs.alignNonRequired) and adrwizard^.prefs.alignNonRequired { s = "<b><font color=\"" + pta^.bgColor + "\">*</font></b> " + s}}; if title == "" { //PBS 01/21/02: no title wanted? (the bug was -- it was checking if title == ":") flspan = true} else { add ("<td valign=\"top\">" + s + "</td>"); flspan=false}}; if flspan { add ("<td colspan=\"2\">"); indentlevel++} else { add ("<td>"); indentlevel++}; case type { "string" { local (size = adrwizard^.prefs.stringDefaultSize, maxlength = adrwizard^.prefs.stringDefaultMaxLength); try {size = xml.getattribute (adritem, "size")^}; try {maxlength = xml.getattribute (adritem, "maxlength")^}; add ("<input type=\"text\" name=\"" + adr + "\" size=\"" + size + "\" maxlength=\"" + maxlength + "\" value=\"" + defaultvalue + "\">")}; "static" { ÇAdd the hidden field so the value is processed with the form, add just the defualt value as the static display. add (defaultvalue); add ("<input type=\"hidden\" name=\"" + adr + "\" value=\"" + defaultvalue + "\">")}; "hidden" { ÇAdd the hidden field so the value is processed with the form. add ("<input type=\"hidden\" name=\"" + adr + "\" value=\"" + defaultvalue + "\">")}; "popup" { Ç<SELECT name="state"> Ç<OPTION>Select a state Ç<OPTION VALUE="AL">Alabama Ç<OPTION VALUE="AK">Alaska Ç<OPTION VALUE="AZ">Arizona Ç<OPTION VALUE="AR">Arkansas Ç</SELECT> add ("<select name=\"" + adr + "\">"); indentlevel++; local (i, adroption, title, value, s); for i = 1 to sizeOf (adritem^) { adroption = @adritem^ [i]; if xml.convertToDisplayName (nameOf (adroption^)) == "option" { title = xml.getattribute (adroption, "title")^; value = xml.getattribute (adroption, "value")^; s = ""; if defaultvalue == value { s = " selected"}; add ("<option value=\"" + value + "\"" + s + ">" + title + "</option>")}}; add ("</select>"); indentlevel--}; "color" { //7/13/99; 11:34:37 PM by DW add ("<select name=\"" + adr + "\">"); indentlevel++; local (adrtable = @system.verbs.colors, i, ct = sizeof (adrtable^)); for i = 1 to ct { onecolor = nameof (adrtable^ [i]); s = ""; if defaultvalue == onecolor { s = " selected"}; add ("<option value=\"" + onecolor + "\"" + s + ">" + onecolor + "</option>")}; add ("</select>"); indentlevel--}; "password" { local (size = adrwizard^.prefs.passwordDefaultSize, maxlength = adrwizard^.prefs.passwordDefaultMaxLength); try {size = xml.getattribute (adritem, "size")^}; try {maxlength = xml.getattribute (adritem, "maxlength")^}; add ("<input type=\"password\" name=\"" + adr + "\" size=\"" + size + "\" maxlength=\"" + maxlength + "\" value=\"" + defaultvalue + "\">")}; "text" { local (rows = adrwizard^.prefs.textDefaultRows, cols = adrwizard^.prefs.textDefaultCols); try {rows = xml.getattribute (adritem, "rows")^}; try {cols = xml.getattribute (adritem, "cols")^}; add ("<textarea name=\"" + adr + "\" rows=\"" + rows + "\" cols=\"" + cols + "\" wrap=\"soft\">" + defaultvalue + "</textarea>")}; "boolean" { Çtemp.ddx2 = boolean (defaultvalue) Çtemp.ddxstring = defaultvalue on addradio (val, flchecked, linetext) { local (s = "<input type=\"radio\" name=\"" + adr + "\" value=" + val); if flchecked { s = s + " checked"}; add (s + ">" + linetext)}; addradio ("true", boolean (defaultvalue), "Yes"); addradio ("false", !boolean (defaultvalue), "No"); Çadd ("<input type=\"radio\" name=\"" + adr + "\" value=" + "1 checked" + ">" + "Yes") };Çadd ("<input type=\"radio\" name=\"" + adr + "\" value=\"" + "0" + "\">" + "No") "checkbox" { add ("<input type=\"checkbox\" name=\"" + adr + "\" value=\"" + defaultvalue + "\">")}; "picture" { flRequiresMultiPart = true; if typeOf (defaultValue) == tableType { //PBS 03/30/00: if defaultvalue is a table, set it to "", fixes an error message on sign-up table.assign (@defaultValue, "")}; add ("<input name=\"" + adr + "\" type=\"file\" size=\"40\" value=\"" + defaultvalue + "\">")}; "custom" { if flcallbacks { //allow application to do object rendering local (adrcallback = @adrcallbacks^.customRenderer); if defined (adrcallback^) { add (adrcallback^ (adr, defaultvalue, adritem))}} //send the partial address, the default value, and the address of the XML table of the object being rendered else { add (" ")}}} else { add (" ")}; add ("</td>"); indentlevel--; add ("</tr>"); indentlevel--}}; add ("<tr>"); indentlevel++; add ("<td> </td>"); bundle { //add Submit button local (s = " "); if flShowSubmitButton { //if all there is is text on the page, no need to put a submit item on the page s = "<input type=\"submit\" value=\" " + "Submit" + " \">"}; add ("<td align=\"right\">" + s + "</td>")}; add ("</tr>"); indentlevel--; add ("</table>"); indentlevel--; add ("</form>"); indentlevel--; if flOneRequired and not flRequiresRedo { //add note about required fields if flHandleRequiredFields { //PBS 8/10/99: required fields handling can be turned off Çadd ("Required fields are marked with <b><font color=\"red\">*</font></b>") htmlText = "Required fields are marked with <b><font color=\"red\">*</font></b>" + htmlText}}; bundle { //do the enctype substitution local (pattern = "<<xxx>>"); if flRequiresMultiPart { htmltext = string.replace (htmltext, pattern, "enctype=\"multipart/form-data\"")} else { htmltext = string.replace (htmltext, pattern, "")}}}; return (htmlText)} \ No newline at end of file --- 1,3 ---- FrontierVcsFile:1:scpt:prefsSuite.browser ! on browser (flSignupForm=false, flIncludeTitle=true, adrSignupCallback=nil, inputPanel=nil, action=nil, adrError=nil, flHandleRequiredFields=true, pta=nil, flRequiresRedo=false, flSetTitle=true, separatorColor=nil, separatorTextColor=nil) { ÇChanges Ç2005 Ç7/27/05; 7:03:00 PM by TAC Çreworked 4/18/04; 7:58:37 PM code for upload a picture or any kind of file ÇPNG support Çstore height and width of pictures we recognize Ç2004 Ç4/18/04; 7:58:37 PM by TAC Çupload any kind of file, need to add interface to link to file Ç2003 Ç7/14/03; 5:24:12 PM by JES ÇAdded support for includeItem callback. Called with the value of the adr attribute of a prefs item, if the callback returns false, the item is skipped. Ç7/10/03; 11:26:22 PM by TAC Çdisplay picture, code looks for displayPicture attribute; if false don't display; default is true, contructs url that points into pta^.responderAttributes.urls^.prefsHome + "picture"; expects script to be there to deal with picture request Ç2002 Ç1/25/02; 6:11:51 PM by PBS ÇPerformance enhancements in the local "add" routine -- add a trailing semicolon; use parentheses to get the expression in x = x + y form (which is optimized by the kernel). Ç1/21/02; 9:00:32 PM by PBS ÇBug fix -- if a title is empty, the item is supposed to span both columns. This feature had been broken. Ç2000 Ç11/25/00; 8:23:57 PM by PBS ÇIf the title of an item is "", don't add a colon. This way we don't get colons before edit-in-Pike buttons. Ç03/31/00; 5:08:00 PM by PBS ÇWhen a sign-up form includes a picture, sometimes the browser would send empty data which got interpreted as a Frontier table. Then when building the form an implicit attempt was made to coerce the table to a string, which failed. Ç1999 Ç11/16/1999; 10:09:08 AM by AR ÇPurged all instances of xml.getAddressList in favor of our own looping code so that this script will work with arbitrarily deeply nested table structures. Ç10/30/99; 12:10:59 PM by PBS ÇImplemented workaround for 302 FOUND browser bug when redirecting to the same page you just posted to. Now the redirect happens to a different URL. If you were on a $panelName URL, you're redirected to a $panelNum URL, and vice versa. Ç10/30/99; 12:02:48 AM by PBS ÇManila sites need to be able to specify the color of separators and the text inside. If colors are not specified, the default is black for the separator and pta^.bgcolor for the text inside. Ç9/22/99; 8:39:27 PM by DW ÇWe used to always generate a form with an enctype="multipart/form-data" in its header. Now we only do so if the form contains a picture, or if there is a panel attribute named multiPart with a value of true. So in most circumstances we will not have a multipart form, in the past we would *always* have a multipart form. Ç9/16/99; 9:47:26 AM by DW ÇAdded link attribute on items, if present, the whole item links to the URL provided in the attribute. Search for "linkattribute" for implementation. Ç9/13/99; 12:37:43 PM by PBS ÇSign-ups and changed passwords weren't getting propagated. Now they are. Ç9/8/99; 12:40:57 AM by PBS ÇIf this is a sign up form, check that the two passwords match before creating the membership record. There was a bug -- the passwords might not match, but a membership record that didn't include a password would be created. Then the person signing up has no password -- but they can't sign up again because they're now a member. Ç8/19/99; 2:23:47 PM by PBS ÇNew optional parameter flSetTitle. If false, prefsSuite.browser does not set pta^.title, so the calling page can use a different title than the title of the panel. This was needed for the store -- which uses one panel for all order forms, but the titles are different depending on whether you're at the standard page or the Academic page. ÇDefault is standard behavior -- prefsSuite.browser sets pta^.title automatically. Ç8/18/99; 7:59:48 PM by PBS ÇIf you place a | character in a title, it will be replaced by a <br> tag so the title will wrap to the next line. Ç8/17/99; 11:24:53 AM by PBS ÇThe sendRpcMessages routine was moved to the top level of prefsSuite. The routine in this script now calls prefsSuite.sendRpcMessages. ÇThis was done so prefs broadcasting could happen outside of the context of this script or the page rendering process, so other scripts could broadcast prefs at will. Ç8/15/99; 3:59:30 PM by PBS ÇflRequiresRedo is no an optional parameter: if true, then the values will be taked from the post args. Ç8/14/99; 9:12:40 PM by PBS ÇMake sure content-type is defined before checking its value. This was causing errors with some browser on the main prefs page. Ç8/13/99; 3:53:13 PM by PBS ÇNew optional parameter pta. (Useful when debugging, also a small optimization.) Ç8/10/99; 10:24:06 PM by PBS ÇIf the person signing up uses an email address of an existing member, the error is reported in red text, and the user has a chance to re-fill out the form or go to the sign up page. ÇCheck that config.prefsServer.prefsDistributorFolder exists, so machines that aren't prefs distributors can run this script without generating errors. Ç8/10/99; 6:27:53 PM by PBS ÇNew parameter, flHandleRequiredFields, allows one to disable the automatic handling of required fields. Ç7/28/99; 9:05:00 by RAB Çadded action parameter Çadded adrError parameter Ç7/27/99; 17:35:00 by RAB ÇIf you specify a null title, then the field spans 2 columns. ÇAdded new pref alignNonRequired which keeps the titles better aligned Ç7/12/99; 2:59:44 by PBS ÇSupport for default values. An item can have a default attribute. If the item is not already in the user's member record, or it's a sign up form, then the item will get this default value. ÇAs in: <item title="Formatted in HTML?" type="boolean" adr="bulletins.inHtml" default="true"> Ç7/8/99; 10:03:09 AM by DW ÇImplement the XML-RPC-based prefs distribution system. Ç7/6/99; 8:41:39 AM by DW ÇAllow the pathargs to be a non-numeric string, it can contain the name of the panel, we'll transition to this form of pointing because it allows us to move things around. Ç6/27/99; 7:05:00 PM by RAB ÇSupport for static fields. ÇSupport for hidden fields. ÇSupport for checkbox fields. ÇOptional parameter for inputPanel number (rather then pathArgs) Ç6/12/99; 3:35:03 PM by PBS ÇSupport for required fields. ÇIf an item in the XML outline has a required="true" attribute, then it's a required field. ÇThe system will prompt you to enter any required fields you didn't enter. Ç6/5/99; 1:51:25 AM by PBS ÇadrSignupCallback is the address of a callback to be used when handling the POST request from a signup form. ÇThe callback is called after the POST args are processed, but before the form is built. ÇIf the callback returns anything but "", then the results of the callback are displayed in the page rather than the form. ÇThe callback thus has the chance to send email, for instance, when adding a member. And it has the chance to build a welcome page. Ç6/4/99; 4:15:27 PM by PBS ÇIf it's a signup form, and the member already exists, it's an error. ÇText in separators is now bold. Ç6/3/99; 12:37:55 PM by DW ÇAdded optional boolean parameter, flSignupForm, defaults false. If true, we don't require that pta^.adrmemberinfo be defined. ÇAdded optional boolean parameter, flIncludeTitle, defaults true. If false, we don't include the title, assume the page already has a title. Ç6/4/99; 10:38:22 AM by DW ÇAdd separator <item>s, that allow the author to separate items into groups. ÇAllow <item>s to be required, if the value has not been set, reject the submission. if pta == nil { pta = html.getPageTableAddress ()}; local (adrWizard = pta^.wizard); local (adrCallbacks = @adrwizard^.callbacks, flCallbacks = defined (adrCallbacks^)); local (pathArgs = pta^.pathArgs); local (pageName = nameOf (pta^.adrobject^)); Çlocal (flRequiresRedo = false) //it becomes true if required fields were missing local (emptyList = {}); local (flOneRequired = false); if adrError != nil { adrError^ = false}; local (rpcParamTable); new (tabletype, @rpcParamTable); on addPrefToRpcParamTable (partialaddress, adrval) { //7/8/99; 10:03:09 AM by DW if typeof (adrval^) == tabletype { local (i, adrItem); for i = 1 to sizeof (adrval^) { adrItem = @adrval^ [i]; if typeof (adrItem^) == binarytype { adrItem^ = base64.encode (adrItem^, infinity)}}}; rpcParamTable.[partialaddress] = adrval^}; on sendRpcMessages () { if defined (pta^.adrMemberInfo) { //PBS 9/2/99: this person may not be a member prefsSuite.sendRpcMessages (@rpcParamTable, pta^.adrMemberInfo)}; //PBS 8/17/99: routine moved to top level of prefsSuite Çlocal (xmltext) Çbundle //build the XML representation Çon add (s) Çxmltext = xmltext + s + "\r" Çadd ("<?xml version=\"1.0\"?>") Çadd ("<prefsUpdate>") Çadd ("<group>" + "default" + "</group>") Çadd ("<memberKey>" + nameof (pta^.adrmemberinfo^) + "</memberKey>") Çadd ("<value>" + xml.coercions.frontierValueToTaggedText (@rpcParamTable, 0) + "</value>") Çadd ("</prefsUpdate>") Çbundle //write the file Çif defined (config.prefsServer.prefsDistributorFolder) //PBS 8/10/99: make sure this machine is a prefs distributor Çlocal (folder = config.prefsServer.prefsDistributorFolder) Çloop //get a unique name, write the file Çlocal (f = folder + clock.ticks () + ".xml") Çfile.surefilepath (f) Çif not file.exists (f) Çfile.writewholefile (f, xmltext) Çbreak ÇprefsSuite.init () Çlocal (i, ct = sizeof (config.prefsServer.subscribers), adrsubscriber) Çlocal (params = {"default", nameof (pta^.adrmemberinfo^), rpcParamTable}) Çfor i = 1 to ct Çadrsubscriber = @config.prefsServer.subscribers [i] Çbetty.rpc.client (nameof (adrsubscriber^), adrsubscriber^.port, adrsubscriber^.procedureName, @params, rpcpath:adrsubscriber^.rpcPath, flAsynch:true) Ç<panel title="Register"> Ç<description>This is an experimental feature. If you have a server that can do something interesting with preferences, and if your server can receive XML-RPC messages, you can hook into the preference system at UserLand.Com. We need three pieces of information: a domain name for your server (an IP address will also work), the port that server is running on, and the name of the XML-RPC procedure you want us to call. This routine will be called every time every user updates, so please don't register unless you're serious.</description> Ç<item title="Domain" type="string" adr="prefsRpcHandler.domain"/> Ç<item title="Port" type="string" adr="prefsRpcHandler.port"/> Ç<item title="Procedure name" type="string" adr="prefsRpcHandler.procedureName"/> Ç</panel> return (true)}; local (htmlText = "", indentLevel = 0); on add (s) { htmlText = htmlText + (string.filledString ("\t", indentLevel) + s + "\r");}; prefsSuite.compileIfDirty (); //compile the XML if needed local (panelNum, adrPanel); bundle { //get the number of the panel, the address of its descriptor in the XML structure, set flPrivate page attribute if inputPanel != nil { //caller supplied the panel num panelNum = number (inputPanel); local (i, ctpanels = 0, adrItem, adrtable = @adrWizard^.structure [1]); for i = 1 to sizeOf (adrtable^) { adrItem = @adrtable^[i]; if xml.convertToDisplayName (nameOf (adrItem^)) == "panel" { ++ctpanels; if ctpanels == panelNum { //found it! adrPanel = adrItem; break}}}; if ctpanels < panelNum { scripterror ("Can't display the panel because the wizard doesn't have a panel #" + panelNum + ".")}} else { panelNum = prefsSuite.pathArgsToPanelNum (pathargs, @adrpanel)}; local (flPrivate = false); try { flPrivate = boolean (xml.getAttribute (adrPanel, "private")^)}; pta^.flPrivate = flPrivate}; local (panelTitle, description); bundle { //get the title and description panelTitle = xml.getAttribute (adrPanel, "title")^; if flSetTitle { //PBS 8/19/99: if flSetTitle is false, then the calling page is responsible for setting pta^.title pta^.title = panelTitle}; description = xml.getValue (adrPanel, "description"); description = string.replaceAll (description, "\t", ""); description = string.replaceAll (description, "\r", "<p>")}; on getPrefAddress (partialAddress) { //takes a partial address, returns an address into user's member table local (nomad = pta^.adrMemberInfo, s); loop { if not (partialAddress contains ".") { nomad = @nomad^.[partialAddress]; break}; s = string.nthField (partialAddress, '.', 1); nomad = @nomad^.[s]; if not defined (nomad^) { new (tableType, nomad)}; partialAddress = string.delete (partialAddress, 1, sizeOf (s) + 1)}; return (nomad)}; if pta^.method == "POST" { //PBS 6/12/99: check that required fields are non-empty if flHandleRequiredFields { //PBS 8/10/99: required fields handling can be turned off local (i, adrOneItem, emptyFieldNames = {}); for i = 1 to sizeOf (adrPanel^) { //check whether there are required fields that have not been filled out adrOneItem = @adrPanel^ [i]; if xml.convertToDisplayName (nameOf (adrOneItem^)) == "item" { local (flRequired = false); try { flRequired = boolean (xml.getAttributeValue (adrOneItem, "required"))}; if flRequired { //make sure it exists and is non-empty local (adr = xml.getAttributeValue (adrOneItem, "adr"), flEmpty = false); if not defined (pta^.postArgs.[adr]) { flEmpty = true} else { if sizeOf (pta^.postArgs.[adr]) == 0 { flEmpty = true}}; if flEmpty { emptyFieldNames = emptyFieldNames + xml.getAttributeValue (adrOneItem, "title")}}}}; if emptyFieldNames != {} { //if the emptyFieldNames list contains items, then display errors local (errorMessage = "Please enter the required field"); local (i, ctEmpties); bundle { //build the top error message ctEmpties = sizeOf (emptyFieldNames); if sizeOf (emptyFieldNames) > 1 { errorMessage = errorMessage + "s"}; errorMessage = errorMessage + " "; for i = 1 to sizeOf (emptyFieldNames) { errorMessage = errorMessage + "<b>" + emptyFieldNames [i] + "</b>"; if i < ctEmpties { if ctEmpties > 2 { errorMessage = errorMessage + ", "} else { errorMessage = errorMessage + " "}; if ctEmpties == 2 or i == ctEmpties - 1 { errorMessage = errorMessage + "and "}}}; if ctEmpties < 2 { errorMessage = errorMessage + "."} //" is required." else { errorMessage = errorMessage + "."}; //" are required." add ("<font color=\"red\">" + errorMessage + "</font>")}; flRequiresRedo = true; if adrError != nil { //PBS 8/9/99 -- adrError is optional: make sure it's not nil before trying to deference it. adrError^ = true}}}}; if pta^.method == "POST" and not flRequiresRedo { //process the POSTed data scratchpad.postargs = pta^.postargs; edit (@scratchpad.postargs); ÇCreate a new membership table if needed. if not defined (pta^.adrMemberInfo) and flSignupForm { if defined (pta^.postArgs.["personalInfo.email"]) { local (memberKey = pta^.postArgs.["personalInfo.email"]); try { //validate the email address mainResponder.members.validMailAddress (memberKey)} else { scriptError ("Can't create a membership record because the email address is invalid.")}; local (adrMember = mainResponder.members.getMemberTable (pta^.defaultMembershipGroup, memberKey)); if not defined (adrMember^) { ÇFirst check the password. PBS 9/7/99 if defined (pta^.postArgs.["scratchpassword1"]) { if defined (pta^.postArgs.["scratchpassword2"]) { if pta^.postArgs.["scratchpassword1"] != pta^.postArgs.["scratchpassword2"] { add ("<p><font color=\"red\">Can't sign you up because the two passwords you entered do not match.</font>"); flRequiresRedo = true}}}; if not flRequiresRedo { new (tableType, adrMember); pta^.adrMemberInfo = adrMember; pta^.memberGroupName = pta^.defaultMembershipGroup}} else { //PBS 6/4/99: member already exists, it's an error flRequiresRedo = true; add ("<font color=\"red\">Can't sign up \"" + memberKey + "\" because \"" + memberKey + "\" is already a member.</font>"); if defined (pta^.urls^.memberLogon) { add ("<p><font color=\"red\">If you want to login, even if you forgot your password, go to the " + html.getLink ("Login", pta^.urls^.memberLogon) + " page.</font>")}}}}; if not flRequiresRedo { //PBS 8/10/99: it may have been set false, even though it was false when entering this block local (refreshAfterPost = false); if defined (pta^.postargs.refreshAfterPost) { refreshAfterPost = true; delete (@pta^.postargs.refreshAfterPost)}; local (adrtable = @pta^.postargs, ct = sizeof (adrtable^), i, adrItem, val); for i = 1 to ct { adrItem = @adrtable^ [i]; local (nomad); if defined (pta^.adrMemberInfo) { nomad = pta^.adrMemberInfo}; local (partialaddress = nameof (adrItem^), s); if partialaddress beginswith "scratchpassword" { if partialaddress == "scratchpassword1" { local (otherpassword = adrtable^.["scratchpassword2"]); if adrtable^.["scratchpassword1"] != otherpassword { scriptError ("Can't set the password because the two passwords you entered are not equal.")}; if not (otherpassword == "") { pta^.adrmemberinfo^.password = otherpassword; addPrefToRpcParamTable ("password", @pta^.adrmemberinfo^.password ); //PBS 9/13/99: propagate passwords local (mailaddress = nameof (pta^.adrmemberinfo^)); mainresponder.members.setcookie (mailaddress, otherpassword)}}} else { on setValueCallback (adrval) { //5/22/99; 8:46:15 AM by DW if flcallbacks { local (adrcallback = @adrcallbacks^.setValue); if defined (adrcallback^) { adrcallback^ (partialaddress, adrval)}}; addPrefToRpcParamTable (partialaddress, adrval)}; //7/8/99; 10:03:09 AM by DW //PBS 9/13/99: promoted this line if defined (pta^.adrMemberInfo) { nomad = getPrefAddress (partialaddress); if typeof (adrItem^) == tabletype { //it's a multi-part object local (datasize = sizeof (adrItem^.data)); local (contentType); if defined (adrItem^.["Content-Type"]) { //PBS 8/14/99: make sure Content-Type is defined before checking its value contentType = string.lower (adrItem^.["Content-Type"])}; if datasize > 0 { //this is what you get if you don't specify a file bundle { // 7/27/05; 7:01:15 PM by TAC - upload a picture or any kind of file; GIF, JPEG, and PNG pictures are recognized local (bt = "data"); // binary type, default if contentType beginswith "image" { local (maxbytes = pta^.wizard^.prefs.maxPictureBytes); if datasize > maxbytes { scriptError ("Can't accept the file because it is too large. Maximum is " + string.kBytes (maxbytes) + ".")}; bundle { // get and set height and width of the image local (hwList); if contentType == "image/gif" { hwList = html.getGifHeightWidth (@adrItem^.data)}; if contentType == "image/jpeg" { hwList = html.getJpegHeightWidth (@adrItem^.data)}; if contentType == "image/png" { hwList = html.getPngHeightWidth (@adrItem^.data)}; if hwList != nil { adrItem^.height = hwList [1]; adrItem^.width = hwList [2]}}} else { if defined (pta^.wizard^.prefs.maxFileBytes) { local { maxBytes = pta^.wizard^.prefs.maxFileBytes}; if dataSize > maxBytes { scriptError ("Can't accept the file because it is too large. Maximum is " + string.kBytes (maxBytes) + ".")}}}; adrItem^.data = binary (adrItem^.data); try { // set the binary type bt = user.webserver.prefs.MIME2Binary.[contentType]}; setBinaryType (@adrItem^.data, bt); nomad^ = adrItem^; //copy the table into storage setValueCallback (adrItem)}; Çbundle // old code Çif not contentType beginswith "image" ÇscriptError ("Can't accept the file because it is not an image.") Çlocal (maxbytes = pta^.wizard^.prefs.maxPictureBytes) Çif datasize > maxbytes ÇscriptError ("Can't accept the file because it is too large. Maximum is " + string.kBytes (maxbytes) + ".") Çbundle //set the type attribute of the data Çlocal (bt = nil) Çif contentType == "image/gif" Çbt = "GIFf" Çif contentType == "image/jpeg" Çbt = "JPEG" Çif bt != nil ÇadrItem^.data = binary (adrItem^.data) ÇsetBinaryType (@adrItem^.data, bt) Çnomad^ = adrItem^ //copy the table into storage ÇsetValueCallback (adrItem)}} else { val = adrItem^; if (val == "true") or (val == "false") { val = boolean (val)}; nomad^ = val; setValueCallback (@val)}}}}; sendRpcMessages (); //7/8/99; 10:03:09 AM by DW if refreshAfterPost { ÇPBS 10/30/99: redirect to a different URL by choosing an alternate pathArgs form. ÇIf number, use title; if title, use number. ÇThis works around the 302 FOUND Netscape browser bug. local (panelIdentifier, newPathArgs); try { panelIdentifier = number (pta^.pathArgs); newPathArgs = string.innerCaseName (panelTitle)} else { newPathArgs = panelNum}; Çmainresponder.redirect (pta^.uri + "$" + pta^.pathargs) mainresponder.redirect (pta^.uri + "$" + newPathArgs)}; ÇCall the signup callback, if applicable. PBS 6/5/99 ÇThe signup callback can send email and do similar operations. ÇIf it returns an empty string, then build the form as normal. ÇIf it returns text, then return that text -- the signup callback can control what gets displayed on the page. if flSignupForm and adrSignupCallback != nil { htmlText = adrSignupCallback^ (); if htmlText != "" { return (htmlText)}}}}; bundle { //add the form with the items local (flRequiresMultiPart = false); try {flRequiresMultiPart = boolean (xml.getattribute (adrpanel, "multiPart"))^}; //multiPart attribute is optional if action == nil { action = pagename + "$" + panelnum}; add ("<form name=\"" + paneltitle + "\" action=\"" + action + "\" method=\"POST\"<<xxx>>>"); indentlevel++; bundle { //add hidden item if it has refreshAfterPost attribute try { local (refreshAfterPost = boolean (xml.getattribute (adrpanel, "refreshAfterPost")^)); if refreshAfterPost { add ("<input type=\"hidden\" name=\"refreshAfterPost\" value=\"1\">")}}}; if flIncludeTitle { add ("<h2>" + paneltitle + "</h2>")}; add (description + "<p>"); add ("<table cellpadding=\"7\" cellspacing=\"0\" border=\"0\">"); indentlevel++; local (flShowSubmitButton = false); local (i, adrItem, adr, title, type, popuptext, linkattribute, defaultvalue, flspan, ixitem = 0); for i = 1 to sizeOf (adrPanel^) { adrItem = @adrPanel^ [i]; adr = ""; if xml.convertToDisplayName (nameOf (adrItem^)) == "item" { ixitem++; flShowSubmitButton = true; defaultValue = ""; //PBS 7/12/99: clear out previous default value bundle { //set title title = xml.getattribute (adrItem, "title")^; local (flAddColon = true); if title endswith "?" { flAddColon = false}; if string.trimWhiteSpace (title) == "" { flAddColon = false}; if flAddColon { title = title + ":"}}; type = string.lower (xml.getattribute (adrItem, "type")^); //types are unicase try {adr = xml.getattribute (adrItem, "adr")^}; //adr attribute is optional, for example separators don't have adrs if adr != "" { //JES 7/14/: call callbacks if they exist -- determine if this item should be included if flCallbacks { if defined (adrCallbacks^.includeItem) { try { if not adrCallbacks^.includeItem (adr) { continue}}}}}; if type == "separator" { //very special case if separatorColor == nil { //PBS 10/30/99: Manila sites need to be able to specify separator and separator text color separatorColor = "black"}; if separatorTextColor == nil { separatorTextColor = pta^.bgcolor}; add ("<tr><td colspan=\"2\"><table cellpadding=\"2\" cellspacing=\"0\" width=\"100%\"><tr>"); indentlevel++; add ("<td bgcolor=\"" + separatorColor + "\"><font color=\"" + separatorTextColor + "\"><b>" + title + "</b></font></td>"); //PBS 6/4/99: text in separators is bold add ("</tr></table></td></tr>"); indentlevel--; continue}; bundle { //get popuptext if it's present try { popuptext = xml.getvalue (adrItem, "popuptext")} else { popuptext = ""}}; bundle { //get link attribute if it's present try { linkattribute = xml.getattribute (adrItem, "link")^} else { linkattribute = ""}}; add ("<tr>"); indentlevel++; ÇIf this is a re-do, and this is an empty required field, then ask the user to fill it in. Çif flRequiresRedo and emptyList contains adrItem Çlocal (fieldName = xml.getAttribute (adrItem, "title")^) Çadd ("<td colspan=\"2\"><font color=\"red\"><b>" + fieldName + "</b> is empty. Please fill it in.</font></td></tr>") Çadd ("<tr>") bundle { //set defaultvalue if flRequiresRedo { //PBS 6/12/99: get the value from the POST args if it's a redo defaultValue = pta^.postArgs.[adr]} else { ÇHandle default values. PBS 7/12/99 try { defaultValue = xml.getAttributeValue (adrItem, "default")}; //PBS 7/12/99: get default value from outline if not flSignupForm { if defined (pta^.adrMemberInfo) { with pta^.adrmemberinfo^ { Çdefaultvalue = "" try { local (adrobject = getPrefAddress (adr)); if typeof (adrobject^) == tabletype { //it's a multi-part object defaultvalue = adrobject^.filename} else { defaultvalue = adrobject^}}; bundle { //5/22/99; 7:31:16 AM by DW, call the callback if one is present if flcallbacks { local (adrcallback = @adrcallbacks^.getValue); if defined (adrcallback^) { defaultvalue = adrcallback^ (adr, defaultvalue)}}}}}}}}; //adr is the partial address, the callback should be a big case statement, based on which value is being asked for bundle { //add title local (s); if popuptext != "" { local (shortaddress = panelnum + "," + ixitem); local (href = "href=\"JavaScript: newWindow=openWin( '" + adrwizard^.prefs.popupPageName + "$" + shortaddress + "', 'prefsPopup', '" + string (adrwizard^.prefs.popupWindowAttributes) + "' );newWindow.focus()\""); s = "<a " + href + " title=\"" + string.firstsentence (popuptext) + "..\">" + title + "</a>"} else { Çif string.lower (type) == "picture" Çlocal (s = "<a href=\"" + adrwizard^.prefs.picturePageName + "$" + adr + "\">" + title + "</a>") Çadd ("<td valign=\"top\">" + s + "</td>") if linkattribute != ""... [truncated message content] |