PageRenderTime 168ms CodeModel.GetById 33ms RepoModel.GetById 1ms app.codeStats 1ms

/~enabled/mem_form.php

https://bitbucket.org/mrdale/txp-plugins
PHP | 1930 lines | 1501 code | 360 blank | 69 comment | 221 complexity | f0200b4f86b80d0ed4fb2dc140e427b1 MD5 | raw file

Large files files are truncated, but you can click here to view the full file

  1. <?php
  2. // This is a PLUGIN TEMPLATE for Textpattern CMS.
  3. // Copy this file to a new name like abc_myplugin.php. Edit the code, then
  4. // run this file at the command line to produce a plugin for distribution:
  5. // $ php abc_myplugin.php > abc_myplugin-0.1.txt
  6. // Plugin name is optional. If unset, it will be extracted from the current
  7. // file name. Plugin names should start with a three letter prefix which is
  8. // unique and reserved for each plugin author ("abc" is just an example).
  9. // Uncomment and edit this line to override:
  10. $plugin['name'] = 'mem_form';
  11. // Allow raw HTML help, as opposed to Textile.
  12. // 0 = Plugin help is in Textile format, no raw HTML allowed (default).
  13. // 1 = Plugin help is in raw HTML. Not recommended.
  14. # $plugin['allow_html_help'] = 1;
  15. $plugin['version'] = '0.8.7';
  16. $plugin['author'] = 'Michael Manfre';
  17. $plugin['author_uri'] = 'http://manfre.net/';
  18. $plugin['description'] = 'A library plugin that provides support for html forms.';
  19. // Plugin load order:
  20. // The default value of 5 would fit most plugins, while for instance comment
  21. // spam evaluators or URL redirectors would probably want to run earlier
  22. // (1...4) to prepare the environment for everything else that follows.
  23. // Values 6...9 should be considered for plugins which would work late.
  24. // This order is user-overrideable.
  25. $plugin['order'] = '5';
  26. // Plugin 'type' defines where the plugin is loaded
  27. // 0 = public : only on the public side of the website (default)
  28. // 1 = public+admin : on both the public and admin side
  29. // 2 = library : only when include_plugin() or require_plugin() is called
  30. // 3 = admin : only on the admin side (no AJAX)
  31. // 4 = admin+ajax : only on the admin side (AJAX supported)
  32. // 5 = public+admin+ajax : on both the public and admin side (AJAX supported)
  33. $plugin['type'] = '2';
  34. // Plugin "flags" signal the presence of optional capabilities to the core plugin loader.
  35. // Use an appropriately OR-ed combination of these flags.
  36. // The four high-order bits 0xf000 are available for this plugin's private use
  37. if (!defined('PLUGIN_HAS_PREFS')) define('PLUGIN_HAS_PREFS', 0x0001); // This plugin wants to receive "plugin_prefs.{$plugin['name']}" events
  38. if (!defined('PLUGIN_LIFECYCLE_NOTIFY')) define('PLUGIN_LIFECYCLE_NOTIFY', 0x0002); // This plugin wants to receive "plugin_lifecycle.{$plugin['name']}" events
  39. $plugin['flags'] = '0';
  40. // Plugin 'textpack' is optional. It provides i18n strings to be used in conjunction with gTxt().
  41. // Syntax:
  42. // ## arbitrary comment
  43. // #@event
  44. // #@language ISO-LANGUAGE-CODE
  45. // abc_string_name => Localized String
  46. /** Uncomment me, if you need a textpack
  47. $plugin['textpack'] = <<<EOT
  48. #@admin
  49. #@language en-gb
  50. abc_sample_string => Sample String
  51. abc_one_more => One more
  52. #@language de-de
  53. abc_sample_string => Beispieltext
  54. abc_one_more => Noch einer
  55. EOT;
  56. **/
  57. // End of textpack
  58. if (!defined('txpinterface'))
  59. @include_once('zem_tpl.php');
  60. # --- BEGIN PLUGIN CODE ---
  61. $mem_glz_custom_fields_plugin = load_plugin('glz_custom_fields');
  62. // needed for MLP
  63. define( 'MEM_FORM_PREFIX' , 'mem_form' );
  64. global $mem_form_lang;
  65. if (!is_array($mem_form_lang))
  66. {
  67. $mem_form_lang = array(
  68. 'error_file_extension' => 'File upload failed for field {label}.',
  69. 'error_file_failed' => 'Failed to upload file for field {label}.',
  70. 'error_file_size' => 'Failed to upload File for field {label}. File is too large.',
  71. 'field_missing' => 'The field {label} is required.',
  72. 'form_expired' => 'The form has expired.',
  73. 'form_misconfigured' => 'The mem_form is misconfigured. You must specify the "form" attribute.',
  74. 'form_sorry' => 'The form is currently unavailable.',
  75. 'form_used' => 'This form has already been used to submit.',
  76. 'general_inquiry' => '',
  77. 'invalid_email' => 'The email address {email} is invalid.',
  78. 'invalid_host' => 'The host {domain} is invalid.',
  79. 'invalid_utf8' => 'Invalid UTF8 string for field {label}.',
  80. 'invalid_value' => 'The value "{value}" is invalid for the input field {label}.',
  81. 'invalid_format' => 'The input field {label} must match the format "{example}".',
  82. 'invalid_too_many_selected' => 'The input field {label} only allows {count} selected {plural}.',
  83. 'item' => 'item',
  84. 'items' => 'items',
  85. 'max_warning' => 'The input field {label} must be smaller than {max} characters long.',
  86. 'min_warning' => 'The input field {label} must be at least {min} characters long.',
  87. 'refresh' => 'Refresh',
  88. 'spam' => 'Your submission was blocked by a spam filter.',
  89. 'submitted_thanks' => 'You have successfully submitted the form. Thank you.',
  90. );
  91. }
  92. register_callback( 'mem_form_enumerate_strings' , 'l10n.enumerate_strings' );
  93. function mem_form_enumerate_strings($event , $step='' , $pre=0)
  94. {
  95. global $mem_form_lang;
  96. $r = array (
  97. 'owner' => 'mem_form', # Change to your plugin's name
  98. 'prefix' => MEM_FORM_PREFIX, # Its unique string prefix
  99. 'lang' => 'en-gb', # The language of the initial strings.
  100. 'event' => 'public', # public/admin/common = which interface the strings will be loaded into
  101. 'strings' => $mem_form_lang, # The strings themselves.
  102. );
  103. return $r;
  104. }
  105. function mem_form_gTxt($what,$args = array())
  106. {
  107. global $mem_form_lang, $textarray;
  108. $key = strtolower( MEM_FORM_PREFIX . '-' . $what );
  109. if (isset($textarray[$key]))
  110. {
  111. $str = $textarray[$key];
  112. }
  113. else
  114. {
  115. $key = strtolower($what);
  116. if (isset($mem_form_lang[$key]))
  117. $str = $mem_form_lang[$key];
  118. elseif (isset($textarray[$key]))
  119. $str = $textarray[$key];
  120. else
  121. $str = $what;
  122. }
  123. if( !empty($args) )
  124. $str = strtr( $str , $args );
  125. return $str;
  126. }
  127. function mem_form($atts, $thing='', $default=false)
  128. {
  129. global $sitename, $prefs, $file_max_upload_size, $mem_form_error, $mem_form_submit,
  130. $mem_form, $mem_form_labels, $mem_form_values, $mem_form_default_break,
  131. $mem_form_default, $mem_form_type, $mem_form_thanks_form,
  132. $mem_glz_custom_fields_plugin;
  133. extract(mem_form_lAtts(array(
  134. 'form' => '',
  135. 'thanks_form' => '',
  136. 'thanks' => graf(mem_form_gTxt('submitted_thanks')),
  137. 'label' => '',
  138. 'type' => '',
  139. 'redirect' => '',
  140. 'redirect_form' => '',
  141. 'class' => 'memForm',
  142. 'enctype' => '',
  143. 'file_accept' => '',
  144. 'max_file_size' => $file_max_upload_size,
  145. 'form_expired_msg' => mem_form_gTxt('form_expired'),
  146. 'show_error' => 1,
  147. 'show_input' => 1,
  148. 'default_break' => br,
  149. ), $atts));
  150. if (empty($type) or (empty($form) && empty($thing))) {
  151. trigger_error('Argument not specified for mem_form tag', E_USER_WARNING);
  152. return '';
  153. }
  154. $out = '';
  155. // init error structure
  156. mem_form_error();
  157. $mem_form_type = $type;
  158. $mem_form_default = is_array($default) ? $default : array();
  159. callback_event('mem_form.defaults');
  160. unset($atts['show_error'], $atts['show_input']);
  161. $mem_form_id = md5(serialize($atts).preg_replace('/[\t\s\r\n]/','',$thing));
  162. $mem_form_submit = (ps('mem_form_id') == $mem_form_id);
  163. $nonce = doSlash(ps('mem_form_nonce'));
  164. $renonce = false;
  165. if ($mem_form_submit) {
  166. safe_delete('txp_discuss_nonce', 'issue_time < date_sub(now(), interval 10 minute)');
  167. if ($rs = safe_row('used', 'txp_discuss_nonce', "nonce = '$nonce'"))
  168. {
  169. if ($rs['used'])
  170. {
  171. unset($mem_form_error);
  172. mem_form_error(mem_form_gTxt('form_used'));
  173. $renonce = true;
  174. $_POST['mem_form_submit'] = TRUE;
  175. $_POST['mem_form_id'] = $mem_form_id;
  176. $_POST['mem_form_nonce'] = $nonce;
  177. }
  178. }
  179. else
  180. {
  181. mem_form_error($form_expired_msg);
  182. $renonce = true;
  183. }
  184. }
  185. if ($mem_form_submit and $nonce and !$renonce)
  186. {
  187. $mem_form_nonce = $nonce;
  188. }
  189. elseif (!$show_error or $show_input)
  190. {
  191. $mem_form_nonce = md5(uniqid(rand(), true));
  192. safe_insert('txp_discuss_nonce', "issue_time = now(), nonce = '$mem_form_nonce'");
  193. }
  194. $form = ($form) ? fetch_form($form) : $thing;
  195. $form = parse($form);
  196. if ($mem_form_submit && empty($mem_form_error))
  197. {
  198. // let plugins validate after individual fields are validated
  199. callback_event('mem_form.validate');
  200. }
  201. if (!$mem_form_submit) {
  202. # don't show errors or send mail
  203. }
  204. elseif (mem_form_error())
  205. {
  206. if ($show_error or !$show_input)
  207. {
  208. $out .= mem_form_display_error();
  209. if (!$show_input) return $out;
  210. }
  211. }
  212. elseif ($show_input and is_array($mem_form))
  213. {
  214. if ($mem_glz_custom_fields_plugin) {
  215. // prep the values
  216. glz_custom_fields_before_save();
  217. }
  218. callback_event('mem_form.spam');
  219. /// load and check spam plugins/
  220. $evaluator =& get_mem_form_evaluator();
  221. $is_spam = $evaluator->is_spam();
  222. if ($is_spam) {
  223. return mem_form_gTxt('spam');
  224. }
  225. $mem_form_thanks_form = ($thanks_form ? fetch_form($thanks_form) : $thanks);
  226. safe_update('txp_discuss_nonce', "used = '1', issue_time = now()", "nonce = '$nonce'");
  227. $result = callback_event('mem_form.submit');
  228. if (mem_form_error()) {
  229. $out .= mem_form_display_error();
  230. $redirect = false;
  231. }
  232. $thanks_form = $mem_form_thanks_form;
  233. unset($mem_form_thanks_form);
  234. if (!empty($result))
  235. return $result;
  236. if (mem_form_error() and $show_input)
  237. {
  238. // no-op, reshow form with errors
  239. }
  240. else if ($redirect)
  241. {
  242. $_POST = array();
  243. while (@ob_end_clean());
  244. $uri = hu.ltrim($redirect,'/');
  245. if (empty($_SERVER['FCGI_ROLE']) and empty($_ENV['FCGI_ROLE']))
  246. {
  247. txp_status_header('303 See Other');
  248. header('Location: '.$uri);
  249. header('Connection: close');
  250. header('Content-Length: 0');
  251. }
  252. else
  253. {
  254. $uri = htmlspecialchars($uri);
  255. $refresh = mem_form_gTxt('refresh');
  256. if (!empty($redirect_form))
  257. {
  258. $redirect_form = fetch_form($redirect_form);
  259. echo str_replace('{uri}', $uri, $redirect_form);
  260. }
  261. if (empty($redirect_form))
  262. {
  263. echo <<<END
  264. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
  265. <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
  266. <head>
  267. <title>$sitename</title>
  268. <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  269. <meta http-equiv="refresh" content="0;url=$uri" />
  270. </head>
  271. <body>
  272. <a href="$uri">$refresh</a>
  273. </body>
  274. </html>
  275. END;
  276. }
  277. }
  278. exit;
  279. }
  280. else {
  281. return '<div class="memThanks" id="mem'.$mem_form_id.'">' .
  282. $thanks_form . '</div>';
  283. }
  284. }
  285. if ($show_input)
  286. {
  287. $file_accept = (!empty($file_accept) ? ' accept="'.$file_accept.'"' : '');
  288. $class = htmlspecialchars($class);
  289. $enctype = !empty($enctype) ? ' enctype="'.$enctype.'"' : '';
  290. return '<form method="post"'.((!$show_error and $mem_form_error) ? '' : ' id="mem'.$mem_form_id.'"').' class="'.$class.'" action="'.htmlspecialchars(serverSet('REQUEST_URI')).'#mem'.$mem_form_id.'"'.$file_accept.$enctype.'>'.
  291. ( $label ? n.'<fieldset>' : n.'<div>' ).
  292. ( $label ? n.'<legend>'.htmlspecialchars($label).'</legend>' : '' ).
  293. $out.
  294. n.'<input type="hidden" name="mem_form_nonce" value="'.$mem_form_nonce.'" />'.
  295. n.'<input type="hidden" name="mem_form_id" value="'.$mem_form_id.'" />'.
  296. (!empty($max_file_size) ? n.'<input type="hidden" name="MAX_FILE_SIZE" value="'.$max_file_size.'" />' : '' ).
  297. callback_event('mem_form.display','',1).
  298. $form.
  299. callback_event('mem_form.display').
  300. ( $label ? (n.'</fieldset>') : (n.'</div>') ).
  301. n.'</form>';
  302. }
  303. return '';
  304. }
  305. function mem_form_text($atts)
  306. {
  307. global $mem_form_error, $mem_form_submit, $mem_form_default, $mem_form_default_break;
  308. extract(mem_form_lAtts(array(
  309. 'break' => $mem_form_default_break,
  310. 'default' => '',
  311. 'isError' => '',
  312. 'label' => mem_form_gTxt('text'),
  313. 'placeholder' => '',
  314. 'max' => 100,
  315. 'min' => 0,
  316. 'name' => '',
  317. 'class' => 'memText',
  318. 'required' => 1,
  319. 'size' => '',
  320. 'password' => 0,
  321. 'format' => '',
  322. 'example' => '',
  323. 'escape_value' => 1,
  324. 'attrs' => ''
  325. ), $atts));
  326. $min = intval($min);
  327. $max = intval($max);
  328. $size = intval($size);
  329. if (empty($name)) $name = mem_form_label2name($label);
  330. if ($mem_form_submit)
  331. {
  332. $value = trim(ps($name));
  333. $utf8len = preg_match_all("/./su", $value, $utf8ar);
  334. $hlabel = empty($label) ? htmlspecialchars($name) : htmlspecialchars($label);
  335. if (strlen($value) == 0 && $required)
  336. {
  337. $mem_form_error[] = mem_form_gTxt('field_missing', array('{label}'=>$hlabel));
  338. $isError = true;
  339. }
  340. elseif ($required && !empty($format) && !preg_match($format, $value))
  341. {
  342. //echo "format=$format<br />value=$value<br />";
  343. $mem_form_error[] = mem_form_gTxt('invalid_format', array('{label}'=>$hlabel, '{example}'=> htmlspecialchars($example)));
  344. $isError = true;
  345. }
  346. elseif (strlen($value))
  347. {
  348. if (!$utf8len)
  349. {
  350. $mem_form_error[] = mem_form_gTxt('invalid_utf8', array('{label}'=>$hlabel));
  351. $isError = true;
  352. }
  353. elseif ($min and $utf8len < $min)
  354. {
  355. $mem_form_error[] = mem_form_gTxt('min_warning', array('{label}'=>$hlabel, '{min}'=>$min));
  356. $isError = true;
  357. }
  358. elseif ($max and $utf8len > $max)
  359. {
  360. $mem_form_error[] = mem_form_gTxt('max_warning', array('{label}'=>$hlabel, '{max}'=>$max));
  361. $isError = true;
  362. }
  363. else
  364. {
  365. $isError = false === mem_form_store($name, $label, $value);
  366. }
  367. }
  368. }
  369. else
  370. {
  371. if (isset($mem_form_default[$name]))
  372. $value = $mem_form_default[$name];
  373. else
  374. $value = $default;
  375. }
  376. $size = ($size) ? ' size="'.$size.'"' : '';
  377. $maxlength = ($max) ? ' maxlength="'.$max.'"' : '';
  378. $placeholder = ($placeholder) ? ' placeholder="'.htmlspecialchars($placeholder).'"' : '';
  379. $isError = $isError ? "errorElement" : '';
  380. $memRequired = $required ? 'memRequired' : '';
  381. $class = htmlspecialchars($class);
  382. if ($escape_value)
  383. {
  384. $value = htmlspecialchars($value);
  385. }
  386. return '<label for="'.$name.'" class="'.$class.' '.$memRequired.$isError.' '.$name.'">'.htmlspecialchars($label).'</label>'.$break.
  387. '<input type="'.($password ? 'password' : 'text').'" id="'.$name.'" class="'.$class.' '.$memRequired.$isError.'" name="'.$name.'" value="'.$value.'"'.$size.$maxlength.$placeholder.
  388. ( !empty($attrs) ? ' ' . $attrs : '').' />';
  389. }
  390. function mem_form_file($atts)
  391. {
  392. global $mem_form_submit, $mem_form_error, $mem_form_default, $file_max_upload_size, $tempdir, $mem_form_default_break;
  393. extract(mem_form_lAtts(array(
  394. 'break' => $mem_form_default_break,
  395. 'isError' => '',
  396. 'label' => mem_form_gTxt('file'),
  397. 'name' => '',
  398. 'class' => 'memFile',
  399. 'size' => '',
  400. 'accept' => '',
  401. 'no_replace' => 1,
  402. 'max_file_size' => $file_max_upload_size,
  403. 'required' => 1,
  404. 'default' => FALSE,
  405. ), $atts));
  406. $fname = ps('file_'.$name);
  407. $frealname = ps('file_info_'.$name.'_name');
  408. $ftype = ps('file_info_'.$name.'_type');
  409. if (empty($name)) $name = mem_form_label2name($label);
  410. $out = '';
  411. if ($mem_form_submit)
  412. {
  413. if (!empty($fname))
  414. {
  415. // see if user uploaded a different file to replace already uploaded
  416. if (isset($_FILES[$name]) && !empty($_FILES[$name]['tmp_name']))
  417. {
  418. // unlink last temp file
  419. if (file_exists($fname) && substr_compare($fname, $tempdir, 0, strlen($tempdir), 1)==0)
  420. unlink($fname);
  421. $fname = '';
  422. }
  423. else
  424. {
  425. // pass through already uploaded filename
  426. mem_form_store($name, $label, array('tmp_name'=>$fname, 'name' => $frealname, 'type' => $ftype));
  427. $out .= "<input type='hidden' name='file_".$name."' value='".htmlspecialchars($fname)."' />"
  428. . "<input type='hidden' name='file_info_".$name."_name' value='".htmlspecialchars($frealname)."' />"
  429. . "<input type='hidden' name='file_info_".$name."_type' value='".htmlspecialchars($ftype)."' />";
  430. }
  431. }
  432. if (empty($fname))
  433. {
  434. $hlabel = empty($label) ? htmlspecialchars($name) : htmlspecialchars($label);
  435. $fname = $_FILES[$name]['tmp_name'];
  436. $frealname = $_FILES[$name]['name'];
  437. $ftype = $_FILES[$name]['type'];
  438. $err = 0;
  439. switch ($_FILES[$name]['error']) {
  440. case UPLOAD_ERR_OK:
  441. if (is_uploaded_file($fname) and $max_file_size >= filesize($fname))
  442. mem_form_store($name, $label, $_FILES[$name]);
  443. elseif (!is_uploaded_file($fname)) {
  444. if ($required) {
  445. $mem_form_error[] = mem_form_gTxt('error_file_failed', array('{label}'=>$hlabel));
  446. $err = 1;
  447. }
  448. }
  449. else {
  450. $mem_form_error[] = mem_form_gTxt('error_file_size', array('{label}'=>$hlabel));
  451. $err = 1;
  452. }
  453. break;
  454. case UPLOAD_ERR_NO_FILE:
  455. if ($required) {
  456. $mem_form_error[] = mem_form_gTxt('field_missing', array('{label}'=>$hlabel));
  457. $err = 1;
  458. }
  459. break;
  460. case UPLOAD_ERR_EXTENSION:
  461. $mem_form_error[] = mem_form_gTxt('error_file_extension', array('{label}'=>$hlabel));
  462. $err = 1;
  463. break;
  464. case UPLOAD_ERR_INI_SIZE:
  465. case UPLOAD_ERR_FORM_SIZE:
  466. $mem_form_error[] = mem_form_gTxt('error_file_size', array('{label}'=>$hlabel));
  467. $err = 1;
  468. break;
  469. default:
  470. $mem_form_error[] = mem_form_gTxt('error_file_failed', array('{label}'=>$hlabel));
  471. $err = 1;
  472. break;
  473. }
  474. if (!$err)
  475. {
  476. // store as a txp tmp file to be used later
  477. $fname = get_uploaded_file($fname);
  478. $err = false === mem_form_store($name, $label, array('tmp_name'=>$fname, 'name' => $frealname, 'type' => $ftype));
  479. if ($err)
  480. {
  481. // clean up file
  482. @unlink($fname);
  483. }
  484. else
  485. {
  486. $out .= "<input type='hidden' name='file_".$name."' value='".htmlspecialchars($fname)."' />"
  487. . "<input type='hidden' name='file_info_".$name."_name' value='".htmlspecialchars($_FILES[$name]['name'])."' />"
  488. . "<input type='hidden' name='file_info_".$name."_type' value='".htmlspecialchars($_FILES[$name]['type'])."' />";
  489. }
  490. }
  491. $isError = $err ? 'errorElement' : '';
  492. }
  493. }
  494. else
  495. {
  496. if (isset($mem_form_default[$name]))
  497. $value = $mem_form_default[$name];
  498. else if (is_array($default))
  499. $value = $default;
  500. if (is_array(@$value))
  501. {
  502. $fname = @$value['tmp_name'];
  503. $frealname = @$value['name'];
  504. $ftype = @$value['type'];
  505. $out .= "<input type='hidden' name='file_".$name."' value='".htmlspecialchars($fname)."' />"
  506. . "<input type='hidden' name='file_info_".$name."_name' value='".htmlspecialchars($frealname)."' />"
  507. . "<input type='hidden' name='file_info_".$name."_type' value='".htmlspecialchars($ftype)."' />";
  508. }
  509. }
  510. $memRequired = $required ? 'memRequired' : '';
  511. $class = htmlspecialchars($class);
  512. $size = ($size) ? ' size="'.$size.'"' : '';
  513. $accept = (!empty($accept) ? ' accept="'.$accept.'"' : '');
  514. $field_out = '<label for="'.$name.'" class="'.$class.' '.$memRequired.$isError.' '.$name.'">'.htmlspecialchars($label).'</label>'.$break;
  515. if (!empty($frealname) && $no_replace)
  516. {
  517. $field_out .= '<div id="'.$name.'">'.htmlspecialchars($frealname) . ' <span id="'.$name.'_ftype">('. htmlspecialchars($ftype).')</span></div>';
  518. }
  519. else
  520. {
  521. $field_out .= '<input type="file" id="'.$name.'" class="'.$class.' '.$memRequired.$isError.'" name="'.$name.'"' .$size.' />';
  522. }
  523. return $out.$field_out;
  524. }
  525. function mem_form_textarea($atts, $thing='')
  526. {
  527. global $mem_form_error, $mem_form_submit, $mem_form_default, $mem_form_default_break;
  528. extract(mem_form_lAtts(array(
  529. 'break' => $mem_form_default_break,
  530. 'cols' => 58,
  531. 'default' => '',
  532. 'isError' => '',
  533. 'label' => mem_form_gTxt('textarea'),
  534. 'placeholder' => '',
  535. 'max' => 10000,
  536. 'min' => 0,
  537. 'name' => '',
  538. 'class' => 'memTextarea',
  539. 'required' => 1,
  540. 'rows' => 8,
  541. 'escape_value' => 1,
  542. 'attrs' => ''
  543. ), $atts));
  544. $min = intval($min);
  545. $max = intval($max);
  546. $cols = intval($cols);
  547. $rows = intval($rows);
  548. if (empty($name)) $name = mem_form_label2name($label);
  549. if ($mem_form_submit)
  550. {
  551. $value = preg_replace('/^\s*[\r\n]/', '', rtrim(ps($name)));
  552. $utf8len = preg_match_all("/./su", ltrim($value), $utf8ar);
  553. $hlabel = htmlspecialchars($label);
  554. if (strlen(ltrim($value)))
  555. {
  556. if (!$utf8len)
  557. {
  558. $mem_form_error[] = mem_form_gTxt('invalid_utf8', array('{label}'=>$hlabel));
  559. $isError = true;
  560. }
  561. elseif ($min and $utf8len < $min)
  562. {
  563. $mem_form_error[] = mem_form_gTxt('min_warning', array('{label}'=>$hlabel, '{min}'=>$min));
  564. $isError = true;
  565. }
  566. elseif ($max and $utf8len > $max)
  567. {
  568. $mem_form_error[] = mem_form_gTxt('max_warning', array('{label}'=>$hlabel, '{max}'=>$max));
  569. $isError = true;
  570. }
  571. else
  572. {
  573. $isError = false === mem_form_store($name, $label, $value);
  574. }
  575. }
  576. elseif ($required)
  577. {
  578. $mem_form_error[] = mem_form_gTxt('field_missing', array('{label}'=>$hlabel));
  579. $isError = true;
  580. }
  581. }
  582. else
  583. {
  584. if (isset($mem_form_default[$name]))
  585. $value = $mem_form_default[$name];
  586. else if (!empty($default))
  587. $value = $default;
  588. else
  589. $value = parse($thing);
  590. }
  591. $isError = $isError ? 'errorElement' : '';
  592. $memRequired = $required ? 'memRequired' : '';
  593. $class = htmlspecialchars($class);
  594. $placeholder = ($placeholder) ? ' placeholder="'.htmlspecialchars($placeholder).'"' : '';
  595. if ($escape_value)
  596. {
  597. $value = htmlspecialchars($value);
  598. }
  599. return '<label for="'.$name.'" class="'.$class.' '.$memRequired.$isError.' '.$name.'">'.htmlspecialchars($label).'</label>'.$break.
  600. '<textarea id="'.$name.'" class="'.$class.' '.$memRequired.$isError.'" name="'.$name.'" cols="'.$cols.'" rows="'.$rows.'"'.$placeholder.
  601. ( !empty($attrs) ? ' ' . $attrs : '').'>'.$value.'</textarea>';
  602. }
  603. function mem_form_email($atts)
  604. {
  605. global $mem_form_error, $mem_form_submit, $mem_form_from, $mem_form_default, $mem_form_default_break;
  606. extract(mem_form_lAtts(array(
  607. 'default' => '',
  608. 'isError' => '',
  609. 'label' => mem_form_gTxt('email'),
  610. 'placeholder' => '',
  611. 'max' => 100,
  612. 'min' => 0,
  613. 'name' => '',
  614. 'required' => 1,
  615. 'break' => $mem_form_default_break,
  616. 'size' => '',
  617. 'class' => 'memEmail',
  618. ), $atts));
  619. if (empty($name)) $name = mem_form_label2name($label);
  620. if ($mem_form_submit)
  621. {
  622. $email = trim(ps($name));
  623. if (strlen($email))
  624. {
  625. if (!is_valid_email($email))
  626. {
  627. $mem_form_error[] = mem_form_gTxt('invalid_email', array('{email}'=>htmlspecialchars($email)));
  628. $isError = true;
  629. }
  630. else
  631. {
  632. preg_match("/@(.+)$/", $email, $match);
  633. $domain = $match[1];
  634. if (is_callable('checkdnsrr') and checkdnsrr('textpattern.com.','A') and !checkdnsrr($domain.'.','MX') and !checkdnsrr($domain.'.','A'))
  635. {
  636. $mem_form_error[] = mem_form_gTxt('invalid_host', array('{domain}'=>htmlspecialchars($domain)));
  637. $isError = true;
  638. }
  639. else
  640. {
  641. $mem_form_from = $email;
  642. }
  643. }
  644. }
  645. }
  646. else
  647. {
  648. if (isset($mem_form_default[$name]))
  649. $email = $mem_form_default[$name];
  650. else
  651. $email = $default;
  652. }
  653. return mem_form_text(array(
  654. 'default' => $email,
  655. 'isError' => $isError,
  656. 'label' => $label,
  657. 'placeholder' => $placeholder,
  658. 'max' => $max,
  659. 'min' => $min,
  660. 'name' => $name,
  661. 'required' => $required,
  662. 'break' => $break,
  663. 'size' => $size,
  664. 'class' => $class,
  665. ));
  666. }
  667. function mem_form_select_section($atts)
  668. {
  669. extract(mem_form_lAtts(array(
  670. 'exclude' => '',
  671. 'sort' => 'name ASC',
  672. 'delimiter' => ',',
  673. ),$atts,false));
  674. if (!empty($exclude)) {
  675. $exclusion = array_map('trim', explode($delimiter, preg_replace('/[\r\n\t\s]+/', ' ',$exclude)));
  676. $exclusion = array_map('strtolower', $exclusion);
  677. if (count($exclusion))
  678. $exclusion = join($delimiter, quote_list($exclusion));
  679. }
  680. $where = empty($exclusion) ? '1=1' : 'LOWER(name) NOT IN ('.$exclusion.')';
  681. $sort = empty($sort) ? '' : ' ORDER BY '. doSlash($sort);
  682. $rs = safe_rows('name, title','txp_section',$where . $sort);
  683. $items = array();
  684. $values = array();
  685. if ($rs) {
  686. foreach($rs as $r) {
  687. $items[] = $r['title'];
  688. $values[] = $r['name'];
  689. }
  690. }
  691. unset($atts['exclude'], $atts['sort']);
  692. $atts['items'] = join($delimiter, $items);
  693. $atts['values'] = join($delimiter, $values);
  694. return mem_form_select($atts);
  695. }
  696. function mem_form_select_category($atts)
  697. {
  698. extract(mem_form_lAtts(array(
  699. 'root' => 'root',
  700. 'exclude' => '',
  701. 'delimiter' => ',',
  702. 'type' => 'article'
  703. ),$atts,false));
  704. $rs = getTree($root, $type);
  705. if (!empty($exclude)) {
  706. $exclusion = array_map('trim', explode($delimiter, preg_replace('/[\r\n\t\s]+/', ' ',$exclude)));
  707. $exclusion = array_map('strtolower', $exclusion);
  708. }
  709. else
  710. $exclusion = array();
  711. $items = array();
  712. $values = array();
  713. if ($rs) {
  714. foreach ($rs as $cat) {
  715. if (count($exclusion) && in_array(strtolower($cat['name']), $exclusion))
  716. continue;
  717. $items[] = $cat['title'];
  718. $values[] = $cat['name'];
  719. }
  720. }
  721. unset($atts['root'], $atts['type']);
  722. $atts['items'] = join($delimiter, $items);
  723. $atts['values'] = join($delimiter, $values);
  724. return mem_form_select($atts);
  725. }
  726. function mem_form_select_range($atts)
  727. {
  728. global $mem_form_default_break;
  729. $latts = mem_form_lAtts(array(
  730. 'start' => 0,
  731. 'stop' => false,
  732. 'step' => 1,
  733. 'name' => '',
  734. 'break' => $mem_form_default_break,
  735. 'delimiter' => ',',
  736. 'isError' => '',
  737. 'label' => mem_form_gTxt('option'),
  738. 'first' => FALSE,
  739. 'required' => 1,
  740. 'select_limit' => FALSE,
  741. 'as_csv' => FALSE,
  742. 'selected' => '',
  743. 'class' => 'memSelect',
  744. 'attrs' => ''
  745. ), $atts);
  746. if ($stop === false)
  747. {
  748. trigger_error(gTxt('missing_required_attribute', array('{name}' => 'stop')), E_USER_ERROR);
  749. }
  750. $step = empty($latts['step']) ? 1 : assert_int($latts['step']);
  751. $start= assert_int($latts['start']);
  752. $stop = assert_int($latts['stop']);
  753. // fixup start/stop based upon step direction
  754. $start = $step > 0 ? min($start, $stop) : max($start, $stop);
  755. $stop = $step > 0 ? max($start, $stop) : min($start, $stop);
  756. $values = array();
  757. for($i=$start; $i >= $start && $i < $stop; $i += $step)
  758. {
  759. array_push($values, $i);
  760. }
  761. // intentional trample
  762. $latts['items'] = $latts['values'] = implode($latts['delimiter'], $values);
  763. return mem_form_select($latts);
  764. }
  765. function mem_form_select($atts)
  766. {
  767. global $mem_form_error, $mem_form_submit, $mem_form_default, $mem_form_default_break;
  768. extract(mem_form_lAtts(array(
  769. 'name' => '',
  770. 'break' => $mem_form_default_break,
  771. 'delimiter' => ',',
  772. 'isError' => '',
  773. 'label' => mem_form_gTxt('option'),
  774. 'items' => mem_form_gTxt('general_inquiry'),
  775. 'values' => '',
  776. 'first' => FALSE,
  777. 'required' => 1,
  778. 'select_limit' => FALSE,
  779. 'as_csv' => FALSE,
  780. 'selected' => '',
  781. 'class' => 'memSelect',
  782. 'attrs' => ''
  783. ), $atts, false));
  784. if (empty($name)) $name = mem_form_label2name($label);
  785. if (!empty($items) && $items[0] == '<') $items = parse($items);
  786. if (!empty($values) && $values[0] == '<') $values = parse($values);
  787. if ($first !== FALSE) {
  788. $items = $first.$delimiter.$atts['items'];
  789. $values = $first.$delimiter.$atts['values'];
  790. }
  791. $select_limit = empty($select_limit) ? 1 : assert_int($select_limit);
  792. $items = array_map('trim', explode($delimiter, preg_replace('/[\r\n\t\s]+/', ' ',$items)));
  793. $values = array_map('trim', explode($delimiter, preg_replace('/[\r\n\t\s]+/', ' ',$values)));
  794. if ($select_limit > 1)
  795. {
  796. $selected = array_map('trim', explode($delimiter, preg_replace('/[\r\n\t\s]+/', ' ',$seelcted)));
  797. }
  798. else
  799. {
  800. $selected = array(trim($selected));
  801. }
  802. $use_values_array = (count($items) == count($values));
  803. if ($mem_form_submit)
  804. {
  805. if (strpos($name, '[]'))
  806. {
  807. $value = ps(substr($name, 0, strlen($name)-2));
  808. $selected = $value;
  809. if ($as_csv)
  810. {
  811. $value = implode($delimiter, $value);
  812. }
  813. }
  814. else
  815. {
  816. $value = trim(ps($name));
  817. $selected = array($value);
  818. }
  819. if (!empty($selected))
  820. {
  821. if (count($selected) <= $select_limit)
  822. {
  823. foreach ($selected as $v)
  824. {
  825. $is_valid = ($use_values_array && in_array($v, $values)) or (!$use_values_array && in_array($v, $items));
  826. if (!$is_valid)
  827. {
  828. $invalid_value = $v;
  829. break;
  830. }
  831. }
  832. if ($is_valid)
  833. {
  834. $isError = false === mem_form_store($name, $label, $value);
  835. }
  836. else
  837. {
  838. $mem_form_error[] = mem_form_gTxt('invalid_value', array('{label}'=> htmlspecialchars($label), '{value}'=> htmlspecialchars($invalid_value)));
  839. $isError = true;
  840. }
  841. }
  842. else
  843. {
  844. $mem_form_error[] = mem_form_gTxt('invalid_too_many_selected', array(
  845. '{label}'=> htmlspecialchars($label),
  846. '{count}'=> $select_limit,
  847. '{plural}'=> ($select_limit==1 ? mem_form_gTxt('item') : mem_form_gTxt('items'))
  848. ));
  849. $isError = true;
  850. }
  851. }
  852. elseif ($required)
  853. {
  854. $mem_form_error[] = mem_form_gTxt('field_missing', array('{label}'=> htmlspecialchars($label)));
  855. $isError = true;
  856. }
  857. }
  858. else if (isset($mem_form_default[$name]))
  859. {
  860. $selected = array($mem_form_default[$name]);
  861. }
  862. $out = '';
  863. foreach ($items as $item)
  864. {
  865. $v = $use_values_array ? array_shift($values) : $item;
  866. $sel = !empty($selected) && in_array($v, $selected);
  867. $out .= n.t.'<option'.($use_values_array ? ' value="'.$v.'"' : '').($sel ? ' selected="selected">' : '>').
  868. (strlen($item) ? htmlspecialchars($item) : ' ').'</option>';
  869. }
  870. $isError = $isError ? 'errorElement' : '';
  871. $memRequired = $required ? 'memRequired' : '';
  872. $class = htmlspecialchars($class);
  873. $multiple = $select_limit > 1 ? ' multiple="multiple"' : '';
  874. return '<label for="'.$name.'" class="'.$class.' '.$memRequired.$isError.' '.$name.'">'.htmlspecialchars($label).'</label>'.$break.
  875. n.'<select id="'.$name.'" name="'.$name.'" class="'.$class.' '.$memRequired.$isError.'"' . $multiple .
  876. ( !empty($attrs) ? ' ' . $attrs : '').'>'.
  877. $out.
  878. n.'</select>';
  879. }
  880. function mem_form_checkbox($atts)
  881. {
  882. global $mem_form_error, $mem_form_submit, $mem_form_default, $mem_form_default_break;
  883. extract(mem_form_lAtts(array(
  884. 'break' => $mem_form_default_break,
  885. 'checked' => 0,
  886. 'isError' => '',
  887. 'label' => mem_form_gTxt('checkbox'),
  888. 'name' => '',
  889. 'class' => 'memCheckbox',
  890. 'required' => 1,
  891. 'attrs' => ''
  892. ), $atts));
  893. if (empty($name)) $name = mem_form_label2name($label);
  894. if ($mem_form_submit)
  895. {
  896. $value = (bool) ps($name);
  897. if ($required and !$value)
  898. {
  899. $mem_form_error[] = mem_form_gTxt('field_missing', array('{label}'=> htmlspecialchars($label)));
  900. $isError = true;
  901. }
  902. else
  903. {
  904. $isError = false === mem_form_store($name, $label, $value ? gTxt('yes') : gTxt('no'));
  905. }
  906. }
  907. else {
  908. if (isset($mem_form_default[$name]))
  909. $value = $mem_form_default[$name];
  910. else
  911. $value = $checked;
  912. }
  913. $isError = $isError ? 'errorElement' : '';
  914. $memRequired = $required ? 'memRequired' : '';
  915. $class = htmlspecialchars($class);
  916. return '<input type="checkbox" id="'.$name.'" class="'.$class.' '.$memRequired.$isError.'" name="'.$name.'"'.
  917. ( !empty($attrs) ? ' ' . $attrs : '').
  918. ($value ? ' checked="checked"' : '').' />'.$break.
  919. '<label for="'.$name.'" class="'.$class.' '.$memRequired.$isError.' '.$name.'">'.htmlspecialchars($label).'</label>';
  920. }
  921. function mem_form_serverinfo($atts)
  922. {
  923. global $mem_form_submit;
  924. extract(mem_form_lAtts(array(
  925. 'label' => '',
  926. 'name' => ''
  927. ), $atts));
  928. if (empty($name)) $name = mem_form_label2name($label);
  929. if (strlen($name) and $mem_form_submit)
  930. {
  931. if (!$label) $label = $name;
  932. mem_form_store($name, $label, serverSet($name));
  933. }
  934. }
  935. function mem_form_secret($atts, $thing = '')
  936. {
  937. global $mem_form_submit;
  938. extract(mem_form_lAtts(array(
  939. 'name' => '',
  940. 'label' => mem_form_gTxt('secret'),
  941. 'value' => ''
  942. ), $atts));
  943. $name = mem_form_label2name($name ? $name : $label);
  944. if ($mem_form_submit)
  945. {
  946. if ($thing)
  947. $value = trim(parse($thing));
  948. else
  949. $value = trim(parse($value));
  950. mem_form_store($name, $label, $value);
  951. }
  952. return '';
  953. }
  954. function mem_form_hidden($atts, $thing='')
  955. {
  956. global $mem_form_submit, $mem_form_default;
  957. extract(mem_form_lAtts(array(
  958. 'name' => '',
  959. 'label' => mem_form_gTxt('hidden'),
  960. 'value' => '',
  961. 'isError' => '',
  962. 'required' => 1,
  963. 'class' => 'memHidden',
  964. 'escape_value' => 1,
  965. 'attrs' => ''
  966. ), $atts));
  967. $name = mem_form_label2name($name ? $name : $label);
  968. if ($mem_form_submit)
  969. {
  970. $value = preg_replace('/^\s*[\r\n]/', '', rtrim(ps($name)));
  971. $utf8len = preg_match_all("/./su", ltrim($value), $utf8ar);
  972. $hlabel = htmlspecialchars($label);
  973. if (strlen($value))
  974. {
  975. if (!$utf8len)
  976. {
  977. $mem_form_error[] = mem_form_gTxt('invalid_utf8', $hlabel);
  978. $isError = true;
  979. }
  980. else
  981. {
  982. $isError = false === mem_form_store($name, $label, $value);
  983. }
  984. }
  985. }
  986. else
  987. {
  988. if (isset($mem_form_default[$name]))
  989. $value = $mem_form_default[$name];
  990. else if ($thing)
  991. $value = trim(parse($thing));
  992. }
  993. $isError = $isError ? 'errorElement' : '';
  994. $memRequired = $required ? 'memRequired' : '';
  995. if ($escape_value)
  996. {
  997. $value = htmlspecialchars($value);
  998. }
  999. return '<input type="hidden" class="'.$class.' '.$memRequired.$isError.' '.$name
  1000. . '" name="'.$name.'" value="'.$value.'" id="'.$name.'" '.$attrs.'/>';
  1001. }
  1002. function mem_form_radio($atts)
  1003. {
  1004. global $mem_form_error, $mem_form_submit, $mem_form_values, $mem_form_default, $mem_form_default_break;
  1005. extract(mem_form_lAtts(array(
  1006. 'break' => $mem_form_default_break,
  1007. 'checked' => 0,
  1008. 'group' => '',
  1009. 'label' => mem_form_gTxt('option'),
  1010. 'name' => '',
  1011. 'class' => 'memRadio',
  1012. 'isError' => '',
  1013. 'attrs' => '',
  1014. 'value' => false
  1015. ), $atts));
  1016. static $cur_name = '';
  1017. static $cur_group = '';
  1018. if (!$name and !$group and !$cur_name and !$cur_group) {
  1019. $cur_group = mem_form_gTxt('radio');
  1020. $cur_name = $cur_group;
  1021. }
  1022. if ($group and !$name and $group != $cur_group) $name = $group;
  1023. if ($name) $cur_name = $name;
  1024. else $name = $cur_name;
  1025. if ($group) $cur_group = $group;
  1026. else $group = $cur_group;
  1027. $id = 'q'.md5($name.'=>'.$label);
  1028. $name = mem_form_label2name($name);
  1029. $value = $value === false ? $id : $value;
  1030. if ($mem_form_submit)
  1031. {
  1032. $is_checked = (ps($name) == $value);
  1033. if ($is_checked or $checked and !isset($mem_form_values[$name]))
  1034. {
  1035. $isError = false === mem_form_store($name, $group, $value);
  1036. }
  1037. }
  1038. else
  1039. {
  1040. if (isset($mem_form_default[$name]))
  1041. $is_checked = $mem_form_default[$name] == $value;
  1042. else
  1043. $is_checked = $checked;
  1044. }
  1045. $class = htmlspecialchars($class);
  1046. $isError = $isError ? ' errorElement' : '';
  1047. return '<input value="'.$value.'" type="radio" id="'.$id.'" class="'.$class.' '.$name.$isError.'" name="'.$name.'"'.
  1048. ( !empty($attrs) ? ' ' . $attrs : '').
  1049. ( $is_checked ? ' checked="checked" />' : ' />').$break.
  1050. '<label for="'.$id.'" class="'.$class.' '.$name.'">'.htmlspecialchars($label).'</label>';
  1051. }
  1052. function mem_form_submit($atts, $thing='')
  1053. {
  1054. global $mem_form_submit;
  1055. extract(mem_form_lAtts(array(
  1056. 'button' => 0,
  1057. 'label' => mem_form_gTxt('save'),
  1058. 'name' => 'mem_form_submit',
  1059. 'class' => 'memSubmit',
  1060. ), $atts));
  1061. $label = htmlspecialchars($label);
  1062. $name = htmlspecialchars($name);
  1063. $class = htmlspecialchars($class);
  1064. if ($mem_form_submit)
  1065. {
  1066. $value = ps($name);
  1067. if (!empty($value) && $value == $label)
  1068. {
  1069. // save the clicked button value
  1070. mem_form_store($name, $label, $value);
  1071. }
  1072. }
  1073. if ($button or strlen($thing))
  1074. {
  1075. return '<button type="submit" class="'.$class.'" name="'.$name.'" value="'.$label.'">'.($thing ? trim(parse($thing)) : $label).'</button>';
  1076. }
  1077. else
  1078. {
  1079. return '<input type="submit" class="'.$class.'" name="'.$name.'" value="'.$label.'" />';
  1080. }
  1081. }
  1082. function mem_form_lAtts($arr, $atts, $warn=true)
  1083. {
  1084. foreach(array('button', 'checked', 'required', 'show_input', 'show_error') as $key)
  1085. {
  1086. if (isset($atts[$key]))
  1087. {
  1088. $atts[$key] = ($atts[$key] === 'yes' or intval($atts[$key])) ? 1 : 0;
  1089. }
  1090. }
  1091. if (isset($atts['break']) and $atts['break'] == 'br') $atts['break'] = '<br />';
  1092. return lAtts($arr, $atts, $warn);
  1093. }
  1094. function mem_form_label2name($label)
  1095. {
  1096. $label = trim($label);
  1097. if (strlen($label) == 0) return 'invalid';
  1098. if (strlen($label) <= 32 and preg_match('/^[a-zA-Z][A-Za-z0-9:_-]*$/', $label)) return $label;
  1099. else return 'q'.md5($label);
  1100. }
  1101. function mem_form_store($name, $label, $value)
  1102. {
  1103. global $mem_form, $mem_form_labels, $mem_form_values;
  1104. $mem_form[$label] = $value;
  1105. $mem_form_labels[$name] = $label;
  1106. $mem_form_values[$name] = $value;
  1107. $is_valid = false !== callback_event('mem_form.store_value', $name);
  1108. // invalid data, unstore it
  1109. if (!$is_valid)
  1110. mem_form_remove($name);
  1111. return $is_valid;
  1112. }
  1113. function mem_form_remove($name)
  1114. {
  1115. global $mem_form, $mem_form_labels, $mem_form_values;
  1116. $label = $mem_form_labels[$name];
  1117. unset($mem_form_labels[$name], $mem_form[$label], $mem_form_values[$name]);
  1118. }
  1119. function mem_form_display_error()
  1120. {
  1121. global $mem_form_error;
  1122. $out = n.'<ul class="memError">';
  1123. foreach (array_unique($mem_form_error) as $error)
  1124. {
  1125. $out .= n.t.'<li>'.$error.'</li>';
  1126. }
  1127. $out .= n.'</ul>';
  1128. return $out;
  1129. }
  1130. function mem_form_value($atts, $thing)
  1131. {
  1132. global $mem_form_submit, $mem_form_values, $mem_form_default;
  1133. extract(mem_form_lAtts(array(
  1134. 'name' => '',
  1135. 'wraptag' => '',
  1136. 'class' => '',
  1137. 'attributes'=> '',
  1138. 'id' => '',
  1139. ), $atts));
  1140. $out = '';
  1141. if ($mem_form_submit)
  1142. {
  1143. if (isset($mem_form_values[$name]))
  1144. $out = $mem_form_values[$name];
  1145. }
  1146. else {
  1147. if (isset($mem_form_default[$name]))
  1148. $out = $mem_form_default[$name];
  1149. }
  1150. return doTag($out, $wraptag, $class, $attributes, $id);
  1151. }
  1152. function mem_form_error($err=NULL)
  1153. {
  1154. global $mem_form_error;
  1155. if (!is_array($mem_form_error))
  1156. $mem_form_error = array();
  1157. if ($err == NULL)
  1158. return !empty($mem_form_error) ? $mem_form_error : false;
  1159. $mem_form_error[] = $err;
  1160. }
  1161. function mem_form_default($key,$val=NULL)
  1162. {
  1163. global $mem_form_default;
  1164. if (is_array($key))
  1165. {
  1166. foreach ($key as $k=>$v)
  1167. {
  1168. mem_form_default($k,$v);
  1169. }
  1170. return;
  1171. }
  1172. $name = mem_form_label2name($key);
  1173. if ($val == NULL)
  1174. {
  1175. return (isset($mem_form_default[$name]) ? $mem_form_default[$name] : false);
  1176. }
  1177. $mem_form_default[$name] = $val;
  1178. return $val;
  1179. }
  1180. function mem_form_mail($from,$reply,$to,$subject,$msg, $content_type='text/plain')
  1181. {
  1182. global $prefs;
  1183. if (!is_callable('mail'))
  1184. return false;
  1185. $deliverTo = '';
  1186. if (is_array($to)) {
  1187. $bcc = isset($to['bcc']) ? mem_form_strip($to['bcc']) : '';
  1188. $deliverTo = isset($to['to']) ? mem_form_strip($to['to']) : '';
  1189. } else {
  1190. $bcc = '';
  1191. $deliverTo = mem_form_strip($to);
  1192. }
  1193. $from = mem_form_strip($from);
  1194. $reply = mem_form_strip($reply);
  1195. $subject = mem_form_strip($subject);
  1196. $msg = mem_form_strip($msg,FALSE);
  1197. if ($prefs['override_emailcharset'] and is_callable('utf8_decode')) {
  1198. $charset = 'ISO-8859-1';
  1199. $subject = utf8_decode($subject);
  1200. $msg = utf8_decode($msg);
  1201. }
  1202. else {
  1203. $charset = 'UTF-8';
  1204. }
  1205. $subject = mem_form_mailheader($subject,'text');
  1206. $sep = !is_windows() ? "\n" : "\r\n";
  1207. $headers = 'From: ' . $from .
  1208. ($bcc ? ($sep . 'Bcc: ' . $bcc) : '') .
  1209. ($reply ? ($sep.'Reply-To: '.$reply) : '') .
  1210. $sep.'X-Mailer: Textpattern (mem_form)' .
  1211. $sep.'X-Originating-IP: '.mem_form_strip((!empty($_SERVER['HTTP_X_FORWARDED_FOR']) ? $_SERVER['HTTP_X_FORWARDED_FOR'].' via ' : '').$_SERVER['REMOTE_ADDR']) .
  1212. $sep.'Content-Transfer-Encoding: 8bit' .
  1213. $sep.'Content-Type: '.$content_type.'; charset="'.$charset.'"';
  1214. return mail($deliverTo, $subject, $msg, $headers);
  1215. }
  1216. function mem_form_mailheader($string, $type)
  1217. {
  1218. global $prefs;
  1219. if (!strstr($string,'=?') and !preg_match('/[\x00-\x1F\x7F-\xFF]/', $string)) {
  1220. if ("phrase" == $type) {
  1221. if (preg_match('/[][()<>@,;:".\x5C]/', $string)) {
  1222. $string = '"'. strtr($string, array("\\" => "\\\\", '"' => '\"')) . '"';
  1223. }
  1224. }
  1225. elseif ("text" != $type) {
  1226. trigger_error('Unknown encode_mailheader type', E_USER_WARNING);
  1227. }
  1228. return $string;
  1229. }
  1230. if ($prefs['override_emailcharset']) {
  1231. $start = '=?ISO-8859-1?B?';
  1232. $pcre = '/.{1,42}/s';
  1233. }
  1234. else {
  1235. $start = '=?UTF-8?B?';
  1236. $pcre = '/.{1,45}(?=[\x00-\x7F\xC0-\xFF]|$)/s';
  1237. }
  1238. $end = '?=';
  1239. $sep = is_windows() ? "\r\n" : "\n";
  1240. preg_match_all($pcre, $string, $matches);
  1241. return $start . join($end.$sep.' '.$start, array_map('base64_encode',$matches[0])) . $end;
  1242. }
  1243. function mem_form_strip($str, $header = TRUE) {
  1244. if ($header) $str = strip_rn($str);
  1245. return preg_replace('/[\x00]/', ' ', $str);
  1246. }
  1247. ///////////////////////////////////////////////
  1248. // Spam Evaluator
  1249. class mem_form_evaluation
  1250. {
  1251. var $status;
  1252. function mem_form_evaluation() {
  1253. $this->status = 0;
  1254. }
  1255. function add_status($rating=-1) {
  1256. $this->status += $rating;
  1257. }
  1258. function get_status() {
  1259. return $this->status;
  1260. }
  1261. function is_spam() {
  1262. return ($this->status < 0);
  1263. }
  1264. }
  1265. function &get_mem_form_evaluator()
  1266. {
  1267. static $instance;
  1268. if(!isset($instance)) {
  1269. $instance = new mem_form_evaluation();
  1270. }
  1271. return $instance;
  1272. }
  1273. # --- END PLUGIN CODE ---
  1274. if (0) {
  1275. ?>
  1276. <!--
  1277. # --- BEGIN PLUGIN HELP ---
  1278. <h1>mem_form plugin</h1>
  1279. <h2>Summary</h2>
  1280. <p>This plugin provides <span class="caps">HTML</span> form capabilities for other plugins. This allows for consistent form tags and behaviors, while reducing overall plugin size and development time.</p>
  1281. <h2>Author Contact</h2>
  1282. <p><a href="mailto:mmanfre@gmail.com?subject=Textpattern%20mem_form%20plugin" rel="nofollow">Michael Manfre</a><br />
  1283. <a href="http://manfre.net" rel="nofollow">http://manfre.net</a></p>
  1284. <h2>License</h2>
  1285. <p>This plugin is licensed under the <a href="http://www.fsf.org/licensing/licenses/info/GPLv2.html" rel="nofollow">GPLv2</a>.</p>
  1286. <h2>Tags</h2>
  1287. <ul>
  1288. <li><a href="#mem_form" rel="nofollow">mem_form</a></li>
  1289. <li><a href="#mem_form_checkbox" rel="nofollow">mem_form_checkbox</a></li>
  1290. <li><a href="#mem_form_email" rel="nofollow">mem_form_email</a></li>
  1291. <li><a href="#mem_form_file" rel="nofollow">mem_form_file</a></li>
  1292. <li><a href="#mem_form_hidden" rel="nofollow">mem_form_hidden</a></li>
  1293. <li><a href="#mem_form_radio" rel="nofollow">mem_form_radio</a></li>
  1294. <li><a href="#mem_form_secret" rel="nofollow">mem_form_secret</a></li>
  1295. <li><a href="#mem_form_select" rel="nofollow">mem_form_select</a></li>
  1296. <li><a href="#mem_form_select_category" rel="nofollow">mem_form_select_category</a></li>
  1297. <li><a href="#mem_form_select_range" rel="nofollow">mem_form_select_range</a></li>
  1298. <li><a href="#mem_form_select_section" rel="nofollow">mem_form_select_section</a></li>
  1299. <li><a href="#mem_form_serverinfo" rel="nofollow">mem_form_serverinfo</a></li>
  1300. <li><a href="#mem_form_submit" rel="nofollow">mem_form_submit</a></li>
  1301. <li><a href="#mem_form_text" rel="nofollow">mem_form_text</a></li>
  1302. <li><a href="#mem_form_textarea" rel="nofollow">mem_form_textarea</a></li>
  1303. <li><a href="#mem_form_value" rel="nofollow">mem_form_value</a></li>
  1304. </ul>
  1305. <h3>mem_form</h3>
  1306. <p>This tag will create an <span class="caps">HTML</span> form and contains all of the processing and validation.</p>
  1307. <ul>
  1308. <li><span>form</span> <span>string</span> Name of a form that will be parsed to display the form.</li>
  1309. <li><span>thanks_form</span> <span>string</span> Name of a form that will be parsed upon successful form submission.</li>
  1310. <li><span>label</span> <span>string</span> Accessible name for the form.</li>
  1311. <li><span>type</span> <span>string</span> Name of the form to identify itself to bound plugin.</li>
  1312. <li><span>thanks</span> <span>string</span> Message to display to user upon successful form submission.</li>
  1313. <li><span>redirect</span> <span>url</span> <span class="caps">URL</span> to redirect upon successful form submission. Overrides &#8220;thanks&#8221; and &#8220;thanks_form&#8221;.</li>
  1314. <li><span>redirect_form</span> <span>string</span> Name of a form that will be parsed as displayed to the user on a redirect. The string &#8220;<em>{uri}</em>&#8221; will be replaced with the redirect url.</li>
  1315. <li><span>enctype</span> <span>string</span> <span class="caps">HTML</span> encoding type used when the form is submitted. <code>enctype=&quot;multipart/form-data&quot;</code> is required when using mem_form_file.</li>
  1316. <li><span>default_break</span> <span>string</span> Separator between label tag and input tag to be used as the default for every mem_form compatible field contained in the form. Default is &lt;br&gt;</li>
  1317. </ul>
  1318. <h3>mem_form_checkbox</h3>
  1319. <p>This will output an <span class="caps">HTML</span> checkbox field.</p>
  1320. <ul>
  1321. <li><span>break</span> <span>string</span> Separator between label tag and input tag.</li>
  1322. <li><span>checked</span> <span>int</span> Is this box checked. Default &#8220;0&#8221;.</li>
  1323. <li><span>label</span> <span>string</span> Friendly name for the input field. If set, this will output an <span class="caps">HTML</span> &lt;label&gt; tag linked to the input field.</li>
  1324. <li><span>name</span> <span>string</span> Input field name.</li>
  1325. <li><span>required</span> <span>int</span> Specifies if input is required.</li>
  1326. <li><span>class</span> <span>string</span> <span class="caps">CSS</span> class name.</li>
  1327. </ul>
  1328. <h3>mem_form_email</h3>
  1329. <p>This will output an <span class="caps">HTML</span> text input field and validates the submitted value as an email address.</p>
  1330. <ul>
  1331. <li><span>break</span> <span>string</span> Separator between label tag and input tag.</li>
  1332. <li><span>label</span> <span>string</span> Friendly name for the input field. If set, this will output an <span class="caps">HTML</span> &lt;label&gt; tag linked to the input field.</li>
  1333. <li><span>name</span> <span>string</span> Input field name.</li>
  1334. <li><span>required</span> <span>int</span> Specifies if input is required.</li>
  1335. <li><span>class</span> <span>string</span> <span class="caps">CSS</span> class name.</li>
  1336. <li><span>default</span> <span>string</span> The default value.</li>
  1337. <li><span>max</span> <span>int</span> Max character length.</li>
  1338. <li><span>min</span> <span>int</span> Min character length.</li>
  1339. <li><span>size</span> <span>int</span> Size of input field.</li>
  1340. </ul>
  1341. <h3>mem_form_file</h3>
  1342. <p>+p(tag-summary). This will output an <span class="caps">HTML</span> file input field. You must add the <code>enctype=&quot;multipart/form-data&quot;</code> attribute to your enclosing mem_form for this to work.</p>
  1343. <ul>
  1344. <li><span>label</span> <span>string</span> Friendly name for the input field. If set, this will output an <span class="caps">HTML</span> &lt;label&gt; tag linked to the input field.</li>
  1345. <li><span>name</span> <span>string</span> Input field name.</li>
  1346. <li><span>class</span> <span>string</span> <span class="caps">CSS</span> class name.</li>
  1347. <li><span>break</span> <span>string</span> Separator between label tag and input tag.</li>
  1348. <li><span>no_replace</span> <span>int</span> Specifies whether a user can upload another file and replace the existing file that will be submitted on successful completion of the form. If &#8220;1&#8221;, the file input field will be replaced with details about the already uploaded file.</li>
  1349. <li><span>required</span> <span>int</span> Specifies if input is required.</li>
  1350. <li><span>size</span> <span>int</span> Size of input field.</li>
  1351. <li><span>max_file_size</span> <span>int</span> Maximum size for the uploaded file. Checked server-side.</li>
  1352. <li><span>accept</span> <span>string</span> The <span class="caps">HTML</span> file input field&#8217;s &#8220;accept&#8221; argument that specifies which file types the field should permit.</li>
  1353. </ul>
  1354. <h3>mem_form_hidden</h3>
  1355. <p>This will output an <span class="caps">HTML</span> hidden text input field.</p>
  1356. <ul>
  1357. <li><span>label</span> <span>string</span> Friendly name for the input field. If set, this will output an <span class="caps">HTML</span> &lt;label&gt; tag linked to the input field.</li>
  1358. <li><span>name</span> <span>string</span> Input field name.</li>
  1359. <li><span>value</span> <span>string</span> The input value.</li>
  1360. <li><span>required</span> <span>int</span> Specifies if input is required.</li>
  1361. <li><span>class</span> <span>string</span> <span class="caps">CSS</span> class name.</li>
  1362. <li><span>escape_value</span> <span>int</span> Set to &#8220;0&#8221; to prevent html escaping the value. Default &#8220;1&#8221;.</li>
  1363. </ul>
  1364. <h3>mem_form_radio</h3>
  1365. <p>This will output an <span class="caps">HTML</span> radio button.</p>
  1366. <ul>
  1367. <li><span>break</span> <span>string</span> Separator between label tag and input tag.</li>
  1368. <li><span>label</span> <span>string</span> Friendly name for the input field. If set, this will output an <span class="caps">HTML</span> &lt;label&gt; tag linked to the input field.</li>
  1369. <li><span>name</span> <span>string</span> Input field name.</li>
  1370. <li><span>class</span> <span>string</span> <span class="caps">CSS</span> class name.</li>
  1371. <li><span>group</span> <span>string</span> A name that identifies a group of radio buttons.</li>
  1372. <li><span>value</span> <span>string</span> The value of the radio button. If not set, a unique value is generated.</li>
  1373. <li><span>checked</span> <span>int</span> Is this box checked. Default &#8220;0&#8221;.</li>
  1374. </ul>
  1375. <h3>mem_form_secret</h3>
  1376. <p>This will output nothing in <span class="caps">HTML</span> and is meant to pass information to the sumbit handler plugins.</p>
  1377. <ul>
  1378. <li><span>label</span> <span>string</span> Friendly name for the input field. If set, this will output an <span class="caps">HTML</span> &lt;label&gt; tag linked to the input field.</li>
  1379. <li><span>name</span> <span>string</span> Input field name.</li>
  1380. <li><span>value</span> <span>string</span> The input value.</li>
  1381. </ul>
  1382. <h3>mem_form_select</h3>
  1383. <p>This will output an <span class="caps">HTML</span> select field.</p>
  1384. <ul>
  1385. <li><span>label</span> <span>string</span> Friendly name for the input field. If set, this will output an <span class="caps">HTML</span> &lt;label&gt; tag linked to the input field.</li>
  1386. <li><span>name</span> <span>string</span> Input field name.</li>
  1387. <li><span>break</span> <span>string</span> Separator between label tag and input tag.</li>
  1388. <li><span>delimiter</span> <span>string</span> List separator. Default &#8220;,&#8221;</li>
  1389. <li><span>items</span> <span>string</span> Delimited list containing a select list display values.</li>
  1390. <li><span>values</span> <span>string</span> Delimited list containing a select list item values.</li>
  1391. <li><span>required</span> <span>int</span>

Large files files are truncated, but you can click here to view the full file