PageRenderTime 56ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/saf/lib/MailForm/MailForm.php

https://github.com/lux/sitellite
PHP | 1490 lines | 672 code | 104 blank | 714 comment | 158 complexity | 2b08d2b80d5864ca822e9d8768b783a9 MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.1, Apache-2.0, GPL-3.0
  1. <?php
  2. //
  3. // +----------------------------------------------------------------------+
  4. // | Sitellite Content Management System |
  5. // +----------------------------------------------------------------------+
  6. // | Copyright (c) 2010 Sitellite.org Community |
  7. // +----------------------------------------------------------------------+
  8. // | This software is released under the GNU GPL License. |
  9. // | Please see the accompanying file docs/LICENSE for licensing details. |
  10. // | |
  11. // | You should have received a copy of the GNU GPL License |
  12. // | along with this program; if not, visit www.sitellite.org. |
  13. // | The license text is also available at the following web site |
  14. // | address: <http://www.sitellite.org/index/license |
  15. // +----------------------------------------------------------------------+
  16. // | Authors: John Luxford <john.luxford@gmail.com> |
  17. // +----------------------------------------------------------------------+
  18. //
  19. // MailForm provides methods for generating, validating and handling HTML
  20. // forms.
  21. //
  22. // resolved tickets:
  23. // #171 nolist error_mode.
  24. //
  25. $GLOBALS['loader']->import ('saf.MailForm.Rule');
  26. /**
  27. * MailForm provides methods for generating, validating, and handling web
  28. * forms. Forms can be handled automatically (sent to an email address), or handled
  29. * using "action files". Action files are passed to the handle () method, and can be
  30. * used to do anything you want to the form values. MailForm will generate forms
  31. * for you, using a basic HTML tabled layout, which is okay for most applications,
  32. * or you can have complete visual customization through form templates. MailForm
  33. * also exposes an EasyText tag, which makes it much quicker to create fully
  34. * validating forms in minutes.
  35. *
  36. * New in 2.0:
  37. * - 16 widgets, including date and time widgets, a directory listing widget, and more.
  38. * - 11 different validation rules, including a regular expression rule, cross
  39. * form widget comparisons (good for password verification widgets), and calling
  40. * to pre-defined functions.
  41. * - Many speed improvements, such as dynamic loading of widgets, so your form
  42. * only loads the necessary widgets.
  43. * - MailForm 2.0 is a complete rewrite, which has a much cleaner API, although it
  44. * is not backward compatible with 1.0, other than through its EasyText tag.
  45. *
  46. * Widget Types:
  47. * - checkbox
  48. * - date
  49. * - datetime
  50. * - dirlist
  51. * - file
  52. * - hidden
  53. * - image
  54. * - multiple (multi-line select box)
  55. * - password
  56. * - radio
  57. * - reset
  58. * - select
  59. * - submit
  60. * - text
  61. * - textarea
  62. * - time
  63. *
  64. * Validation Rules:
  65. * - is "value"
  66. * - contains "some value"
  67. * - regex "some regex"
  68. * - equals "anotherfield"
  69. * - not empty
  70. * - length "6+" (eg: 6, 6+, 6-12, 12-)
  71. * - gt "value"
  72. * - ge "value"
  73. * - lt "value"
  74. * - le "value"
  75. * - func "func_name" (or function "func_name")
  76. *
  77. * Miscellaneous:
  78. * - Do not use underscores (_) in the naming of complex widgets (ie. the datetime
  79. * widget).
  80. *
  81. * New in 2.2:
  82. * - Added an 'Extra' parameter to the EasyText =MailForm tag parameter list, so
  83. * that the File widget can be used without having to resort to coding the form
  84. * in PHP instead.
  85. * - Fixed a bug in the EasyText() method, where the value of the Email property
  86. * wasn't being passed on.
  87. *
  88. * New in 2.4:
  89. * - Changed a reference to "$GLOBALS['PHP_SELF']" to "global $_SERVER; $_SERVER['PHP_SELF']"
  90. * so that it works with register_globals off.
  91. * - Added File widgets to the list of widgets skipped on the isset() condition in invalid(),
  92. * because some browsers don't send file fields at all if there is no file. This may inhibit
  93. * file field validation, but it's necessary due to inconsistencies across browsers.
  94. *
  95. * New in 2.6:
  96. * - Moved the validation layer into the Widget level. See saf.MailForm.Widget and
  97. * saf.MailForm.Rule for more info.
  98. * - Added a template example to the DocReader docs below.
  99. *
  100. * New in 2.8:
  101. * - Fixed a bug in getValues() that caused the $vars passed to a validation function
  102. * to be blank.
  103. * - Fixed EasyText() to use the new addRule() method instead of validation(), and
  104. * added the ability to include multiple rules for the same widget through EasyText()
  105. * using commas as separators.
  106. * - Added a $submitted property which is used by setValues() to keep an accurate
  107. * reading on widgets whose $passover_isset property is set to true.
  108. *
  109. * New in 3.0:
  110. * - Added an $_attrs property and three new methods, attr(), unsetAttr(), and getAttrs().
  111. * - Deprecated the $extra property in favour of the new property and methods just
  112. * added.
  113. * - Improved the email output formatting in handle().
  114. *
  115. * New in 3.2:
  116. * - Deprecated the handle() method in favour of a setHandler(), run(), and onSubmit()
  117. * methods. These methods make it easier to subclass MailForm to unify the
  118. * location of the form definition and handling.
  119. * - Added $sendTo, $sendFrom, $sendExtra, $screenReply, and $handler support
  120. * properties to the new methods.
  121. * - Added a parseSettings() method, which makes it much easier to create new
  122. * forms.
  123. * - getValues() and invalid() now do not use a passed $cgi object, and instead
  124. * both rely on a global $cgi object, which is set automatically in the Sitellite
  125. * Content Server, Content Manager, and the init.php script in SAF itself, so
  126. * it's reasonable to assume it will be available. This doesn't affect code
  127. * that still passes the object to invalid(), and the parameter was deprecated
  128. * in getValues() already anyway.
  129. * - getValues() now uses a new property called $uploadFiles, which tells it to
  130. * upload files from file widgets for you automatically. This breaks backward
  131. * compatibility as a default, but you can pass a false value to achieve the
  132. * old behaviour.
  133. *
  134. * New in 3.4:
  135. * - Added makeAssoc() and rememberFields() methods, for use with the Sitellite
  136. * Content Server form API.
  137. * - Added a $title property, which will show in a top-level header above the form
  138. * if provided.
  139. * - Added a global formdata_get() function which returns a key/value list from
  140. * the global $formdata array defined in the application property files.
  141. * - Added a $uploadFile parameter to run(), which allows finer control over
  142. * file upload handling.
  143. *
  144. * New in 3.6:
  145. * - Removed the EasyText() and EasyTextInit() methods.
  146. * - Removed the saf.MailForm.Wizard package, since SCS now provides a more
  147. * flexible, elegant, and clean, and less buggy way of accomplishing the
  148. * same effect.
  149. * - Removed the EasyText widget.
  150. * - Added the ability to report all invalid rules at once, instead of just one.
  151. * However, just one is still the default.
  152. *
  153. * New in 3.8:
  154. * - Added the ability to call addWidget() by specifying the type as a loader path
  155. * to an alternate location. This does not affect backward compatibility in
  156. * any way.
  157. * - Added the ability to call addWidget () by passing a widget object as the
  158. * $type parameter.
  159. *
  160. * New in 4.0:
  161. * - FormHelp ins now integrated into MailForm. In settings.php, you can
  162. * specify 'formhelp = yes' under [Form] and 'formhelp = Message' under
  163. * any widget and the display of it is automatic.
  164. *
  165. * <code>
  166. * <?php
  167. *
  168. * <?php
  169. *
  170. * $form = new MailForm;
  171. * $form->template = 'mf2template.spt';
  172. * $form->message = 'Please take a moment to fill out our form.';
  173. *
  174. * // old way to set attributes
  175. * //$form->extra = 'enctype="multipart/form-data"';
  176. *
  177. * // new way to set attributes
  178. * $form->attr ('enctype', 'multipart/form-data');
  179. *
  180. * // build the form
  181. *
  182. * // standard usage:
  183. * $form->addWidget ('text', 'username');
  184. * $form->widgets['username']->display_value = 'Username (min. 6 chars)';
  185. * $form->widgets['username']->addRule ('length "6-24"', 'Your username must be between 6 and 24 characters in length. Please fix this to continue.');
  186. *
  187. * // or if you prefer:
  188. * $password =& $form->addWidget ('password', 'password');
  189. * $password->addRule ('length "6-24"', 'Your password must be between 6 and 24 characters in length. Please fix this to continue.');
  190. *
  191. * $verify =& $form->addWidget ('password', 'verify');
  192. * $verify->display_value = 'Verify Password';
  193. * $verify->addRule ('equals "password"', 'Your passwords did not match. Please fix this to continue.');
  194. *
  195. * $form->addWidget ('text', 'firstname');
  196. * $form->widgets['firstname']->validation ('not empty');
  197. * $form->addWidget ('text', 'lastname');
  198. * $form->widgets['lastname']->validation ('not empty');
  199. *
  200. * $province =& $form->addWidget ('select', 'province');
  201. * $province->setValues (array (
  202. * 'BC' => 'British Columbia',
  203. * 'MB' => 'Manitoba',
  204. * 'ON' => 'Ontario',
  205. * ));
  206. * $province->default_value = 'MB';
  207. *
  208. * // the new 'dirlist' widget type
  209. * $dlist =& $form->addWidget ('dirlist', 'dltest');
  210. * $dlist->directory = 'pix';
  211. * $dlist->extensions = array ('jpg', 'gif', 'png');
  212. *
  213. * // the new 'date' widget type
  214. * $form->addWidget ('date', 'birth-date');
  215. * $form->widgets['birth-date']->display_value = 'Birth Date';
  216. *
  217. * $textarea =& $form->addWidget ('textarea', 'comments');
  218. * $textarea->setValue ('hello world!');
  219. * $textarea->addRule ('not empty', 'You must enter a comment. Please fix this to continue.');
  220. *
  221. * $send =& $form->addWidget ('submit', 'send');
  222. * $send->setValues ('Submit!');
  223. *
  224. * if ($form->invalid ($cgi)) {
  225. *
  226. * // form is invalid or has not been set yet
  227. * $form->setValues ($cgi, $invalid_field);
  228. * echo $form->show ('inc/html/formtemplate.spt');
  229. *
  230. * } else {
  231. *
  232. * // handle submitted form
  233. *
  234. * if (! $form->handle ('john.luxford@gmail.com', 'Mail Form')) {
  235. * echo 'Error: ' . $form->error_message;
  236. * }
  237. *
  238. * }
  239. *
  240. * ? >
  241. *
  242. * -----
  243. * inc/html/formtemplate.spt (Note: Replace ** with { and }):
  244. *
  245. * <form method="**mailform_method**" action="**mailform_action**" **mailform_extra**>
  246. * <p>**mailform_message**</p>
  247. *
  248. * <p>Username<br />**username**</p>
  249. * <p>Password<br />**password**</p>
  250. * <p>Verify Password<br />**verify**</p>
  251. * <p>First Name<br />**firstname**</p>
  252. * <p>Last Name<br />**lastname**</p>
  253. * <p>Province<br />**province**</p>
  254. * <p>Pick an image<br />**dltest**</p>
  255. * <p>Birthday<br />**birth-date**</p>
  256. * <p>Comments<br />**comments**</p>
  257. * <p>**send**</p>
  258. *
  259. * </form>
  260. *
  261. *
  262. * ? >
  263. * </code>
  264. *
  265. * @package MailForm
  266. * @author John Luxford <john.luxford@gmail.com>
  267. * @license http://www.sitellite.org/index/license GNU GPL License
  268. * @version 4.0, 2004-01-29, $Id: MailForm.php,v 1.18 2008/05/20 05:43:57 lux Exp $
  269. * @access public
  270. *
  271. */
  272. class MailForm {
  273. /**
  274. * Contains the name of the widget that did not validate during
  275. * the last call to the invalid () method.
  276. *
  277. * @access public
  278. *
  279. */
  280. var $invalid_field = '';
  281. /**
  282. * The value of the method attribute of the HTML form tag.
  283. * $method is actually an alias for $_attrs['method'].
  284. *
  285. * @access public
  286. *
  287. */
  288. var $method;
  289. /**
  290. * The value of the action attribute of the HTML form tag.
  291. * $action is actually an alias for $_attrs['action'].
  292. *
  293. * @access public
  294. *
  295. */
  296. var $action;
  297. /**
  298. * An array of form widgets.
  299. *
  300. * @access public
  301. *
  302. */
  303. var $widgets = array ();
  304. /**
  305. * The optional template file or data used to customize the look
  306. * of the form.
  307. *
  308. * @access public
  309. *
  310. */
  311. var $template;
  312. /**
  313. * The title to be displayed at the top of the form.
  314. *
  315. * @access public
  316. *
  317. */
  318. var $title;
  319. /**
  320. * The initial message to be displayed at the top of the form.
  321. *
  322. * @access public
  323. *
  324. */
  325. var $message;
  326. /**
  327. * A way to pass extra parameters to the HTML form tag, for
  328. * example 'enctype="multipart/formdata"'. Notice: This property is
  329. * deprecated in favour of the $_attrs list and the attr() and unset()
  330. * methods.
  331. *
  332. * @access public
  333. *
  334. */
  335. var $extra;
  336. /**
  337. * Contains the message from any internal errors.
  338. *
  339. * @access public
  340. *
  341. */
  342. var $error_message;
  343. /**
  344. * Determines the way in which error messages are displayed.
  345. * The default ('single') is to display the error message for the first
  346. * invalid field only. Another ('all') is to display a list of all
  347. * invalid fields with their corresponding error messages. Please note
  348. * that $error_mode 'all' assumes that a custom error message is provided
  349. * for every rule. The other ('nolist') is to display no list at all, but only
  350. * a message "the fields were not filled in correctly".
  351. *
  352. * @access public
  353. *
  354. */
  355. var $error_mode = 'single';
  356. /**
  357. * A list of all invalid fields in the form, and their corresponding
  358. * error messages.
  359. *
  360. * @access public
  361. *
  362. */
  363. var $invalid = array ();
  364. /**
  365. * Contains a true or false value as to whether the form has been
  366. * submitted successfully or not. An invalid form will contain false.
  367. * This value is used internally by the setValues() method.
  368. *
  369. * @access private
  370. *
  371. */
  372. var $submitted = false;
  373. /**
  374. * The name of this form. Optional. $name is actually an alias
  375. * for $_attrs['name'].
  376. *
  377. * @access public
  378. *
  379. */
  380. var $name;
  381. /**
  382. * This contains a list of attributes of the HTML form tag.
  383. *
  384. * @access private
  385. *
  386. */
  387. var $_attrs = array ();
  388. /**
  389. * The email address to send the form to in the default handler.
  390. *
  391. * @access public
  392. *
  393. */
  394. var $sendTo;
  395. /**
  396. * The email address to send the form from in the default handler.
  397. *
  398. * @access public
  399. *
  400. */
  401. var $sendFrom = '';
  402. /**
  403. * Any extra parameters for the mail() function in the default handler.
  404. *
  405. * @access public
  406. *
  407. */
  408. var $sendExtra = '';
  409. /**
  410. * The subject line of the email to send from the default handler.
  411. *
  412. * @access public
  413. *
  414. */
  415. var $sendSubject = 'Mail Form';
  416. /**
  417. * The response to return upon a successfully submitted form in the
  418. * default handler. Defaults to "Thank you. Your form has been sent."
  419. *
  420. * @access public
  421. *
  422. */
  423. var $screenReply = 'Thank you. Your form has been sent.';
  424. /**
  425. * The function or object method to use to handle the submitted form.
  426. * This function or method will be called by the run() method. Use the
  427. * setHandler() method to change this setting.
  428. *
  429. * @access public
  430. *
  431. */
  432. var $handler;
  433. /**
  434. * Whether to upload files automatically or to leave them for a custom
  435. * saving mechanism.
  436. *
  437. * @access public
  438. *
  439. */
  440. var $uploadFiles = true;
  441. /**
  442. * Whether to verify the REQUEST_METHOD and HTTP_REFERER headers to make
  443. * it more difficult (although not impossible) for spammers to abuse your
  444. * form. Note that this can be enabled in a form's settings file under
  445. * the [Form] block via: verify_sender = yes
  446. *
  447. * @access public
  448. *
  449. */
  450. var $verify_sender = false;
  451. /**
  452. * Whether to strip all HTML and PHP tags/code from all input parameters.
  453. * This is off by default because it would break forms with the Xed editor
  454. * by default, so it must be enabled as needed. Note that this can be
  455. * enabled in a form's settings file under the [Form] block via:
  456. * clean_input = yes
  457. *
  458. * @access public
  459. *
  460. */
  461. var $clean_input = false;
  462. /**
  463. * Whether to verify the remote address of the form submitter against
  464. * a list of invalid IP addresses in the database table
  465. * sitellite_form_blacklist so as to prevent repeated abuse from a single
  466. * source.
  467. *
  468. * @access public
  469. *
  470. */
  471. var $blacklist = true;
  472. /**
  473. * Whether to verify that the submitter can accept session data, which
  474. * helps ensure they are a legitimate human user. Passing session
  475. * verification requires cookies to be enabled for the submitter, which
  476. * may help prevent abuse in combination with the other abuse-prevention
  477. * techniques because a spambot may ignore the cookie, however this
  478. * restricts forms for legitimate visitors who have cookies disabled
  479. * in their browser (only a very small number of users disable cookies,
  480. * but some do). To disable for a single form, add verify_session = no
  481. * to its settings.php form.
  482. *
  483. * @access public
  484. *
  485. */
  486. var $verify_session = true;
  487. /**
  488. * Whether this form should tie into Sitellite's autosave capabilities.
  489. * Please note that the autosave handler is only available to authenticated
  490. * users and not to anonymous forms.
  491. *
  492. * @access public
  493. *
  494. */
  495. var $autosave = false;
  496. /**
  497. * The context of the form. If this is set to 'action' then the title of
  498. * the form will be set by calling page_title() instead of outputting an
  499. * <h1> tag.
  500. */
  501. var $context = false;
  502. /**
  503. * Constructor Method. Action will be set to $PHP_SELF if it
  504. * is empty, unless a global $site object is defined in which case the
  505. * action with be $site->url . $PHP_SELF.
  506. *
  507. * @access public
  508. * @param string $action
  509. * @param string $method
  510. *
  511. */
  512. function MailForm ($action = '', $method = 'post') {
  513. $this->method = $method;
  514. if (empty ($action)) {
  515. if (function_exists ('site_current')) {
  516. $action = site_current ();
  517. } else {
  518. global $_SERVER;
  519. $action = $_SERVER['PHP_SELF'];
  520. }
  521. /*if (is_object ($GLOBALS['site'])) {
  522. global $site;
  523. $action = $site->url . $action;
  524. }*/
  525. }
  526. $this->action = $action;
  527. $GLOBALS['loader']->import ('saf.MailForm.Widget');
  528. // set up the $_attrs list
  529. $this->_attrs['action'] =& $this->action;
  530. $this->_attrs['method'] =& $this->method;
  531. $this->name = false;
  532. $this->_attrs['name'] =& $this->name;
  533. $this->handler = array (&$this, 'onSubmit');
  534. // attempt to automatically parse the settings.php file
  535. $cls = strtolower (get_class ($this));
  536. if ($cls != 'mailform') {
  537. if (function_exists ('site_current')) {
  538. $this->action = site_current ();
  539. } else {
  540. $this->action = $_SERVER['PHP_SELF'];
  541. }
  542. $this->_attrs['action'] =& $this->action;
  543. $app = loader_app ();
  544. if (strpos ($action, ':') === 1) {
  545. $action = str_replace ('\\', '/', $action);
  546. }
  547. list ($misc, $path) = explode ($app . '/forms/', $action);
  548. $box = dirname ($path);
  549. if (@file_exists ('inc/app/' . $app . '/forms/' . $box . '/settings.php')) {
  550. $this->parseSettings ('inc/app/' . $app . '/forms/' . $box . '/settings.php');
  551. }
  552. }
  553. }
  554. /**
  555. * Adds another widget to the form. If the $type is specified as
  556. * a loader path, it will import from the proper location outside of
  557. * saf.MailForm.Widget.*, and if you send an object as the $type value
  558. * addWidget() will use that object as the widget (so make sure it is one!),
  559. * as of version 3.8.
  560. *
  561. * @access public
  562. * @param string $type
  563. * @param string $name
  564. * @return object reference
  565. *
  566. */
  567. function &addWidget ($type, $name) {
  568. if (is_object ($type)) {
  569. $this->widgets[$name] =& $type;
  570. $this->widgets[$name]->form =& $this;
  571. return $this->widgets[$name];
  572. } elseif (strpos ($type, '.') !== false) {
  573. loader_import ($type);
  574. $pieces = explode ('.', $type);
  575. $cls = 'MF_Widget_' . strtolower (array_pop ($pieces));
  576. } else {
  577. $cls = 'MF_Widget_' . $type;
  578. loader_import ('saf.MailForm.Widget.' . ucfirst ($type));
  579. }
  580. $this->widgets[$name] = new $cls ($name);
  581. $this->widgets[$name]->form =& $this;
  582. return $this->widgets[$name];
  583. }
  584. /**
  585. * Validates the form values against a global $cgi object. Used in
  586. * the logic of "if the form is invalid then...". Also sets an internal
  587. * $invalid_field property. Returns true if the form is invalid or has not
  588. * been filled out yet. If the form passes (false returned), it also sets
  589. * the $submitted value to true.
  590. *
  591. * @access public
  592. * @return boolean
  593. *
  594. */
  595. function invalid () {
  596. global $cgi;
  597. $this->invalid = array ();
  598. $this->submitted = false;
  599. // determine if form has been submitted (based on submit buttons only)
  600. // making sure form still submits if there are more than one submit button
  601. $ret = true;
  602. $tpl = array ();
  603. foreach ($this->widgets as $k => $v) {
  604. if (in_array (strtolower (get_class ($v)), array ('mf_widget_submit', 'mf_widget_msubmit')) && isset ($cgi->{$k})) {
  605. $ret = false;
  606. break;
  607. } elseif (strtolower (get_class ($v)) == 'mf_widget_image' && isset ($cgi->{$k . '_x'})) {
  608. $ret = false;
  609. break;
  610. } elseif (strtolower (get_class ($v)) == 'mf_widget_template' && count ($v->submitButtons) > 0) {
  611. $tpl[$k] = $v->submitButtons;
  612. }
  613. }
  614. if ($ret) {
  615. foreach ($tpl as $k => $buttons) {
  616. foreach ($buttons as $button) {
  617. if (isset ($cgi->{$button})) {
  618. $ret = false;
  619. break;
  620. }
  621. }
  622. }
  623. if ($ret) {
  624. // form not yet submitted
  625. return true;
  626. }
  627. }
  628. $ret = false;
  629. foreach (array_keys ($this->widgets) as $key) {
  630. $widget =& $this->widgets[$key];
  631. // must compile value of widget here, so compound widgets can validate
  632. $widget_value = $widget->getValue ($cgi);
  633. if (in_array (strtolower (get_class ($widget)), array ('mf_widget_submit', 'mf_widget_msubmit', 'mf_widget_image'))) {
  634. // we've already checked submit buttons
  635. continue;
  636. } elseif (! $widget->passover_isset && ! isset ($cgi->{$key})) {
  637. // specified field is missing, assuming form not yet submitted
  638. return true;
  639. }
  640. //if ($key == 'password') {
  641. // echo 'aha!';
  642. //}
  643. if (! $widget->validate ($widget_value, $this, $cgi)) {
  644. if (! $ret) {
  645. $this->invalid_field = $widget->name;
  646. $ret = true;
  647. }
  648. $this->invalid[$widget->name] = $widget->error_message;
  649. }
  650. }
  651. $this->submitted = true;
  652. if ($ret) {
  653. return true;
  654. }
  655. if ($this->verify_sender) {
  656. if (! $this->verifyRequestMethod ()) {
  657. die ('Invalid request method!');
  658. }
  659. if (! $this->verifyReferer ()) {
  660. die ('Invalid referrer!');
  661. }
  662. }
  663. return false;
  664. }
  665. /**
  666. * Manually set a specific field to be invalid, including a custom error message.
  667. * Useful for setting an error message during the onSubmit() before calling
  668. * return $this->show(); again.
  669. *
  670. * @access public
  671. * @param string $field
  672. * @param string $message
  673. *
  674. */
  675. function setInvalid ($field, $message) {
  676. $this->invalid_field = $field;
  677. $this->invalid[$field] = $message;
  678. $this->widgets[$field]->error_message = $message;
  679. }
  680. /**
  681. * Sets the values of the form widgets from a provided CGI object.
  682. * The second parameter is deprecated.
  683. *
  684. * @access public
  685. * @param object $cgi
  686. * @param boolean $invalid
  687. *
  688. */
  689. function setValues ($cgi, $invalid = false) {
  690. foreach ($cgi->param as $key) {
  691. $value = $cgi->{$key};
  692. if (is_object ($this->widgets[$key])) {
  693. $this->widgets[$key]->setValue ($value);
  694. } elseif (preg_match ('/^(MF_)+([a-zA-Z0-9-]+)_([A-Z0-9_]+)$/', $key, $regs)) {
  695. //echo '<pre>'; print_r ($regs); echo '</pre>';
  696. if (is_object ($this->widgets[$regs[2]])) {
  697. $this->widgets[$regs[2]]->setValue ($value, $regs[3]);
  698. }
  699. }
  700. }
  701. // loop through widgets who are not set but who have passover_isset set to true
  702. // and set their values to ''.
  703. if ($this->submitted) {
  704. foreach ($this->widgets as $key => $widget) {
  705. if ($widget->passover_isset && ! isset ($cgi->{$key})) {
  706. $this->widgets[$key]->setValue ('');
  707. }
  708. }
  709. }
  710. $this->cgi = $cgi;
  711. }
  712. /**
  713. * Generates the HTML form. You can provide an optional template
  714. * to customize the look of the form. Template directives (ie. ##field##)
  715. * must be provided for each form widget, as well as ##mailform_action## and
  716. * ##mailform_method##, which correspond to the action and method attributes
  717. * of the HTML form tag.
  718. *
  719. * @access public
  720. * @param string $template
  721. * @return string
  722. *
  723. */
  724. function show ($template = '') {
  725. /*if (session_pref ('browse_level') == 'normal') {
  726. foreach ($this->widgets as $key => $widget) {
  727. if ($widget->advanced) {
  728. $this->widgets[$key] =& $this->widgets[$key]->changeType ('hidden');
  729. }
  730. }
  731. }*/
  732. if (! empty ($template)) {
  733. // last minute template setting
  734. $this->template = $template;
  735. }
  736. if ($this->formhelp) {
  737. page_add_script (site_prefix () . '/js/formhelp-compressed.js');
  738. }
  739. if ($this->autosave) {
  740. global $cgi;
  741. loader_import ('saf.MailForm.Autosave');
  742. $a = new Autosave ();
  743. if ($a->has_draft ()) {
  744. if ($cgi->_autosave_start_from == intl_get ('Restore your previous editing session')) {
  745. $data = $a->retrieve ();
  746. foreach ($data as $k => $v) {
  747. if (is_object ($this->widgets[$k])) {
  748. $this->widgets[$k]->setValue ($v);
  749. }
  750. $cgi->{$k} = $v;
  751. $cgi->param[] = $k;
  752. }
  753. } elseif ($cgi->_autosave_start_from == intl_get ('Start from the currently saved version')) {
  754. $a->clear ();
  755. } else {
  756. // has an existing autosave version, prompt for action
  757. return '<p>' . intl_get ('An auto-saved edit of this form has been found from a previous editing session. Would you like to continue from your previous editing session, or start from the currently saved version?') . '</p>'
  758. . '<form method="post" action="' . $_SERVER['REQUEST_URI'] . '">'
  759. . '<p><input type="submit" name="_autosave_start_from" value="' . intl_get ('Restore your previous editing session') . '" /> &nbsp; &nbsp; '
  760. . '<input type="submit" name="_autosave_start_from" value="' . intl_get ('Start from the currently saved version') . '" /></p>'
  761. . '</form>';
  762. }
  763. }
  764. page_add_script (site_prefix () . '/js/rpc.js');
  765. page_add_script (site_prefix () . '/js/autosave.js');
  766. }
  767. if (! empty ($this->template)) {
  768. // use template to display form
  769. $form_contents = array ();
  770. // determine appropriate instructional message
  771. if (! empty ($this->invalid_field)) {
  772. if ($this->error_mode == 'single') {
  773. // display only the first error message (the default)
  774. if (! empty ($this->widgets[$this->invalid_field]->error_message)) {
  775. $form_contents['mailform_message'] = $this->widgets[$this->invalid_field]->error_message;
  776. } else {
  777. $form_contents['mailform_message'] = intl_get ('Oops! The following field was not filled in correctly:') . ' ' .
  778. $this->widgets[$this->invalid_field]->display_value .
  779. '. ' . intl_get ('Please fix this before continuing.');
  780. }
  781. $this->widgets[$this->invalid_field]->invalid = true;
  782. // Start: SEMIAS #171 nolist error_mode.
  783. } elseif ($this->error_mode == 'nolist') {
  784. // do not display error messages
  785. $form_contents['mailform_message'] = intl_get ('The following fields were not filled in correctly') . ".";
  786. foreach ($this->invalid as $name => $message) {
  787. // $_message .= TAB . '<li>' . $message . '</li>' . NEWLINE;
  788. $this->widgets[$name]->invalid = true;
  789. }
  790. // END: SEMIAS
  791. } else {
  792. // display all error messages
  793. $form_contents['mailform_message'] = intl_get ('Oops! The following information must be corrected in order to continue:') . NEWLINE;
  794. $form_contents['mailform_message'] .= '<ul>' . NEWLINE;
  795. foreach ($this->invalid as $name => $message) {
  796. $form_contents['mailform_message'] .= TAB . '<li>' . $message . '</li>' . NEWLINE;
  797. $this->widgets[$name]->invalid = true;
  798. }
  799. $form_contents['mailform_message'] .= '</ul>' . NEWLINE;
  800. }
  801. } else {
  802. $form_contents['mailform_message'] = $this->message;
  803. }
  804. foreach ($this->widgets as $key =>$widget) {
  805. //$form_contents[$key] = str_replace ('##', 'SITELLITE_DOUBLE_POUND_SUBSTITUTION', $widget->display (0));
  806. if (! is_object ($this->widgets[$key]->form)) {
  807. $this->widgets[$key]->form =& $this;
  808. }
  809. $form_contents[$key] = $this->widgets[$key]->display (0);
  810. }
  811. $form_contents['mailform_title'] = $this->title;
  812. $form_contents['mailform_method'] = $this->method;
  813. $form_contents['mailform_action'] = $this->action;
  814. $form_contents['mailform_extra'] = $this->extra;
  815. $form_contents['mailform_attrs'] = $this->getAttrs ();
  816. global $simple;
  817. //$loader->import ('saf.Template.Simple');
  818. //$tpl = new SimpleTemplate ('', SIMPLE_TEMPLATE_DELIM_POUND);
  819. //$simple = new SimpleTemplate ('');
  820. $return_data = $simple->fill ($this->template, $form_contents);
  821. //return str_replace ('SITELLITE_DOUBLE_POUND_SUBSTITUTION', '##', $return_data);
  822. return $return_data;
  823. } else {
  824. // determine appropriate instructional message
  825. $_message = '';
  826. if (! empty ($this->invalid_field)) {
  827. if ($this->error_mode == 'single') {
  828. if (! empty ($this->widgets[$this->invalid_field]->error_message)) {
  829. $_message .= '<p class="invalid">' . $this->widgets[$this->invalid_field]->error_message . "</p>\n";
  830. } else {
  831. $_message .= '<p class="invalid">' . intl_get ('Oops! The following field was not filled in correctly:') . ' ' .
  832. $this->widgets[$this->invalid_field]->display_value .
  833. '. ' . intl_get ('Please fix this before continuing.') . "</p>\n";
  834. }
  835. $this->widgets[$this->invalid_field]->invalid = true;
  836. // Start: SEMIAS #171 nolist error_mode.
  837. } elseif ($this->error_mode == 'nolist') {
  838. // display no error messages at all
  839. $_message .= '<p class="invalid">' . intl_get ('The fields marked below were not filled in correctly') . ".</p>\n" ;
  840. foreach ($this->invalid as $name => $message) {
  841. $this->widgets[$name]->invalid = true;
  842. }
  843. // END: SEMIAS
  844. } else {
  845. // display all error messages
  846. $_message .= '<p class="invalid">' . intl_get ('Oops! The following information must be corrected in order to continue:') . NEWLINE;
  847. $_message .= '<ul>' . NEWLINE;
  848. foreach ($this->invalid as $name => $message) {
  849. $_message .= TAB . '<li>' . $message . '</li>' . NEWLINE;
  850. $this->widgets[$name]->invalid = true;
  851. }
  852. $_message .= '</ul>' . NEWLINE . '</p>' . NEWLINEx2;
  853. }
  854. } elseif (! empty ($this->message)) {
  855. $_message .= '<p>' . $this->message . "</p>\n";
  856. }
  857. $_widgets = '';
  858. foreach ($this->widgets as $key => $widget) {
  859. if (! method_exists ($this->widgets[$key], 'display')) {
  860. die ('Widget "' . $key . '" has no display() method!');
  861. }
  862. if (! is_object ($this->widgets[$key]->form)) {
  863. $this->widgets[$key]->form =& $this;
  864. }
  865. $_widgets .= $this->widgets[$key]->display (1);
  866. }
  867. $attrstr = $this->getAttrs ();
  868. if (! empty ($this->name)) {
  869. $data = '<form ' . $attrstr . ' ' . $this->extra . '>' . "\n";
  870. } else {
  871. $data = '<form ' . $attrstr . ' ' . $this->extra . '>' . "\n";
  872. }
  873. if (! empty ($this->title)) {
  874. if ($this->context == 'action') {
  875. page_title ($this->title);
  876. } else {
  877. $data .= '<h1>' . $this->title . '</h1>';
  878. }
  879. }
  880. $data .= $_message;
  881. $align = empty ($this->align) ? 'center' : $this->align;
  882. //$data .= '<table border="0" cellspacing="0" cellpadding="0" align="' . $align . '">' . "\n";
  883. $data .= '<table border="0" cellspacing="1" cellpadding="3" align="' . $align . '">' . "\n";
  884. $data .= $_widgets;
  885. return $data . '</table>' . "\n" . '</form>';
  886. }
  887. }
  888. /**
  889. * Returns the form values as an associative array. If $uploadFiles
  890. * is set to true, it will return the saved path or false for file widgets,
  891. * otherwise it will return the saf.CGI.UploadedFile object and not act
  892. * on the object for you.
  893. *
  894. * @access public
  895. * @param boolean $uploadFiles
  896. * @return associative array
  897. *
  898. */
  899. function getValues () {
  900. global $cgi;
  901. $uploadFiles = $this->uploadFiles;
  902. $return = array ();
  903. foreach ($this->widgets as $key => $obj) {
  904. if ($uploadFiles && strtolower (get_class ($obj)) == 'mf_widget_file') {
  905. $return[$key] = $obj->move ();
  906. } else if ($uploadFiles && strtolower (get_class ($obj)) == 'mf_widget_mfile') {
  907. $return[$key] = $obj->move ();
  908. } else {
  909. if (is_object ($cgi)) {
  910. $return[$key] = $obj->getValue ($cgi);
  911. } else {
  912. $return[$key] = $obj->getValue ();
  913. }
  914. }
  915. }
  916. return $return;
  917. }
  918. /**
  919. * Sets the function to use to handle the output of the current form.
  920. * To specify a method of an object, pass it an array with an object reference
  921. * as the first element and the method name as the second. The default handler
  922. * is the internal onSubmit(). The handler is called using call_user_func()
  923. * in the run() method.
  924. *
  925. * @access public
  926. * @param mixed $func
  927. *
  928. */
  929. function setHandler ($func) {
  930. $this->handler = $func;
  931. }
  932. /**
  933. * Runs the form and returns either the rendered form or the output
  934. * of the handler function. $uploadFiles can be set to false to cause the
  935. * getValues() method not to call move() on File widgets. This is useful
  936. * for situations when you need to do something other than simply save the
  937. * file to a predetermined folder. Please note: The $uploadFiles parameter
  938. * is deprecated in favour of the $uploadFiles property of the MailForm
  939. * class. This allows the setting to be managed via a settings.php file.
  940. *
  941. * @access public
  942. * @param boolean $uploadFiles
  943. * @return string
  944. *
  945. */
  946. function run ($uploadFiles = true) {
  947. global $cgi;
  948. if (! $uploadFiles) {
  949. $this->uploadFiles = $uploadFiles;
  950. }
  951. if ($this->invalid ($cgi)) {
  952. $this->setValues ($cgi);
  953. if ($this->verify_session) {
  954. @session_start ();
  955. $_SESSION['mf_verify_session'] = 'mf_verified';
  956. }
  957. return $this->show ();
  958. } else {
  959. if ($this->verify_session) {
  960. @session_start ();
  961. if ($_SESSION['mf_verify_session'] != 'mf_verified') {
  962. die ('This form requires that you enable cookies in your browser, which helps us to prevent abuse of our forms by automated spam systems.');
  963. }
  964. }
  965. if ($this->blacklist) {
  966. if (db_shift ('select count(*) from sitellite_form_blacklist where ip_address = ?', $_SERVER['REMOTE_ADDR'])) {
  967. die ('The IP address submitting this form has been blacklisted due to abuse. If you feel this has been done in error, please contact the website owner.');
  968. }
  969. }
  970. if ($this->autosave) {
  971. loader_import ('saf.MailForm.Autosave');
  972. $a = new Autosave ();
  973. $a->clear ($_SERVER['HTTP_REFERER']);
  974. }
  975. $this->setValues ($cgi);
  976. $vals = $this->getValues ();
  977. if ($this->clean_input) {
  978. foreach ($vals as $k => $v) {
  979. if(is_string($v)) {
  980. $vals[$k] = strip_tags ($v);
  981. }
  982. }
  983. }
  984. return call_user_func ($this->handler, $vals);
  985. }
  986. }
  987. /**
  988. * This is the default handler function. It is called via run()
  989. * and can be overridden via subclassing.
  990. *
  991. * @access public
  992. * @param array $vals
  993. * @return string
  994. *
  995. */
  996. function onSubmit ($vals) {
  997. if (! empty ($this->sendTo) || ! empty ($this->email)) {
  998. $email = $this->sendTo;
  999. $subject = $this->sendSubject;
  1000. $from_field = $this->sendFrom;
  1001. $extra = $this->sendExtra;
  1002. global $site;
  1003. $message_body = intl_get ('The following information has been sent from') . ' ' . $site->url . $GLOBALS['PHP_SELF'] . ":\n\n";
  1004. foreach ($vals as $key => $value) {
  1005. if ($this->widgets[$key]->type == 'separator') {
  1006. $message_body .= "\n----------\n\n";
  1007. } elseif ($this->widgets[$key]->type == 'section') {
  1008. $message_body .= $this->widgets[$key]->title . "\n\n";
  1009. } else {
  1010. if (strlen ($this->widgets[$key]->alt) > 30) {
  1011. $alt = substr ($this->widgets[$key]->alt, 0, 27) . '...';
  1012. } else {
  1013. $alt = $this->widgets[$key]->alt;
  1014. }
  1015. $message_body .= str_pad ($alt, 35) . ": " . $value . "\n";
  1016. }
  1017. }
  1018. if (! empty ($from_field)) {
  1019. if (strpos ($vars[$from_field], "\n") !== false) {
  1020. die ('Invalid from field value.');
  1021. }
  1022. $from_field = 'From: ' . $vals[$from_field] . "\r\n";
  1023. }
  1024. //echo '<pre>' . htmlentities_compat ($message_body) . '</pre>';
  1025. if (@mail ($email, $subject, $message_body, $from_field . $extra)) {
  1026. return $this->screenReply;
  1027. } else {
  1028. $this->error_message = intl_get ('Email could not sent. Please verify that your mail daemon is functioning correctly.');
  1029. return $this->error_message;
  1030. }
  1031. }
  1032. $this->error_message = intl_get ('No email address set. Please check your form settings.');
  1033. return $this->error_message;
  1034. }
  1035. /**
  1036. * Note: Deprecated in favour of the setHandler() and run() methods
  1037. * and subclassing. Handles the form, once it has been satisfactorily completed.
  1038. * If the first parameter points to a file (ie. 'inc/forms/contact.php'), it will
  1039. * use that file as an "action file" to handle the form. Otherwise, the first
  1040. * parameter must be an email address, as handle () will simply send an email
  1041. * of the form contents to the specified email address. Note: Extra will be
  1042. * passed to the PHP mail () function as a fourth parameter, or can be used for
  1043. * any purpose you'd like in an action file.
  1044. *
  1045. * @access public
  1046. * @param string $email
  1047. * @param string $subject
  1048. * @param string $from_field
  1049. * @param string $extra
  1050. * @return boolean
  1051. *
  1052. */
  1053. function handle ($email, $subject = 'Mail Form', $from_field = '', $extra = '') {
  1054. if (! strstr ($email, '@')) {
  1055. //echo 'using actionfile: ' . $email . '<br />';
  1056. // $email is an action file, so give it some action! ;)
  1057. if (strstr ($email, '..')) {
  1058. // we don't like file paths with .. in them. they really should never be needed.
  1059. $this->error_message = intl_get ('Sorry, no action file names with ".." in them.');
  1060. return false;
  1061. } elseif (! @file_exists ($email)) {
  1062. $this->error_message = intl_get ('Sorry, the action file you have specified could not be found.');
  1063. return false;
  1064. } else {
  1065. include_once ($email);
  1066. return true;
  1067. }
  1068. } else {
  1069. // send email
  1070. //echo 'using email address: ' . $email . '<br />';
  1071. $vars = $this->getValues ();
  1072. global $site;
  1073. $message_body = $this->formatEmail ($vars);
  1074. if (! empty ($from_field)) {
  1075. if (strpos ($vars[$from_field], "\n") !== false) {
  1076. die ('Invalid from field value.');
  1077. }
  1078. $from_field = 'From: ' . $vars[$from_field] . "\r\n";
  1079. }
  1080. //echo '<pre>' . htmlentities_compat ($message_body) . '</pre>';
  1081. if (@mail ($email, $subject, $message_body, $from_field . $extra)) {
  1082. return true;
  1083. } else {
  1084. $this->error_message = intl_get ('Email could not sent. Please verify that your mail daemon is functioning correctly.');
  1085. return false;
  1086. }
  1087. //echo "<pre>mail ('$email', '$subject', '$message_body', '$from_field$extra')</pre>";
  1088. //return true;
  1089. }
  1090. }
  1091. function formatEmail ($vals) {
  1092. global $site;
  1093. $message_body = intl_get ('The following information has been sent from') . ' ' . $site->url . $GLOBALS['PHP_SELF'] . ":\n\n";
  1094. foreach ($vals as $key => $value) {
  1095. if ($this->widgets[$key]->type == 'separator') {
  1096. $message_body .= "\n----------\n\n";
  1097. } elseif ($this->widgets[$key]->type == 'section') {
  1098. $message_body .= $this->widgets[$key]->title . "\n\n";
  1099. } else {
  1100. if (strlen ($this->widgets[$key]->alt) > 30) {
  1101. $alt = substr ($this->widgets[$key]->alt, 0, 27) . '...';
  1102. } else {
  1103. $alt = $this->widgets[$key]->alt;
  1104. }
  1105. $message_body .= str_pad ($alt, 35) . ": " . $value . "\n";
  1106. }
  1107. }
  1108. return $message_body;
  1109. }
  1110. /**
  1111. * Parses the specified file using the parse_ini_file()
  1112. * function. Sections in the file correspond to the names of
  1113. * widgets you wish to create, in addition to a [Form] section
  1114. * that sets properties for the form itself. The values in
  1115. * each section correspond to properties or methods of the
  1116. * widgets. This method can be used to simplify the process
  1117. * of defining and customizing a form.
  1118. *
  1119. * @access public
  1120. * @param string $file
  1121. * @return boolean
  1122. *
  1123. */
  1124. function parseSettings ($file) {
  1125. if (! @file_exists ($file)) {
  1126. return false;
  1127. }
  1128. ini_add_filter ('ini_filter_split_comma_single', array (
  1129. 'rule 0', 'rule 1', 'rule 2', 'rule 3', 'rule 4', 'rule 5', 'rule 6', 'rule 7', 'rule 8',
  1130. 'button 0', 'button 1', 'button 2', 'button 3', 'button 4', 'button 5', 'button 6', 'button 7', 'button 8',
  1131. 'submitButtons',
  1132. ));
  1133. $conf = ini_parse ($file, true);
  1134. ini_clear ();
  1135. if (count ($conf) == 0) {
  1136. return false;
  1137. }
  1138. // form properties, optional
  1139. if (is_array ($conf['Form'])) {
  1140. foreach ($conf['Form'] as $key => $value) {
  1141. if (($key == 'title' || $key == 'message') && function_exists ('intl_get')) {
  1142. $value = intl_get ($value);
  1143. }
  1144. $this->{$key} = $value;
  1145. }
  1146. unset ($conf['Form']);
  1147. }
  1148. foreach ($conf as $name => $data) {
  1149. $this->createWidget ($name, $data);
  1150. }
  1151. return true;
  1152. }
  1153. /**
  1154. * Creates a widget from a name and an array, usually taken from a parsed
  1155. * settings.php (ini formatted) file.
  1156. *
  1157. * @access public
  1158. * @param string
  1159. * @param array hash
  1160. */
  1161. function &createWidget ($name, $data) {// create widget
  1162. $type = $data['type'];
  1163. unset ($data['type']);
  1164. $widget =& $this->addWidget ($type, $name);
  1165. // handle setValues
  1166. if (! empty ($data['setValues'])) {
  1167. if (strpos ($data['setValues'], 'eval:') === 0) {
  1168. eval (CLOSE_TAG . OPEN_TAG . ' $widget->setValues (' . substr ($data['setValues'], 5) . '); ' . CLOSE_TAG);
  1169. } elseif (preg_match ('/, ?/', $data['setValues'])) {
  1170. $widget->setValues (preg_split ('/, ?/', $data['setValues']));
  1171. // eval (CLOSE_TAG . OPEN_TAG . ' $widget->setValues (array (' . $data['setValues'] . ')); ' . CLOSE_TAG);
  1172. } else {
  1173. if (strpos ($data['setValues'], '\'') === 0 && strrpos ($data['setValues'], '\'') == strlen ($data['setValues']) - 1) {
  1174. $data['setValues'] = substr ($data['setValues'], 1, strlen ($data['setValues']) - 2);
  1175. }
  1176. $widget->setValues ($data['setValues']);
  1177. }
  1178. // eval (CLOSE_TAG . OPEN_TAG . ' $widget->setValues (' . $data['setValues'] . '); ' . CLOSE_TAG);
  1179. }
  1180. unset ($data['setValues']);
  1181. if (! empty ($data['setDefault'])) {
  1182. if (strpos ($data['setDefault'], 'eval:') === 0) {
  1183. eval (CLOSE_TAG . OPEN_TAG . ' $widget->setDefault (' . substr ($data['setDefault'], 5) . '); ' . CLOSE_TAG);
  1184. } else {
  1185. $widget->setDefault ($data['setDefault']);
  1186. }
  1187. }
  1188. if (! empty ($data['setValue'])) {
  1189. if (strpos ($data['setValue'], 'eval:') === 0) {
  1190. eval (CLOSE_TAG . OPEN_TAG . ' $widget->setValue (' . substr ($data['setValue'], 5) . '); ' . CLOSE_TAG);
  1191. } else {
  1192. $widget->setValue ($data['setValue']);
  1193. }
  1194. }
  1195. if (! empty ($data['setRules'])) {
  1196. if (strpos ($data['setRules'], 'eval:') === 0) {
  1197. eval (CLOSE_TAG . OPEN_TAG . ' $widget->rules = ' . substr ($data['setRules'], 5) . '); ' . CLOSE_TAG);
  1198. }
  1199. }
  1200. // handle rules
  1201. //foreach (preg_split ('/, ?/', $data['rules'], -1, PREG_SPLIT_NO_EMPTY) as $rule) {
  1202. // $widget->addRule ($rule);
  1203. //}
  1204. //unset ($data['rules']);
  1205. // widget properties
  1206. foreach ($data as $key => $value) {
  1207. if (strpos ($key, 'rule ') === 0) {
  1208. if (is_array ($value)) {
  1209. if (function_exists ('intl_get')) {
  1210. $value[1] = intl_get ($value[1]);
  1211. }
  1212. $widget->addRule ($value[0], $value[1]);
  1213. } else {
  1214. $widget->addRule ($value);
  1215. }
  1216. } elseif (strpos ($key, 'value ') === 0) {
  1217. $widget->setValues ($value, $value);
  1218. } elseif ($type == 'msubmit' && strpos ($key, 'button ') === 0) {
  1219. $b =& $widget->getButton ();
  1220. if (empty ($b->value)) {
  1221. if (is_array ($value)) {
  1222. if (function_exists ('intl_get')) {
  1223. $value[0] = intl_get ($value[0]);
  1224. }
  1225. $b->setValues ($value[0]);
  1226. $b->extra = $value[1];
  1227. } else {
  1228. if (function_exists ('intl_get')) {
  1229. $value = intl_get ($value);
  1230. }
  1231. $b->setValues ($value);
  1232. }
  1233. } else {
  1234. if (is_array ($value)) {
  1235. if (function_exists ('intl_get')) {
  1236. $value[0] = intl_get ($value[0]);
  1237. }
  1238. $b =& $widget->addButton ($name, $value[0]);
  1239. $b->extra = $value[1];
  1240. } else {
  1241. if (function_exists ('intl_get')) {
  1242. $value = intl_get ($value);
  1243. }
  1244. $widget->addButton ($name, $value);
  1245. }
  1246. }
  1247. } elseif ($key == 'alt') {
  1248. if (function_exists ('intl_get')) {
  1249. $widget->{$key} = intl_get ($value);
  1250. } else {
  1251. $widget->{$key} = $value;
  1252. }
  1253. } elseif (method_exists ($widget, $key)) {
  1254. $widget->{$key} ($value);
  1255. } else {
  1256. $widget->{$key} = $value;
  1257. }
  1258. }
  1259. if (! empty ($widget->formhelp) && session_pref ('form_help') == 'on') {
  1260. $widget->extra .= ' onfocus="formhelp_show (this, \'' . addslashes (intl_get ($widget->formhelp)) . '\')" onblur="formhelp_hide ()"';
  1261. }
  1262. unset ($widget);
  1263. return $this->widgets[$name];
  1264. }
  1265. /**
  1266. * Takes a non-associative array and creates an associative array
  1267. * out of its values. This is used to send non-associative arrays to the
  1268. * setValues() method of the Widget objects.
  1269. *
  1270. * @access public
  1271. * @param array $list
  1272. * @return associative array
  1273. *
  1274. */
  1275. function makeAssoc ($list) {
  1276. $new = array ();
  1277. foreach ($list as $key => $value) {
  1278. if (! is_int ($key)) {
  1279. $new[$key] = $value;
  1280. } else {
  1281. $new[$value] = $value;
  1282. }
  1283. }
  1284. return $new;
  1285. }
  1286. /**
  1287. * Takes a non-associative array listing the names of each field
  1288. * from $cgi you want to "remember", and creates hidden fields for each
  1289. * of them, so you don't have to hard-code lists of hidden fields in
  1290. * multi-screen forms.
  1291. *
  1292. * @access public
  1293. * @param array $list
  1294. *
  1295. */
  1296. function rememberFields ($list) {
  1297. foreach ($list as $field) {
  1298. $this->addWidget ('hidden', $field);
  1299. }
  1300. }
  1301. /**
  1302. * This is the accessor method for setting and getting the value of
  1303. * any attribute of the form tag, including 'method' and 'action'. This will
  1304. * replace the $extra property, which is henceforth deprecated. If you call
  1305. * this method and provide no $value, you are using it as a 'getter', as in
  1306. * you are getting the current value. If you provide a value, the new value
  1307. * will be set, so you are acting as a 'setter'. If you simply specify that
  1308. * the $value be true, then it will appear filled with its own name (useful
  1309. * for things like the checked="checked" attribute of a checkbox input field,
  1310. * even though this isn't a checkbox field).
  1311. *
  1312. * @access public
  1313. * @param string $key
  1314. * @param string $key
  1315. * @return string
  1316. *
  1317. */
  1318. function attr ($key, $value = false) {
  1319. if ($value === false) {
  1320. return $this->_attrs[$key];
  1321. } else {
  1322. $this->_attrs[$key] = $value;
  1323. return $value;
  1324. }
  1325. }
  1326. /**
  1327. * Use this method to remove an attribute from the form tag
  1328. * attribute list. Use this instead of passing a false value to attr(),
  1329. * because a false value essentially means "return the current value"
  1330. * in that method. This method returns the old value of the attribute
  1331. * being unset.
  1332. *
  1333. * @access public
  1334. * @param string $key
  1335. * @return string
  1336. *
  1337. */
  1338. function unsetAttr ($key) {
  1339. $old = $this->_attrs[$key];
  1340. unset ($this->_attrs[$key]);
  1341. return $old;
  1342. }
  1343. /**
  1344. * Returns a list of all of the attributes of this object's form tag
  1345. * in a string ready to be concatenated into the actual rendered tag output.
  1346. *
  1347. * @access public
  1348. * @return string
  1349. *
  1350. */
  1351. function getAttrs () {
  1352. $res = '';
  1353. foreach ($this->_attrs as $key => $value) {
  1354. if ($value === false) {
  1355. continue;
  1356. } elseif ($value === true) {
  1357. $res .= $key . '="' . $key . '" ';
  1358. } else {
  1359. $res .= $key . '="' . $value . '" ';
  1360. }
  1361. }
  1362. return $res;
  1363. }
  1364. function verifyRequestMethod () {
  1365. if (strtoupper ($_SERVER['REQUEST_METHOD']) != strtoupper ($this->method)) {
  1366. return false;
  1367. }
  1368. return true;
  1369. }
  1370. function verifyReferer () {
  1371. if (strpos ($_SERVER['HTTP_REFERER'], site_url ()) !== 0) {
  1372. return false;
  1373. }
  1374. return true;
  1375. }
  1376. }
  1377. ?>