forked from stefangabos/Zebra_Form
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathZebra_Form.php
4949 lines (3652 loc) · 228 KB
/
Zebra_Form.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<?php
define('ZEBRA_FORM_UPLOAD_RANDOM_NAMES', false);
/**
* Zebra_Form, a jQuery augmented PHP library for creating and validating HTML forms
*
* It provides an easy and intuitive way of creating template-driven, visually appealing forms, complex client-side and
* server-side validations and prevention against cross-site scripting (XSS) and cross-site request forgery (CSRF) attacks
* prevention.
*
* For the form validation part you can use the built-in rules (i.e. required fields, emails, minimum/maximum length,
* etc) and you can also define custom rules, with extreme ease, depending on your specific needs.
*
* All the basic controls that you would find in a form are available plus a few extra: text, textarea, submit, image,
* reset, button, file, password, radio buttons, checkboxes, hidden, captcha, date and time pickers.
*
* One additional note: this class is not a drag and drop utility - it is intended for coders who are comfortable with
* PHP, HTML, CSS and JavaScript/jQuery - you will have to build your forms when using this class, but it saves a great
* deal of time when it comes to validation and assures that your forms are secure and have a consistent look and feel
* throughout your projects!
*
* Requires PHP 5.0.2+ (compiled with the php_fileinfo extension), and jQuery 1.6.2+
*
* Visit {@link http://stefangabos.ro/php-libraries/zebra-form/} for more information.
*
* For more resources visit {@link http://stefangabos.ro/}
*
* @author Stefan Gabos <contact@stefangabos.ro>
* @version 2.9.4 (last revision: May 30, 2014)
* @copyright (c) 2006 - 2014 Stefan Gabos
* @license http://www.gnu.org/licenses/lgpl-3.0.txt GNU LESSER GENERAL PUBLIC LICENSE
* @package Zebra_Form
*/
class Zebra_Form
{
/**
* Array containing all the controls added to the form
*
* @var array
*
* @access private
*/
var $controls;
/**
* Array containing all the error messages generated by the form
*
* @var array
*
* @access private
*/
var $errors;
/**
* An associative array of items uploaded to the current script via the HTTP POST method.
* This property, available only if a file upload has occurred, will have the same values as
* {@link http://php.net/manual/en/reserved.variables.files.php $_FILES} plus some extra values:
*
* - <b>path</b> - the path where the file was uploaded to
* - <b>file_name</b> - the name the file was uploaded with
* - <b>imageinfo</b> - <b>available only if the uploaded file is an image!</b><br>
* an array of attributes specific to the uploaded image as returned by
* {@link http://www.php.net/manual/en/function.getimagesize.php getimagesize()} but
* with meaningful names:<br>
* <b>bits</b><br>
* <b>channels</b><br>
* <b>mime</b><br>
* <b>width</b><br>
* <b>height</b><br>
* <b>type</b> ({@link http://php.net/manual/en/function.exif-imagetype.php possible types})<br>
* <b>html</b><br>
*
* <b>Note that the file name can be different than the original name of the uploaded file!</b>
*
* By design, the script will append
* a number to the end of a file's name if at the path where the file is uploaded to there is another file with the
* same name (for example, if at the path where a file named "example.txt" is uploaded to, a file with the same name
* exists, the file's new name will be "example1.txt").
*
* The file names can also be random-generated. See the {@link Zebra_Form_Control::set_rule() set_rule()} method and
* the <b>upload</b> rule
*
* @var array
*/
var $file_upload;
/**
* Indicates the {@link http://en.wikipedia.org/wiki/Filesystem_permissions filesystem} permissions to be set for
* files uploaded through the {@link Zebra_Form_Control::set_rule() upload} rule.
*
* <code>
* $form->file_upload_permissions = '0777';
* </code>
*
* The permissions are set using PHP's {@link http://php.net/manual/en/function.chmod.php chmod} function which may
* or may not be available or be disabled on your environment. If so, this action will fail silently (no errors or
* notices will be shown by the library).
*
* Better to leave this setting as it is.
*
* If you know what you are doing, here is how you can calculate the permission levels:
*
* - 400 Owner Read
* - 200 Owner Write
* - 100 Owner Execute
* - 40 Group Read
* - 20 Group Write
* - 10 Group Execute
* - 4 Global Read
* - 2 Global Write
* - 1 Global Execute
*
* Default is '0755'
*
* @var string
*/
var $file_upload_permissions;
/**
* Array containing the variables to be made available in the template file (added through the {@link assign()}
* method)
*
* @var array
*
* @access private
*/
var $variables;
/**
* Constructor of the class
*
* Initializes the form.
*
* <code>
* $form = new Zebra_Form('myform');
* </code>
*
* @param string $name Name of the form
*
* @param string $method (Optional) Specifies which HTTP method will be used to submit the form data set.
*
* Possible (case-insensitive) values are <b>POST</b> an <b>GET</b>
*
* Default is <b>POST</b>
*
* @param string $action (Optional) An URI to where to submit the form data set.
*
* If left empty, the form will submit to itself.
*
* <samp>You should *always* submit the form to itself, or server-side validation
* will not take place and you will have a great security risk. Submit the form
* to itself, let it do the server-side validation, and then redirect accordingly!</samp>
*
* @param array $attributes (Optional) An array of attributes valid for a <form> tag (i.e. style)
*
* Note that the following attributes are automatically set when the control is
* created and should not be altered manually:
*
* <b>action</b>, <b>method</b>, <b>enctype</b>, <b>name</b>
*
* @return void
*/
function __construct($name, $method = 'POST', $action = '', $attributes = '')
{
$this->controls = $this->variables = $this->errors = $this->master_labels = array();
// default filesysyem permissions for uploaded files
$this->file_upload_permissions = '0755';
// default values for the form's properties
$this->form_properties = array(
'action' => ($action == '' ? $_SERVER['REQUEST_URI'] : $action),
'assets_server_path' => rtrim(dirname(__FILE__), '\\/') . DIRECTORY_SEPARATOR,
'assets_url' => rtrim(str_replace('\\', '/', 'http' . (isset($_SERVER['HTTPS']) ? 's' : '') . '://' . rtrim($_SERVER['HTTP_HOST'], '\\/') . '/' . substr(rtrim(dirname(__FILE__), '\\/'), strlen($_SERVER['DOCUMENT_ROOT']))), '\\/') . '/',
'attributes' => $attributes,
'auto_fill' => false,
'captcha_storage' => 'cookie',
'csrf_cookie_config' => array('path' => '/', 'domain' => '', 'secure' => false, 'httponly' => false),
'csrf_cookie_name' => 'zebra_csrf_token_' . $name,
'csrf_storage_method' => 'auto',
'csrf_token' => '',
'csrf_token_lifetime' => 0,
'csrf_token_name' => 'zebra_csrf_token_' . $name,
'doctype' => 'html',
'has_upload' => false,
'honeypot' => 'zebra_honeypot_' . $name,
'identifier' => 'name_' . $name,
'language' => array(),
'method' => strtoupper($method),
'name' => $name,
'other_suffix' => '_other',
'secret_key' => '',
'show_all_error_messages' => false,
);
// set default client-side validation properties
$this->clientside_validation(true);
// get the maximum allowed file size for uploads
$upload_max_filesize = ini_get('upload_max_filesize');
// see what it is given in (G, M, K)
$unit = strtolower(substr($upload_max_filesize, -1));
// get the numeric value
$value = substr($upload_max_filesize, 0, -1);
// convert to bytes
// notice that there is no break
switch (strtolower(substr($upload_max_filesize, -1))) {
case 'g':
$value*=1024;
case 'm':
$value*=1024;
case 'k':
$value*=1024;
}
// set the form's respective property
$this->form_properties['max_file_size'] = $value;
// include the XSS filter class - the Zebra_Form_Control class extends this class
require_once dirname(__FILE__) . '/includes/XSSClean.php';
// include the Control.php file which contains the Zebra_Form_Control class which is
// extended by all of the classes
require_once dirname(__FILE__) . '/includes/Control.php';
// load the default language file
$this->language('english');
// enable protection against CSRF attacks using the default values
// note that this has no effect if this method was already called before
$this->csrf();
}
/**
* Adds a control to the form.
*
* <code>
* // create a new form
* $form = new Zebra_Form('my_form');
*
* // add a text control to the form
* $obj = $form->add('text', 'my_text');
*
* // make the text field required
* $obj->set_rule(
* 'required' => array(
* 'error', // variable to add the error message to
* 'Field is required' // error message if value doesn't validate
* )
* );
*
* // don't forget to always call this method before rendering the form
* if ($form->validate()) {
* // put code here
* }
*
* // output the form using an automatically generated template
* $form->render();
* </code>
*
* @param string $type Type of the control to add.
*
* Controls that can be added to a form:
*
* - {@link Zebra_Form_Button buttons}
* - {@link Zebra_Form_Captcha CAPTCHAs}
* - {@link Zebra_Form_Checkbox checkboxes}
* - {@link Zebra_Form_Date date pickers}
* - {@link Zebra_Form_File file upload controls}
* - {@link Zebra_Form_Hidden hidden controls}
* - {@link Zebra_Form_Image image button controls}
* - {@link Zebra_Form_Label labels}
* - {@link Zebra_Form_Note notes}
* - {@link Zebra_Form_Password password controls}
* - {@link Zebra_Form_Radio radio buttons}
* - {@link Zebra_Form_Reset reset buttons}
* - {@link Zebra_Form_Select selects}
* - {@link Zebra_Form_Submit submit buttons}
* - {@link Zebra_Form_Text text box controls}
* - {@link Zebra_Form_Textarea textareas}
* - {@link Zebra_Form_Time time pickers}
*
* @param mixed $arguments A list of arguments as required by the control that is added.
*
* @return reference Returns a reference to the newly created object
*/
function &add($type)
{
// if shortcut for multiple radio buttons or checkboxes
if ($type == 'radios' || $type == 'checkboxes') {
// if there are less than 3 arguments
if (func_num_args() < 3)
// trigger a warning
_zebra_form_show_error('For <strong>' . $type . '</strong>, the <strong>add()</strong> method requires at least 3 arguments', E_USER_WARNING);
// if third argument is not an array
elseif (!is_array(func_get_arg(2)))
// trigger a warning
_zebra_form_show_error('For <strong>' . $type . '</strong>, the <strong>add()</strong> method requires the 3rd argument to be an array', E_USER_WARNING);
// if everything is ok
else {
// controls' name
$name = func_get_arg(1);
// the values and labels
$values = func_get_arg(2);
// a 4th argument (the default option) was passed to the method
if (func_num_args() >= 4) {
// save the default value
$default = func_get_arg(3);
// if default value is not given as an array
// (makes sense for checkboxes when there may be multiple preselected values)
// make it an array
if (!is_array($default)) $default = array($default);
}
if (func_num_args() >= 5) $additional = func_get_arg(4);
$counter = 0;
// iterate through values and their respective labels
foreach ($values as $value => $caption) {
// create control
$obj = & $this->add(
($type == 'radios' ? 'radio' : 'checkbox'), $name, $value,
(isset($default) && in_array($value, $default) ?
(isset($additional) ? array_merge($additional, array('checked' => 'checked')) : array('checked' => 'checked')) :
(isset($additional) ? $additional :'')));
// if this is the first control in the array
// we will later need to return a reference to it
if ($counter++ == 0) $pointer = &$obj;
// sanitize controls' name (remove square brackets)
$sanitize_name = preg_replace('/\[\]$/', '', $name);
// santize the value
$value = str_replace(array(' '), array('_'), $value);
// add the label for the control
$this->add('label', 'label_' . $sanitize_name . '_' . $value, $sanitize_name . '_' . $value, $caption);
}
// if the array of values was not empty
// return reference to the first control
if (isset($pointer)) return $pointer;
}
// for all other controls
} else {
$file_name = ucfirst(strtolower($type));
// the classes have the "Zebra_Form_" prefix
$class_name = 'Zebra_Form_' . ucfirst(strtolower($type));
// include the file containing the PHP class, if not already included
require_once dirname(__FILE__) . '/includes/' . $file_name . '.php';
// if included file contains such a class
if (class_exists($class_name)) {
// prepare arguments passed to the add() method
// notice that first argument is ignored as it refers to the type of the control to add
// and we don't have to pass that to the class
$arguments = array_slice(func_get_args(), 1);
// if name was not specified trigger an error
if (strlen(trim($arguments[0])) == 0) trigger_error('Name is required for control of type ' . $class_name, E_USER_ERROR);
// use this method to instantiate the object with dynamic arguments
$obj = call_user_func_array(array(new ReflectionClass($class_name), 'newInstance'), $arguments);
// make available the form's properties in the newly created object
$obj->form_properties = & $this->form_properties;
// get some attributes for the newly created control
$attributes = $obj->get_attributes(array('id', 'name'));
// perform some extra tasks for different types of controls
switch ($class_name) {
// if the newly created control is a file upload control
case 'Zebra_Form_File':
// set a flag to be used at rendering
$this->form_properties['has_upload'] = true;
break;
// if the newly created control is a radio button or a checkbox
case 'Zebra_Form_Radio':
case 'Zebra_Form_Checkbox':
// radio buttons and checkboxes might have a "master label", a label that is tied to the radio buttons' or
// checkboxes' name rather than individual controls' IDs. (as grouped radio buttons and checkboxes share
// the same name but have different values)
// we use this so that, if the controls have the "required" rule set, the asterisk is attached to the master
// label rather than to one of the actual controls
// therefore, we generate a "lookup" array of "master" labels for each group of radio buttons or
// checkboxes. this does not means that there will be an actual master label - we use this lookup
// array to easily determine if a master label exists when rendering the form
// sanitize the control's name
$attributes['name'] = preg_replace('/\[\]$/', '', $attributes['name']);
// if there isn't a master label for the group the current control is part of
if (!isset($this->master_labels[$attributes['name']]))
// create the entry
// the "control" index will hold the actual label's name if a "master" label is added to the form
$this->master_labels[$attributes['name']] = array('control' => false);
break;
}
// put the reference to the newly created object in the 'controls' array
$this->controls[$attributes['id']] = &$obj;
// return the identifier to the newly created object
return $obj;
}
}
}
/**
* Appends a message to an already existing {@link Zebra_Form_Control::set_rule() error block}
*
* <code>
* // create a new form
* $form = new Zebra_Form('my_form');
*
* // add a text control to the form
* $obj = $form->add('text', 'my_text');
*
* // make the text field required
* $obj->set_rule(
* 'required' => array(
* 'error', // variable to add the error message to
* 'Field is required' // error message if value doesn't validate
* )
* );
*
* // don't forget to always call this method before rendering the form
* if ($form->validate()) {
*
* // for the purpose of this example, we will do a custom validation
* // after calling the "validate" method.
* // for custom validations, using the "custom" rule is recommended instead
*
* // check if value's is between 1 and 10
* if ((int)$_POST['my_text']) < 1 || (int)$_POST['my_text']) > 10) {
*
* $form->add_error('error', 'Value must be an integer between 1 and 10!');
*
* } else {
*
* // put code here that is to be executed when the form values are ok
*
* }
*
* }
*
* // output the form using an automatically generated template
* $form->render();
* </code>
*
* @param string $error_block The name of the error block to append the error message to (also the name
* of the PHP variable that will be available in the template file).
*
* @param string $error_message The error message to append to the error block.
*
* @return void
*/
function add_error($error_block, $error_message)
{
// if the error block was not yet created, create the error block
if (!isset($this->errors[$error_block])) $this->errors[$error_block] = array();
// if the same exact message doesn't already exists
if (!in_array(trim($error_message), $this->errors[$error_block]))
// append the error message to the error block
$this->errors[$error_block][] = trim($error_message);
}
/**
* Set the server path and URL to the "process.php" and "mimes.json" files.
*
* These files are required for CAPTCHAs and uploads.
*
* By default, the location of these files is in the same folder as Zebra_Form.php and the script will automatically
* try to determine both the server path and the URL to these files. However, when the script is run on a virtual
* host, or if these files were moved, the script may not correctly determine the paths to these files. In these
* instances, use this method to correctly set the server path - needed by the script to correctly include these
* files, and the URL - needed by the client-side validation to include these files.
*
* Also, for security reasons, I recommend moving these two files by default to the root of your website (or another
* publicly accessible place) and manually set the paths, in order to prevent malicious users from finding out
* information about your directory structure.
*
* <samp>If you move these files don't forget to also move the font file from the "includes" folder, and to manually
* adjust the path to the font file in "process.php"!</samp>
*
* @param string $server_path The server path (the one similar to what is in $_SERVER['DOCUMENT_ROOT']) to
* the folder where the "process.php" and "mimes.json" files can be found.
*
* <i>With trailing slash!</i>
*
* @param string $url The URL to where the "process.php" and "mimes.json" files can be found.
*
* <i>With trailing slash!</i>
*
* @return void
*/
function assets_path($server_path, $url)
{
// set values
$this->form_properties['assets_server_path'] = $server_path;
$this->form_properties['assets_url'] = $url;
}
/**
* Creates a PHP variable with the given value, available in the template file.
*
* <code>
* // create a new form
* $form = new Zebra_Form('my_form');
*
* // make available the $my_value variable in the template file
* $form->assign('my_value', '100');
*
* // don't forget to always call this method before rendering the form
* if ($form->validate()) {
* // put code here
* }
*
* // output the form
* // notice that we are using a custom template
* // my_template.php file is expected to be found
* // and in this file, you may now use the $my_value variable
* $form->render('my_template.php');
* </code>
*
* @param string $variable_name Name by which the variable will be available in the template file.
*
* @param mixed $value The value to be assigned to the variable.
*
* @return void
*/
function assign($variable_name, $value)
{
// save the variable in an array that we will make available in the template file upon rendering
$this->variables[$variable_name] = $value;
}
/**
* Call this method anytime *before* calling the {@link render()} method to instruct the library to automatically
* fill out all of the form's fields with random content while obeying any rules that might be set for each control.
*
* You can also use this method to set defaults for the form's elements by setting the method's second argument to TRUE.
*
* <b>Notes:</b>
*
* - unless overridden, the value of {@link Zebra_Form_Password password} controls will always be "12345678";
* - unless overridden, the value of controls having the "email" or "emails" {@link Zebra_Form_Control::set_rule() rule}
* set will be in the form of <i>random_text@random_text.com</i>;
* - unless overridden, the value of controls having the "url" {@link Zebra_Form_Control::set_rule() rule} set will
* be in the form of <i>random_text.com</i>, prefixed or not with "http://", depending on the rule's attributes;
* - {@link Zebra_Form_File file upload} controls and controls having the "captcha" or "regexp"
* {@link Zebra_Form_Control::set_rule() rule} set will *not* be autofilled;
*
* <samp>This method will produce results *only* if the form has not yet been submitted! Also, this method will fill
* elements with random content *only* if the element does not already has a default value! And finally, this method
* will produce no results unless at some point the form's {@link validate()} method is called.</samp>
*
* @param array $defaults An associative array in the form of <i>$element => $value</i> used for filling
* out specific fields with specific values instead of random ones.
*
* For elements that may have more than one value (checkboxes and selects with
* the "multiple" attribute set) you may set the value as an array.
*
* <code>
* // auto-fill all fields with random values
* $form->auto_fill();
*
* // auto-fill all fields with random values
* // except the one called "email" which should have a custom value
* $form->auto_fill(array(
* 'email' => 'some@email.com',
* ));
*
* // auto-fill all fields with random values
* // except a checkboxes group where we select multiple values
* // note that we use "my_checkboxes" insteas of "my_checkboxes[]"
* // (the same goes for "selects" with the "multiple" attribute set)
* $form->auto_fill(array(
* 'my_checkboxes' => array('value_1', 'value_2'),
* ));
* </code>
*
* @param boolean $specifics_only (Optional) If set to TRUE only the fields given in the $defaults argument
* will be filled with the given values and the other fields will be skipped.
*
* Can be used as a handy shortcut for giving default values to elements instead
* of putting default values in the constructor or using the {@link set_attributes()}
* method.
*
* Default is FALSE.
*
*
* @since 2.8.9
*
* @return void
*/
function auto_fill($defaults = array(), $specifics_only = false)
{
$this->form_properties['auto_fill'] = array($defaults, $specifics_only);
}
/**
* Sets the storage method for CAPTCHA values.
*
* By default, captcha values are triple md5 hashed and stored in cookies, and when the user enters the captcha
* value the value is also triple md5 hashed and the two values are then compared.
*
* Sometimes, your users may have a very restrictive cookie policy and so cookies will not be set, and therefore,
* they will never be able to get past the CAPTCHA control. If it's the case, call this method and set the storage
* method to "session".
*
* In this case, call this method and set the the storage method to "session".
*
* @param string $method Storage method for CAPTCHA values.
*
* Valid values are "cookie" and "session".
*
* Default is "cookie".
*
* @since 2.8.9
*
* @return void
*/
function captcha_storage($method)
{
// if storage method is "session"
if ($method == 'session')
// set the storage method
$this->form_properties['captcha_storage'] = 'session';
// "cookie" otherwise
else $this->form_properties['captcha_storage'] = 'cookie';
}
/**
* Alias of {@link clientside_validation()} method.
*
* Deprecated since 2.8.9
*/
function client_side_validation($properties)
{
$this->clientside_validation($properties);
}
/**
* Sets properties for the client-side validation.
*
* Client-side validation, when enabled, occurs on the "onsubmit" event of the form.
*
* <code>
* // create a new form
* $form = new Zebra_Form('my_form');
*
* // disable client-side validation
* $form->clientside_validation(false);
*
* // enable client-side validation using default properties
* $form->clientside_validation(true);
*
* // enable client-side validation using customized properties
* $form->clientside_validation(array(
* 'close_tips' => false, // don't show a "close" button on tips with error messages
* 'on_ready' => false, // no function to be executed when the form is ready
* 'disable_upload_validation' => true, // using a custom plugin for managing file uploads
* 'scroll_to_error' => false, // don't scroll the browser window to the error message
* 'tips_position' => 'right', // position tips with error messages to the right of the controls
* 'validate_on_the_fly' => false, // don't validate controls on the fly
* 'validate_all' => false, // show error messages one by one upon trying to submit an invalid form
* ));
* </code>
*
* To access the JavaScript object and use the public methods provided by it, use $('#formname').data('Zebra_Form')
* where <i>formname</i> is the form's name <b>with any dashes turned into underscores!</b>
*
* <i>Therefore, if a form's name is "my-form", the JavaScript object would be accessed like $('my_form').data('Zebra_Form').</i>
*
* From JavaScript, these are the methods that can be called on this object:
*
* - <b>attach_tip(element, message)</b> - displays a custom error message, attached to the element with the
* indicated ID (so, remember, "element" is string, not an object!)
* - <b>clear_errors()</b> - hides all error messages;
* - <b>submit()</b> - submits the form;
* - <b>validate()</b> - checks if the form is valid; returns TRUE or FALSE;
*
* Here's how you can use these methods, in JavaScript:
*
* <code>
* // let's submit the form when clicking on a random button
*
* // get a reference to the Zebra_Form object
* var $form = $('#formname').data('Zebra_Form');
*
* // handle the onclick event on a random button
* $('#somebutton').bind('click', function(e) {
*
* // stop default action
* e.preventDefault();
*
* // validate the form, and if the form validates
* if ($form.validate()) {
*
* // do your thing here
*
* // when you're done, submit the form
* $form.submit();
*
* }
*
* // if the form is not valid, everything is handled automatically by the library
*
* });
* </code>
*
* @param mixed $properties Can have the following values:
*
* - FALSE, disabling the client-side validation;
* <i>Note that the {@link Zebra_Form_Control::set_rule() dependencies} rule will
* still be checked client-side so that callback functions get called, if it is
* the case!</i>
* - TRUE, enabling the client-side validation with the default properties;
*
* - an associative array with customized properties for the client-side validation;
*
* In this last case, the available properties are:
*
* - <b>close_tips</b>, boolean, TRUE or FALSE<br>
* Specifies whether the tips with error messages should have a "close" button
* or not<br>
* Default is <b>TRUE</b>.
*
* - <b>disable_upload_validation</b>, boolean, TRUE or FALSE<br>
* Useful for disabling all client-side processing of file upload controls, so
* that custom plugins may be used for it (like, for instance,
* {@link http://blueimp.github.io/jQuery-File-Upload/basic.html this one})
* Default is <b>FALSE</b>.
*
* - <b>on_ready</b>, JavaScript function to be executed when the form is loaded.
* Useful for getting a reference to the Zebra_Form object after everything is
* loaded.
*
* <code>
* $form->clientside_validation(array(
* // where $form is a global variable and 'id' is the form's id
* 'on_ready': 'function() { $form = $("#id").data('Zebra_Form'); }',
* ));
* </code>
*
* - <b>scroll_to_error</b>, boolean, TRUE or FALSE<br>
* Specifies whether the browser window should be scrolled to the error message
* or not.<br>
* Default is <b>TRUE</b>.
*
* - <b>tips_position</b>, string, <i>left</i> or <i>right</i><br>
* Specifies where the error message tip should be positioned relative to the
* control.<br>
* Default is <b>left</b>.
*
* - <b>validate_on_the_fly</b>, boolean, TRUE or FALSE<br>
* Specifies whether values should be validated as soon as the user leaves a
* field; if set to TRUE and the validation of the control fails, the error
* message will be shown right away<br>
* Default is <b>FALSE</b>.
*
* - <b>validate_all</b>, boolean, TRUE or FALSE<br>
* Specifies whether upon submitting the form, should all error messages be
* shown at once if there are any errors<br>
* Default is <b>FALSE</b>.
*
* @return void
*/
function clientside_validation($properties)
{
// default properties of the client-side validation
$defaults = array(
'clientside_disabled' => false,
'close_tips' => true,
'disable_upload_validation' => false,
'on_ready' => false,
'scroll_to_error' => true,
'tips_position' => 'left',
'validate_on_the_fly' => false,
'validate_all' => false,
);
// set the default properties for the client-side validation
if (!isset($this->form_properties['clientside_validation'])) $this->form_properties['clientside_validation'] = $defaults;
// if client-side validation needs to be disabled
if ($properties == false) $this->form_properties['clientside_validation']['clientside_disabled'] = true;
// if custom settings for client-side validation
elseif (is_array($properties))
// merge the new settings with the old ones
$this->form_properties['clientside_validation'] = array_merge($this->form_properties['clientside_validation'], $properties);
}
/**
* By default, this class generates <b>HTML 4.01 Strict</b> markup.
*
* Use this method if you want the generated HTML markup to validate as <b>XHTML 1.0 Strict</b>.
*
* @param string $doctype (Optional) The DOCTYPE of the generated HTML markup.
*
* Possible (case-insensitive) values are <b>HTML</b> or <b>XHTML</b>
*
* Default is HTML.
*
* @return void
*/
function doctype($doctype = 'html')
{
// set the doctype
$this->form_properties['doctype'] = (strtolower($doctype) == 'xhtml' ? 'xhtml' : 'html');
}
/**
* Enables protection against {@link http://en.wikipedia.org/wiki/Cross-site_request_forgery Cross-site request
* forgery} (CSRF) attacks.
*
* Read more about specifics and a simple implementation on
* {@link http://shiflett.org/articles/cross-site-request-forgeries Chris Shiflett's website}.
*
* This method is automatically called by the library, so protection against CSRF attacks is enabled by default for
* all forms and the script will decide automatically on the method to use for storing the CSRF token: if a session
* is already started then the CSRF token will be stored in a session variable or, if a session is not started, the
* CSRF token will be stored in a session cookie (cookies that expire when the browser is closed) but, in this case,
* it offers a lower level of security.
*
* If cookies are used for storage, you'll have to make sure that Zebra_Form is instantiated before any output from
* your script (this is a protocol restriction) including <html> and <head> tags as well as any whitespace!
* A workaround is to turn output buffering on in php.ini.
*
* <i>You are encouraged to start a PHP session before instantiating this class in order to maximize the level of
* security of your forms.</i>
*
* The CSRF token is automatically regenerated when the form is submitted regardless if the form validated or not.
* A notable exception is that the form doesn't validate but was submitted via AJAX the CSRF token will not be
* regenerated - useful if you submit forms by AJAX.
*
* As an added benefit, protection against CSRF attacks prevents "double posts" by design.
*
* <samp>You only need to call this method if you want to change CSRF related settings. If you do call this method
* then you should call it right after instantiating the class and *before* calling the form's {@link validate()}
* and {@link render()} methods!</samp>
*
* <code>
* // recommended usage is:
*
* // call session_start() somewhere in your code but before outputting anything to the browser
* session_start();
*
* // include the Zebra_Form
* require 'path/to/Zebra_Form.php';
*
* // instantiate the class
* // protection against CSRF attack will be automatically enabled
* // but will be less secure if a session is not started (as it will
* // rely on cookies)
* $form = new Zebra_Form('my_form');
* </code>
*
* @param string $csrf_storage_method (Optional) Sets whether the CSRF token should be stored in a cookie, in
* a session variable, or let the script to automatically decide and use
* sessions if available or a cookie otherwise.
*
* Possible values are "auto", "cookie", "session" or boolean FALSE.
*
* If value is "auto", the script will decide automatically on what to use:
* if a session is already started then the CSRF token will be stored in a
* session variable, or, if a session is not started, the CSRF token will be
* stored in a cookie with the parameters as specified by the
* <b>csrf_cookie_config</b> argument (read below).
*
* If value is "cookie" the CSRF token will be stored in a cookie with the
* parameters as specified by the <b>csrf_cookie_config</b> argument (read
* below).
*
* If value is "session" the CSRF token will be stored in a session variable
* and thus a session must be started before instantiating the library.
*
* If value is boolean FALSE (not recommended), protection against CSRF
* attack will be disabled.
*
* The stored value will be compared, upon for submission, with the value
* stored in the associated hidden field, and if the two values do not match
* the form will not validate.
*
* Default is "auto".
*
* @param integer $csrf_token_lifetime (Optional) The number of seconds after which the CSRF token is to be
* considered as expired.
*
* If set to "0" the tokens will expire at the end of the session (when the
* browser closes or session expires).
*
* <i>Note that if csrf_storage_method is set to "session" this value cannot
* be higher than the session's life time as, if idle, the session will time
* out regardless of this value!</i>
*
* Default is 0.
*
* @param array $csrf_cookie_config (Optional) An associative array containing the properties to be used when
* setting the cookie with the CSRF token (if <b>csrf_storage_method</b> is
* set to "cookie").
*
* The properties that can be set are "path", "domain", "secure" and "httponly".
* where:
*
* - <b>path</b> - the path on the server in which the cookie will
* be available on. If set to "/", the cookie will
* be available within the entire domain. If set to
* '/foo/', the cookie will only be available within
* the /foo/ directory and all subdirectories such
* as /foo/bar/ of domain.<br>
* Default is "/"
*
* - <b>domain</b> - The domain that the cookie will be available on.
* To make the cookie available on all subdomains of
* example.com, domain should be set to to
* ".example.com". The . (dot) is not required but
* makes it compatible with more browsers. Setting
* it to "www.example.com" will make the cookie
* available only in the www subdomain.
*
* - <b>secure</b> - Indicates whether cookie information should only
* be transmitted over a HTTPS connection.<br>
* Default is FALSE.
*
* - <b>httponly</b> - When set to TRUE the cookie will be made accessible
* only through the HTTP protocol. This means that
* the cookie won't be accessible by scripting languages,