1: <?php
2: /**
3: * This file contains the QTextBoxBase and QCrossScriptingException class.
4: *
5: * @package Controls
6: */
7:
8: /**
9: * This class will render an HTML Textbox -- which can either be [input type="text"],
10: * [input type="password"] or [textarea] depending on the TextMode (see below).
11: *
12: * @package Controls\Base
13: * @property integer $Columns is the "cols" html attribute (applicable for MultiLine textboxes)
14: * @property string $Format
15: * @property string $Text is the contents of the textbox, itself
16: * @property string|null $Value Returns the value of the text. If the text is empty, will return null.
17: * Subclasses can use this to return a specific type of data.
18: * @property string $LabelForRequired
19: * @property string $LabelForRequiredUnnamed
20: * @property string $LabelForTooShort
21: * @property string $LabelForTooShortUnnamed
22: * @property string $LabelForTooLong
23: * @property string $LabelForTooLongUnnamed
24: * @property string $Placeholder HTML5 Only. Placeholder text that gets erased once a user types.
25: * @property string $CrossScripting can be Allow, HtmlEntities, or Deny. Deny is the default. Prevents cross scripting hacks. HtmlEntities causes framework to automatically call php function htmlentities on the input data. Allow allows everything to come through without altering at all. USE "ALLOW" judiciously: using ALLOW on text entries, and then outputting that data WILL allow hackers to perform cross scripting hacks.
26: * @property integer $MaxLength is the "maxlength" html attribute (applicable for SingleLine textboxes)
27: * @property integer $MinLength is the minimum requred length to pass validation
28: * @property integer $Rows is the "rows" html attribute (applicable for MultiLine textboxes)
29: * @property string $TextMode a QTextMode item. Determines if its a single or multi-line textbox, and the "type" property of the input.
30: * @property boolean $AutoTrim to automatically remove white space from beginning and end of data
31: * @property integer $SanitizeFilter PHP filter constant to apply to incoming data
32: * @property mixed $SanitizeFilterOptions PHP filter constants or array to apply to SanitizeFilter option
33: * @property integer $ValidateFilter PHP filter constant to apply to validate with
34: * @property mixed $ValidateFilterOptions PHP filter constants or array to apply to ValidateFilter option
35: * @property mixed $LabelForInvalid PHP filter constants or array to apply to ValidateFilter option
36: */
37: abstract class QTextBoxBase extends QControl {
38: // APPEARANCE
39: /** @var int */
40: protected $intColumns = 0;
41: /** @var string */
42: protected $strText = null;
43: /** @var string */
44: protected $strLabelForRequired;
45: /** @var string */
46: protected $strLabelForRequiredUnnamed;
47: /** @var string */
48: protected $strLabelForTooShort;
49: /** @var string */
50: protected $strLabelForTooShortUnnamed;
51: /** @var string */
52: protected $strLabelForTooLong;
53: /** @var string */
54: protected $strLabelForTooLongUnnamed;
55: /** @var string */
56: protected $strPlaceholder = '';
57: /** @var string */
58: protected $strFormat = '%s';
59:
60: // BEHAVIOR
61: /** @var int */
62: protected $intMaxLength = 0;
63: /** @var int */
64: protected $intMinLength = 0;
65: /** @var int */
66: protected $intRows = 0;
67: /** @var string Subclasses should not set this directly, but rather use the TextMode accessor */
68: protected $strTextMode = QTextMode::SingleLine;
69: /** @var string */
70: protected $strCrossScripting;
71: /** @var null */
72: protected $objHTMLPurifierConfig = null;
73:
74: // Sanitization and validating
75: /** @var bool */
76: protected $blnAutoTrim = false;
77: /** @var int */
78: protected $intSanitizeFilter = null;
79: /** @var mixed */
80: protected $mixSanitizeFilterOptions = null;
81: /** @var int */
82: protected $intValidateFilter = null;
83: /** @var mixed */
84: protected $mixValidateFilterOptions = null;
85: /** @var string */
86: protected $strLabelForInvalid = null;
87:
88:
89: //////////
90: // Methods
91: //////////
92: /**
93: * Constructor for the QTextBox[Base]
94: *
95: * @param QControl|QForm $objParentObject
96: * @param null|string $strControlId
97: */
98: public function __construct($objParentObject, $strControlId = null) {
99: parent::__construct($objParentObject, $strControlId);
100:
101: $this->strLabelForRequired = QApplication::Translate('%s is required');
102: $this->strLabelForRequiredUnnamed = QApplication::Translate('Required');
103:
104: $this->strLabelForTooShort = QApplication::Translate('%s must have at least %s characters');
105: $this->strLabelForTooShortUnnamed = QApplication::Translate('Must have at least %s characters');
106:
107: $this->strLabelForTooLong = QApplication::Translate('%s must have at most %s characters');
108: $this->strLabelForTooLongUnnamed = QApplication::Translate('Must have at most %s characters');
109:
110: $this->strCrossScripting = QApplication::$DefaultCrossScriptingMode;
111:
112: if ($this->strCrossScripting == QCrossScripting::HTMLPurifier) {
113: $this->InitHtmlPurifier();
114: }
115: }
116:
117: /**
118: * Initializee the HtmlPurifier library.
119: */
120: protected function InitHtmlPurifier() {
121: // If we are purifying using HTMLPurify, we will need the autoloader to be included.
122: // We load lazy to make sure that the library is not loaded every time 'prepend.inc.php'
123: // or 'qcubed.inc.php' is inlcuded. HTMLPurifier is a HUGE and SLOW library. Lazy loading
124: // keeps it simpler.
125: require_once(__DOCROOT__ . __VENDOR_ASSETS__ . '/ezyang/htmlpurifier/library/HTMLPurifier.auto.php');
126:
127: // We configure the default set of forbidden tags (elements) and attributes here
128: // so that the rules are applicable the moment CrossScripting is set to Purify.
129: // Use the QTextBox::SetPurifierConfig method to override these settings.
130: $this->objHTMLPurifierConfig = HTMLPurifier_Config::createDefault();
131: $this->objHTMLPurifierConfig->set('HTML.ForbiddenElements', 'script,applet,embed,style,link,iframe,body,object');
132: $this->objHTMLPurifierConfig->set('HTML.ForbiddenAttributes', '*@onfocus,*@onblur,*@onkeydown,*@onkeyup,*@onkeypress,*@onmousedown,*@onmouseup,*@onmouseover,*@onmouseout,*@onmousemove,*@onclick');
133:
134: if (defined('__PURIFIER_CACHE__')) {
135: if (!is_dir(__PURIFIER_CACHE__)) {
136: mkdir(__PURIFIER_CACHE__);
137: }
138: $this->objHTMLPurifierConfig->set('Cache.SerializerPath', __PURIFIER_CACHE__);
139: } else {
140: # Disable the cache entirely
141: $this->objHTMLPurifierConfig->set('Cache.DefinitionImpl', null);
142: }
143: }
144:
145: /**
146: * This function allows to set the Configuration for HTMLPurifier
147: * similar to the HTMLPurifierConfig::set() method from the HTMLPurifier API.
148: *
149: * @param strParameter : The parameter to set for HTMLPurifier
150: * @param mixValue : Value of the parameter.
151: * NOTE: THERE IS NO SUPPORT FOR THE DEPRECATED API OF HTMLPURIFIER, HENCE NO THIRD ARGUMENT TO THE
152: * FUNCTION CAN BE PASSED.
153: * Visit http://htmlpurifier.org/live/configdoc/plain.html for the list of parameters and their effects.
154: */
155: public function SetPurifierConfig($strParameter, $mixValue) {
156: if ($this->objHTMLPurifierConfig != null) {
157: $this->objHTMLPurifierConfig->set($strParameter, $mixValue);
158: }
159: }
160:
161: /**
162: * Parse the data posted back via the control.
163: * This function basically test for the Crossscripting rules applied to the QTextBox
164: * @throws QCrossScriptingException
165: */
166: public function ParsePostData() {
167: // Check to see if this Control's Value was passed in via the POST data
168: if (array_key_exists($this->strControlId, $_POST)) {
169: // It was -- update this Control's value with the new value passed in via the POST arguments
170: $strText = $_POST[$this->strControlId];
171: $strText = str_replace("\r\n", "\n", $strText); // Convert posted newlines to PHP newlines
172: $this->strText = $strText;
173:
174: $this->Sanitize();
175:
176: switch ($this->strCrossScripting) {
177: case QCrossScripting::Allow:
178: // Do Nothing, allow everything
179: break;
180: case QCrossScripting::HtmlEntities:
181: // Go ahead and perform HtmlEntities on the text
182: $this->strText = QApplication::HtmlEntities($this->strText);
183: break;
184: case QCrossScripting::HTMLPurifier:
185: // let HTMLPurifier do the job! User should have set it up!
186: // require_once(__VENDOR__ . '/ezyang/htmlpurifier/library/HTMLPurifier.auto.php');
187: $objPurifier = new HTMLPurifier($this->objHTMLPurifierConfig);
188:
189: // HTML Purifier does an html_encode, which is not what we usually want.
190: $this->strText = html_entity_decode($objPurifier->purify($this->strText)); // don't save data as html entities! Encode at display time.
191: break;
192: // The use of the modes below is not recommended; they're there only for legacy
193: // purposes. If you need to check for cross-site scripting violations, use QCrossScripting::Purify
194: case QCrossScripting::Legacy:
195: case QCrossScripting::Deny:
196: default:
197: // Deny the Use of CrossScripts
198: // Check for cross scripting patterns
199: $strText = mb_strtolower($this->strText, QApplication::$EncodingType);
200: if ((mb_strpos($strText, '<script', 0, QApplication::$EncodingType) !== false) ||
201: (mb_strpos($strText, '<applet', 0, QApplication::$EncodingType) !== false) ||
202: (mb_strpos($strText, '<embed', 0, QApplication::$EncodingType) !== false) ||
203: (mb_strpos($strText, '<style', 0, QApplication::$EncodingType) !== false) ||
204: (mb_strpos($strText, '<link', 0, QApplication::$EncodingType) !== false) ||
205: (mb_strpos($strText, '<body', 0, QApplication::$EncodingType) !== false) ||
206: (mb_strpos($strText, '<iframe', 0, QApplication::$EncodingType) !== false) ||
207: (mb_strpos($strText, 'javascript:', 0, QApplication::$EncodingType) !== false) ||
208: (mb_strpos($strText, ' onfocus=', 0, QApplication::$EncodingType) !== false) ||
209: (mb_strpos($strText, ' onblur=', 0, QApplication::$EncodingType) !== false) ||
210: (mb_strpos($strText, ' onkeydown=', 0, QApplication::$EncodingType) !== false) ||
211: (mb_strpos($strText, ' onkeyup=', 0, QApplication::$EncodingType) !== false) ||
212: (mb_strpos($strText, ' onkeypress=', 0, QApplication::$EncodingType) !== false) ||
213: (mb_strpos($strText, ' onmousedown=', 0, QApplication::$EncodingType) !== false) ||
214: (mb_strpos($strText, ' onmouseup=', 0, QApplication::$EncodingType) !== false) ||
215: (mb_strpos($strText, ' onmouseover=', 0, QApplication::$EncodingType) !== false) ||
216: (mb_strpos($strText, ' onmouseout=', 0, QApplication::$EncodingType) !== false) ||
217: (mb_strpos($strText, ' onmousemove=', 0, QApplication::$EncodingType) !== false) ||
218: (mb_strpos($strText, ' onclick=', 0, QApplication::$EncodingType) !== false) ||
219: (mb_strpos($strText, '<object', 0, QApplication::$EncodingType) !== false) ||
220: (mb_strpos($strText, 'background:url', 0, QApplication::$EncodingType) !== false))
221: throw new QCrossScriptingException($this->strControlId);
222: }
223: }
224: }
225:
226: /**
227: * Sanitizes the current value.
228: */
229: protected function Sanitize() {
230: if ($this->blnAutoTrim) {
231: $this->strText = trim ($this->strText);
232: }
233:
234: if ($this->intSanitizeFilter) {
235: $this->strText = filter_var ($this->strText, $this->intSanitizeFilter, $this->mixSanitizeFilterOptions);
236: }
237: }
238:
239: /**
240: * Returns the HTML formatted string for the control
241: * @return string HTML string
242: */
243: protected function GetControlHtml() {
244: $attrOverride = array('name'=>$this->strControlId);
245:
246: switch ($this->strTextMode) {
247: case QTextMode::MultiLine:
248: $strText = QApplication::HtmlEntities($this->strText);
249:
250: return $this->RenderTag('textarea',
251: $attrOverride,
252: null,
253: $strText);
254:
255: default:
256: $attrOverride['value'] = $this->strText;
257: return $this->RenderTag('input',
258: $attrOverride,
259: null,
260: null,
261: true
262: );
263:
264: }
265: }
266:
267:
268: /**
269: * Render HTML attributes for the purpose of drawing the tag. Text objects have a number of parameters specific
270: * to them, some of which we use for validation, and some of which are dual purpose.
271: * We render those here, rather than setting the attributes when those are set.
272: *
273: * @param null $attributeOverrides
274: * @param null $styleOverrides
275: *
276: * @return string|void
277: */
278: public function RenderHtmlAttributes ($attributeOverrides = null, $styleOverrides = null) {
279: if ($this->intMaxLength) {
280: $attributeOverrides['maxlength'] = $this->intMaxLength;
281: }
282: if ($this->strTextMode == QTextMode::MultiLine) {
283: if ($this->intColumns) {
284: $attributeOverrides['cols'] = $this->intColumns;
285: }
286: if ($this->intRows) {
287: $attributeOverrides['rows'] = $this->intRows;
288: }
289: //if (!$this->blnWrap) {
290: /**
291: * $strToReturn .= 'wrap="off" '; Note that this is not standard HTML5 and not supported by all browsers
292: * In fact, HTML5 has completely changed its meaning to mean whether the text itself has embedded
293: * hard returns inserted when the textarea wraps. Deprecating. We will have to wait for another solution.
294: */
295: //}
296: } else {
297: if ($this->intColumns) {
298: $attributeOverrides['size'] = $this->intColumns;
299: }
300: $typeStr = $this->strTextMode ? $this->strTextMode : 'text';
301: $attributeOverrides['type'] = $typeStr;
302: }
303:
304: if(strlen($this->strPlaceholder) > 0) {
305: $attributeOverrides['placeholder'] = $this->strPlaceholder;
306: }
307:
308: return parent::RenderHtmlAttributes($attributeOverrides, $styleOverrides);
309: }
310:
311:
312: /**
313: * Tests that the value given inside the textbox passes the rules set for the input
314: * Tests it does:
315: * (1) Checks if the textbox was empty while 'Required' property was set to true
316: * (2) Checks for length contrainsts set by 'MaxLength' and 'MinLength' properties
317: *
318: * @return bool whether or not the control is valid
319: */
320: public function Validate() {
321: // Copy text
322: $strText = $this->strText;
323: // Check for Required
324: if ($this->blnRequired) {
325: if (mb_strlen($strText, QApplication::$EncodingType) == 0) {
326: if ($this->strName)
327: $this->ValidationError = sprintf($this->strLabelForRequired, $this->strName);
328: else
329: $this->ValidationError = $this->strLabelForRequiredUnnamed;
330: return false;
331: }
332: }
333:
334: // Check against minimum length?
335: if ($this->intMinLength > 0) {
336: if (mb_strlen($strText, QApplication::$EncodingType) < $this->intMinLength) {
337: if ($this->strName)
338: $this->ValidationError = sprintf($this->strLabelForTooShort, $this->strName, $this->intMinLength);
339: else
340: $this->ValidationError = sprintf($this->strLabelForTooShortUnnamed, $this->intMinLength);
341: return false;
342: }
343: }
344:
345: // Check against maximum length?
346: if ($this->intMaxLength > 0) {
347: if (mb_strlen($strText, QApplication::$EncodingType) > $this->intMaxLength) {
348: if ($this->strName)
349: $this->ValidationError = sprintf($this->strLabelForTooLong, $this->strName, $this->intMaxLength);
350: else
351: $this->ValidationError = sprintf($this->strLabelForTooLongUnnamed, $this->intMaxLength);
352: return false;
353: }
354: }
355:
356: // Check against PHP validation
357: if ($this->intValidateFilter && $this->strText) {
358: if (!filter_var($this->strText, $this->intValidateFilter, $this->mixValidateFilterOptions)) {
359: $this->ValidationError = $this->strLabelForInvalid;
360: return false;
361: }
362: }
363:
364: // If we're here, then everything is a-ok. Return true.
365: return true;
366: }
367:
368: /**
369: * This will focus on and do a "select all" on the contents of the textbox
370: */
371: public function Select() {
372: QApplication::ExecuteJavaScript(sprintf('qc.getW("%s").select();', $this->strControlId));
373: }
374:
375: /**
376: * Returns the current state of the control to be able to restore it later.
377: * @return mixed
378: */
379: protected function GetState(){
380: return array('text'=>$this->Text);
381: }
382:
383: /**
384: * Restore the state of the control.
385: * @param mixed $state Previously saved state as returned by GetState above.
386: */
387: protected function PutState($state) {
388: if (isset($state['text'])) {
389: $this->Text = $state['text'];
390: }
391: }
392:
393: /////////////////////////
394: // Public Properties: GET
395: /////////////////////////
396: /**
397: * PHP __get magic method implementation
398: * @param string $strName Name of the property
399: *
400: * @return array|bool|int|mixed|null|QControl|QForm|string
401: * @throws Exception|QCallerException
402: */
403: public function __get($strName) {
404: switch ($strName) {
405: // APPEARANCE
406: case "Columns": return $this->intColumns;
407: case "Format": return $this->strFormat;
408: case "Text": return $this->strText;
409: case "LabelForRequired": return $this->strLabelForRequired;
410: case "LabelForRequiredUnnamed": return $this->strLabelForRequiredUnnamed;
411: case "LabelForTooShort": return $this->strLabelForTooShort;
412: case "LabelForTooShortUnnamed": return $this->strLabelForTooShortUnnamed;
413: case "LabelForTooLong": return $this->strLabelForTooLong;
414: case "LabelForTooLongUnnamed": return $this->strLabelForTooLongUnnamed;
415: case "Placeholder": return $this->strPlaceholder;
416: case 'Value': return empty($this->strText) ? null : $this->strText;
417:
418:
419: // BEHAVIOR
420: case "CrossScripting": return $this->strCrossScripting;
421: case "MaxLength": return $this->intMaxLength;
422: case "MinLength": return $this->intMinLength;
423: case "Rows": return $this->intRows;
424: case "TextMode": return $this->strTextMode;
425:
426: // LAYOUT
427: //case "Wrap": return $this->blnWrap;
428:
429: // FILTERING and VALIDATION
430: case "AutoTrim": return $this->blnAutoTrim;
431: case "SanitizeFilter": return $this->intSanitizeFilter;
432: case "SanitizeFilterOptions": return $this->mixSanitizeFilterOptions;
433: case "ValidateFilter": return $this->intValidateFilter;
434: case "ValidateFilterOptions": return $this->mixValidateFilterOptions;
435: case "LabelForInvalid": return $this->strLabelForInvalid;
436:
437: default:
438: try {
439: return parent::__get($strName);
440: } catch (QCallerException $objExc) {
441: $objExc->IncrementOffset();
442: throw $objExc;
443: }
444: }
445: }
446:
447: /////////////////////////
448: // Public Properties: SET
449: /////////////////////////
450: /**
451: * PHP __set magic method implementation
452: *
453: * @param string $strName Name of the property
454: * @param string $mixValue Value of the property
455: *
456: * @return mixed
457: * @throws Exception|QCallerException|QInvalidCastException
458: */
459: public function __set($strName, $mixValue) {
460: // Setters that do not cause a complete redraw
461: switch ($strName) {
462: case "Text":
463: case "Value":
464: try {
465: $val = QType::Cast($mixValue, QType::String);
466: if ($val !== $this->strText) {
467: $this->strText = $val;
468: $this->AddAttributeScript('val', $val);
469: }
470: return $this->strText;
471: } catch (QInvalidCastException $objExc) {
472: $objExc->IncrementOffset();
473: throw $objExc;
474: }
475:
476: // APPEARANCE
477: case "Columns":
478: try {
479: if ($this->intColumns !== ($mixValue = QType::Cast($mixValue, QType::Integer))) {
480: $this->blnModified = true;
481: $this->intColumns = $mixValue;
482: }
483: break;
484: } catch (QInvalidCastException $objExc) {
485: $objExc->IncrementOffset();
486: throw $objExc;
487: }
488: case "Format":
489: try {
490: if ($this->strFormat !== ($mixValue = QType::Cast($mixValue, QType::String))) {
491: $this->blnModified = true;
492: $this->strFormat = $mixValue;
493: }
494: break;
495: } catch (QInvalidCastException $objExc) {
496: $objExc->IncrementOffset();
497: throw $objExc;
498: }
499: case "LabelForRequired":
500: try {
501: // no redraw needed
502: $this->strLabelForRequired = QType::Cast($mixValue, QType::String);
503: break;
504: } catch (QInvalidCastException $objExc) {
505: $objExc->IncrementOffset();
506: throw $objExc;
507: }
508: case "LabelForRequiredUnnamed":
509: try {
510: $this->strLabelForRequiredUnnamed = QType::Cast($mixValue, QType::String);
511: break;
512: } catch (QInvalidCastException $objExc) {
513: $objExc->IncrementOffset();
514: throw $objExc;
515: }
516: case "LabelForTooShort":
517: try {
518: $this->strLabelForTooShort = QType::Cast($mixValue, QType::String);
519: break;
520: } catch (QInvalidCastException $objExc) {
521: $objExc->IncrementOffset();
522: throw $objExc;
523: }
524: case "LabelForTooShortUnnamed":
525: try {
526: $this->strLabelForTooShortUnnamed = QType::Cast($mixValue, QType::String);
527: break;
528: } catch (QInvalidCastException $objExc) {
529: $objExc->IncrementOffset();
530: throw $objExc;
531: }
532: case "LabelForTooLong":
533: try {
534: $this->strLabelForTooLong = QType::Cast($mixValue, QType::String);
535: break;
536: } catch (QInvalidCastException $objExc) {
537: $objExc->IncrementOffset();
538: throw $objExc;
539: }
540: case "LabelForTooLongUnnamed":
541: try {
542: $this->strLabelForTooLongUnnamed = QType::Cast($mixValue, QType::String);
543: break;
544: } catch (QInvalidCastException $objExc) {
545: $objExc->IncrementOffset();
546: throw $objExc;
547: }
548: case "Placeholder":
549: try {
550: if ($this->strPlaceholder !== ($mixValue = QType::Cast($mixValue, QType::String))) {
551: $this->blnModified = true;
552: $this->strPlaceholder = $mixValue;
553: }
554: break;
555: } catch (QInvalidCastException $objExc) {
556: $objExc->IncrementOffset();
557: throw $objExc;
558: }
559:
560: // BEHAVIOR
561: case "CrossScripting":
562: try {
563: $this->strCrossScripting = QType::Cast($mixValue, QType::String);
564: // Protect from XSS to the best we can do with HTMLPurifier.
565: if ($this->strCrossScripting == QCrossScripting::HTMLPurifier) {
566: $this->InitHtmlPurifier();
567: }
568: break;
569: } catch (QInvalidCastException $objExc) {
570: $objExc->IncrementOffset();
571: throw $objExc;
572: }
573: case "MaxLength":
574: try {
575: if ($this->intMaxLength !== ($mixValue = QType::Cast($mixValue, QType::Integer))) {
576: $this->blnModified = true;
577: $this->intMaxLength = $mixValue;
578: }
579: break;
580: } catch (QInvalidCastException $objExc) {
581: $objExc->IncrementOffset();
582: throw $objExc;
583: }
584: case "MinLength":
585: try {
586: if ($this->intMinLength !== ($mixValue = QType::Cast($mixValue, QType::Integer))) {
587: $this->blnModified = true;
588: $this->intMinLength = $mixValue;
589: }
590: break;
591: } catch (QInvalidCastException $objExc) {
592: $objExc->IncrementOffset();
593: throw $objExc;
594: }
595: case "Rows":
596: try {
597: if ($this->intRows !== ($mixValue = QType::Cast($mixValue, QType::Integer))) {
598: $this->blnModified = true;
599: $this->intRows = $mixValue;
600: }
601: break;
602: } catch (QInvalidCastException $objExc) {
603: $objExc->IncrementOffset();
604: throw $objExc;
605: }
606: case "TextMode":
607: try {
608: if ($this->strTextMode !== ($strMode = QType::Cast($mixValue, QType::String))) {
609: $this->blnModified = true;
610: $this->strTextMode = $strMode;
611: }
612: break;
613: } catch (QInvalidCastException $objExc) {
614: $objExc->IncrementOffset();
615: throw $objExc;
616: }
617:
618: // LAYOUT
619: //case "Wrap":
620: // Deprecated. HTML5 has changed the meaning of this, and wrap=off is not consistenly implemented
621: // across browers.
622: break;
623:
624: // FILTERING and VALIDATING, no redraw needed
625: case "AutoTrim":
626: try {
627: $this->blnAutoTrim = QType::Cast($mixValue, QType::Boolean);
628: break;
629: } catch (QInvalidCastException $objExc) {
630: $objExc->IncrementOffset();
631: throw $objExc;
632: }
633:
634: case "SanitizeFilter":
635: try {
636: $this->intSanitizeFilter = QType::Cast($mixValue, QType::Integer);
637: break;
638: } catch (QInvalidCastException $objExc) {
639: $objExc->IncrementOffset();
640: throw $objExc;
641: }
642:
643: case "SanitizeFilterOptions":
644: try {
645: $this->mixSanitizeFilterOptions = $mixValue; // can be integer or array. See PHP doc.
646: break;
647: } catch (QInvalidCastException $objExc) {
648: $objExc->IncrementOffset();
649: throw $objExc;
650: }
651:
652: case "ValidateFilter":
653: try {
654: $this->intValidateFilter = QType::Cast($mixValue, QType::Integer);
655: break;
656: } catch (QInvalidCastException $objExc) {
657: $objExc->IncrementOffset();
658: throw $objExc;
659: }
660:
661: case "ValidateFilterOptions":
662: try {
663: $this->mixValidateFilterOptions = $mixValue; // can be integer or array. See PHP doc.
664: break;
665: } catch (QInvalidCastException $objExc) {
666: $objExc->IncrementOffset();
667: throw $objExc;
668: }
669:
670: case "LabelForInvalid":
671: try {
672: $this->strLabelForInvalid = QType::Cast($mixValue, QType::String);
673: break;
674: } catch (QInvalidCastException $objExc) {
675: $objExc->IncrementOffset();
676: throw $objExc;
677: }
678:
679: default:
680: try {
681: parent::__set($strName, $mixValue);
682: } catch (QCallerException $objExc) {
683: $objExc->IncrementOffset();
684: throw $objExc;
685: }
686: break;
687: }
688: }
689:
690: /**
691: * Returns an description of the options available to modify by the designer for the code generator.
692: *
693: * @return QModelConnectorParam[]
694: */
695: public static function GetModelConnectorParams() {
696: return array_merge(parent::GetModelConnectorParams(), array(
697: new QModelConnectorParam (get_called_class(), 'Columns', 'Width of field', QType::Integer),
698: new QModelConnectorParam (get_called_class(), 'Rows', 'Height of field for multirow field', QType::Integer),
699: new QModelConnectorParam (get_called_class(), 'Format', 'printf format string to use', QType::String),
700: new QModelConnectorParam (get_called_class(), 'Placeholder', 'HTML5 Placeholder attribute', QType::String),
701: new QModelConnectorParam (get_called_class(), 'ReadOnly', 'Editable or not', QType::Boolean),
702: new QModelConnectorParam (get_called_class(), 'TextMode', 'Field type', QModelConnectorParam::SelectionList,
703: array (null=>'-',
704: 'QTextMode::Search'=>'Search',
705: 'QTextMode::MultiLine'=>'MultiLine',
706: 'QTextMode::Password'=>'Password',
707: 'QTextMode::SingleLine'=>'SingleLine'
708: ))
709: ));
710: }
711: }
712:
713: /**
714: * Class QCrossScriptingException: Called when the textbox fails CrossScripting checks
715: */
716: class QCrossScriptingException extends QCallerException {
717: /**
718: * Constructor
719: * @param string $strControlId Control ID of the control for which it being called
720: */
721: public function __construct($strControlId) {
722: parent::__construct("Cross Scripting Violation: Potential cross script injection in Control \"" .
723: $strControlId . "\"\r\nTo allow any input on this TextBox control, set CrossScripting to QCrossScripting::Allow. Also consider QCrossScripting::HTMLPurifier.", 2);
724: }
725: }