Skip to content
Browse files

added CJavaScriptExpression while keeping BC

  • Loading branch information...
1 parent c1ac363 commit ada1cedc7dd5946cc660ce9722a9881d7eb31040 @samdark samdark committed Jul 27, 2012
View
2 CHANGELOG
@@ -60,7 +60,7 @@ Version 1.1.11 work in progress
- Enh #369: Added $hashKey to CCache (kidol)
- Enh #414: Added sort parameter to yiic message command that sorts messages by key when merging (ranvis)
- Enh #455: Added support for default value in CConsoleCommand::prompt (eagleoneraptor)
-- Enh #551: Added $safe parameter to CJavaScript::encode. If set to true, 'js:' will not be allowed (samdark)
+- Enh #551: Added $safe parameter to CJavaScript::encode. If set to true, 'js:' will not be allowed. If you need to pass JavaScript, wrap your code with CJavaScriptExpression instead (samdark)
- Enh #552: Added support for http-level caching via CHttpCacheFilter (DaSourcerer)
- Enh #568: CHtml::getIdByName() will now convert spaces to underscore to get proper ID for HTML elements (mdomba)
- Enh #578: Added extension checks to CMemCache (samdark)
View
25 UPGRADE
@@ -24,24 +24,37 @@ Upgrading from v1.1.10
- API of public method CConsoleCommand::confirm() changed. If you are overriding this method make sure to update your code.
The method now has a 2nd parameter for the default value which will be used if no selection is made, so you have to
adjust the signature to fit
-
+
public function confirm($message,$default=false)
-
+
and the parent call to
-
+
parent::confirm($message,$default);
- API of protected method CConsoleCommand::afterAction() changed, if you are overriding this method make sure to update your code.
method now has a 3rd parameter for application exit code, so you have to adjust the signature to fit
-
+
protected function afterAction($action,$params,$exitCode=0)
-
+
and the parent call to
-
+
parent::afterAction($action,$params,$exitCode);
- CDateFormat::format() now will return null if the parameter $time is null. Previously it would return 1/1/1970.
+- If you are using CJavaScript::encode in your application with parameter coming
+ from user input, set second argument to true:
+
+ CJavaScript::encode($userInput, true);
+
+ It will disable prefixing parameters with "js:". If you need to pass JavaScript
+ expression it's now preferrable to wrap these with CJavaScriptExpression:
+
+ CJavaScript::encode(new CJavaScriptExpression('alert("Yii!");'), true);
+
+ Note that second "safe" parameter doesn't affect CJavaScriptExpression in any way.
+
+
Upgrading from v1.1.9
---------------------
- Previously xSendFile() was returning false if the file was not found.
View
4 framework/gii/generators/model/views/index.php
@@ -68,10 +68,10 @@
'source'=>array_keys(Yii::app()->{$model->connectionId}->schema->getTables()),
'options'=>array(
'minLength'=>'0',
- 'focus' => 'js:function(event,ui) {
+ 'focus' => new CJavaScriptExpression('function(event,ui) {
$("#'.CHtml::activeId($model,'tableName').'").val(ui.item.label);
return false;
- }'
+ }')
),
'htmlOptions'=>array(
'id'=>'ModelCode_tableName',
View
12 framework/web/helpers/CHtml.php
@@ -1038,28 +1038,28 @@ public static function ajax($options)
{
Yii::app()->getClientScript()->registerCoreScript('jquery');
if(!isset($options['url']))
- $options['url']='js:location.href';
+ $options['url']=new CJavaScriptExpression('location.href');
else
$options['url']=self::normalizeUrl($options['url']);
if(!isset($options['cache']))
$options['cache']=false;
if(!isset($options['data']) && isset($options['type']))
- $options['data']='js:jQuery(this).parents("form").serialize()';
+ $options['data']=new CJavaScriptExpression('jQuery(this).parents("form").serialize()');
foreach(array('beforeSend','complete','error','success') as $name)
{
- if(isset($options[$name]) && strpos($options[$name],'js:')!==0)
- $options[$name]='js:'.$options[$name];
+ if(isset($options[$name]) && (!($options[$name] instanceof CJavaScriptExpression) || strpos($options[$name],'js:')!==0))
+ $options[$name]=new CJavaScriptExpression($options[$name]);
}
if(isset($options['update']))
{
if(!isset($options['success']))
- $options['success']='js:function(html){jQuery("'.$options['update'].'").html(html)}';
+ $options['success']=new CJavaScriptExpression('function(html){jQuery("'.$options['update'].'").html(html)}');
unset($options['update']);
}
if(isset($options['replace']))
{
if(!isset($options['success']))
- $options['success']='js:function(html){jQuery("'.$options['replace'].'").replaceWith(html)}';
+ $options['success']=new CJavaScriptExpression('function(html){jQuery("'.$options['replace'].'").replaceWith(html)}');
unset($options['replace']);
}
return 'jQuery.ajax('.CJavaScript::encode($options).');';
View
5 framework/web/helpers/CJavaScript.php
@@ -51,7 +51,8 @@ public static function quote($js,$forUrl=false)
* If you are encoding user input, make sure $safe is set to true.
*
* @param mixed $value PHP variable to be encoded
- * @param boolean $safe If true, 'js:' will not be allowed.
+ * @param boolean $safe If true, 'js:' will not be allowed while
+ * {@link CJavaScriptExpression} will allow you to pass JavaScript expressions.
* Default is false. This parameter is available since 1.1.11.
* @return string the encoded string
*/
@@ -79,6 +80,8 @@ public static function encode($value,$safe=false)
else
return rtrim(sprintf('%.16F',$value),'0'); // locale-independent representation
}
+ else if($value instanceof CJavaScriptExpression)
+ return (string)$value;
else if(is_object($value))
return self::encode(get_object_vars($value));
else if(is_array($value))
View
40 framework/web/helpers/CJavaScriptExpression.php
@@ -0,0 +1,40 @@
+<?php
+/**
+ * CJavaScriptExpression class file.
+ *
+ * @author Alexander Makarov <sam@rmcreative.ru>
+ * @link http://www.yiiframework.com/
+ * @copyright Copyright &copy; 2012 Yii Software LLC
+ * @license http://www.yiiframework.com/license/
+ */
+
+/**
+ * CJavaScriptExpression represents a JavaScript expression that does not need escaping.
+ * It can be passed to {@link CJavaScript::encode()} and the code will stay as is
+ * no matter if $safe set to true or not.
+ *
+ * @author Alexander Makarov <sam@rmcreative.ru>
+ * @package system.web.helpers
+ * @since 1.1.11
+ */
+class CJavaScriptExpression
+{
+ public $code;
+
+ /**
+ * @param $code
+ */
+ public function __construct($code)
+ {
+ $this->code=$code;
+ }
+
+ /**
+ * String magic method
+ * @return string the DB expression
+ */
+ public function __toString()
+ {
+ return $this->code;
+ }
+}
View
18 framework/web/widgets/CActiveForm.php
@@ -215,7 +215,7 @@ class CActiveForm extends CWidget
* the jquery representation of the form object. If the return value of this function is NOT true, the validation
* will be cancelled.
*
- * Note that because this option refers to a js function, you should prefix the value with 'js:' to prevent it
+ * Note that because this option refers to a js function, you should wrap the value with {@link CJavaScriptExpressoin} to prevent it
* from being encoded as a string. This option has been available since version 1.1.3.</li>
* <li>afterValidate: function, the function that will be invoked after performing ajax-based validation
* triggered by form submission action (available only when validateOnSubmit is set true).
@@ -224,15 +224,15 @@ class CActiveForm extends CWidget
* is a boolean value indicating whether there is any validation error. If the return value of this function is NOT true,
* the normal form submission will be cancelled.
*
- * Note that because this option refers to a js function, you should prefix the value with 'js:' to prevent it
+ * Note that because this option refers to a js function, you should wrap the value with {@link CJavaScriptExpressoin} to prevent it
* from being encoded as a string. This option has been available since version 1.1.3.</li>
* <li>beforeValidateAttribute: function, the function that will be invoked before performing ajax-based validation
* triggered by a single attribute input change. The expected function signature should be
* <code>beforeValidateAttribute(form, attribute) {...}</code>, where 'form' is the jquery representation of the form object
* and 'attribute' refers to the js options for the triggering attribute (see {@link error}).
* If the return value of this function is NOT true, the validation will be cancelled.
*
- * Note that because this option refers to a js function, you should prefix the value with 'js:' to prevent it
+ * Note that because this option refers to a js function, you should wrap the value with {@link CJavaScriptExpressoin} to prevent it
* from being encoded as a string. This option has been available since version 1.1.3.</li>
* <li>afterValidateAttribute: function, the function that will be invoked after performing ajax-based validation
* triggered by a single attribute input change. The expected function signature should be
@@ -241,7 +241,7 @@ class CActiveForm extends CWidget
* 'data' is the JSON response from the server-side validation; 'hasError' is a boolean value indicating whether
* there is any validation error.
*
- * Note that because this option refers to a js function, you should prefix the value with 'js:' to prevent it
+ * Note that because this option refers to a js function, you should wrap the value with {@link CJavaScriptExpressoin} to prevent it
* from being encoded as a string. This option has been available since version 1.1.3.</li>
* </ul>
*
@@ -479,7 +479,7 @@ public function error($model,$attribute,$htmlOptions=array(),$enableAjaxValidati
}
}
if($validators!==array())
- $option['clientValidation']="js:function(value, messages, attribute) {\n".implode("\n",$validators)."\n}";
+ $option['clientValidation']=new CJavaScriptExpression("function(value, messages, attribute) {\n".implode("\n",$validators)."\n}");
}
$html=CHtml::error($model,$attribute,$htmlOptions);
@@ -559,7 +559,7 @@ public function labelEx($model,$attribute,$htmlOptions=array())
{
return CHtml::activeLabelEx($model,$attribute,$htmlOptions);
}
-
+
/**
* Renders a url field for a model attribute.
* This method is a wrapper of {@link CHtml::activeUrlField}.
@@ -575,7 +575,7 @@ public function urlField($model,$attribute,$htmlOptions=array())
{
return CHtml::activeUrlField($model,$attribute,$htmlOptions);
}
-
+
/**
* Renders an email field for a model attribute.
* This method is a wrapper of {@link CHtml::activeEmailField}.
@@ -591,7 +591,7 @@ public function emailField($model,$attribute,$htmlOptions=array())
{
return CHtml::activeEmailField($model,$attribute,$htmlOptions);
}
-
+
/**
* Renders an number field for a model attribute.
* This method is a wrapper of {@link CHtml::activeNumberField}.
@@ -607,7 +607,7 @@ public function numberField($model,$attribute,$htmlOptions=array())
{
return CHtml::activeNumberField($model,$attribute,$htmlOptions);
}
-
+
/**
* Renders an number field for a model attribute.
* This method is a wrapper of {@link CHtml::activeRangeField}.
View
6 framework/web/widgets/CAutoComplete.php
@@ -183,7 +183,7 @@ class CAutoComplete extends CInputWidget
* @var array additional options that can be passed to the constructor of the autocomplete js object.
* This allows you to override existing functions of the autocomplete js class (e.g. the parse() function)
*
- * If you want to provide JavaScript native code, you have to prefix the string with js: otherwise it will
+ * If you want to provide JavaScript native code, you have to wrap the string with {@link CJavaScriptExpression} otherwise it will
* be enclosed by quotes.
*/
public $options=array();
@@ -282,8 +282,8 @@ protected function getClientOptions()
}
foreach($functions as $func)
{
- if(is_string($this->$func) && strncmp($this->$func,'js:',3))
- $options[$func]='js:'.$this->$func;
+ if(!($func instanceof CJavaScriptExpression) && is_string($this->$func) && strncmp($this->$func,'js:',3))
+ $options[$func]=new CJavaScriptExpression($this->$func);
}
return $options;
View
4 framework/web/widgets/CMaskedTextField.php
@@ -103,8 +103,8 @@ protected function getClientOptions()
$options['placeholder']=$this->placeholder;
if(is_string($this->completed))
{
- if(strncmp($this->completed,'js:',3))
- $options['completed']='js:'.$this->completed;
+ if(!($this->completed instanceof CJavaScriptExpression) && strncmp($this->completed,'js:',3))
+ $options['completed']=new CJavaScriptExpression($this->completed);
else
$options['completed']=$this->completed;
}
View
4 framework/web/widgets/CMultiFileUpload.php
@@ -119,8 +119,8 @@ protected function getClientOptions()
$options=$this->options;
foreach(array('onFileRemove','afterFileRemove','onFileAppend','afterFileAppend','onFileSelect','afterFileSelect') as $event)
{
- if(isset($options[$event]) && strpos($options[$event],'js:')!==0)
- $options[$event]='js:'.$options[$event];
+ if(isset($options[$event]) && !($options[$event] instanceof CJavaScriptExpression) && strpos($options[$event],'js:')!==0)
+ $options[$event]=new CJavaScriptExpression($options[$event]);
}
if($this->accept!==null)
View
12 framework/web/widgets/CStarRating.php
@@ -193,22 +193,22 @@ protected function getClientOptions()
$options['readOnly']=true;
if($this->focus!==null)
{
- if(strncmp($this->focus,'js:',3))
- $options['focus']='js:'.$this->focus;
+ if(!($this->focus instanceof CJavaScriptExpression) && strncmp($this->focus,'js:',3))
+ $options['focus']=new CJavaScriptExpression($this->focus);
else
$options['focus']=$this->focus;
}
if($this->blur!==null)
{
- if(strncmp($this->blur,'js:',3))
- $options['blur']='js:'.$this->blur;
+ if(!($this->blur instanceof CJavaScriptExpression) && strncmp($this->blur,'js:',3))
+ $options['blur']=new CJavaScriptExpression($this->blur);
else
$options['blur']=$this->blur;
}
if($this->callback!==null)
{
- if(strncmp($this->callback,'js:',3))
- $options['callback']='js:'.$this->callback;
+ if(!($this->callback instanceof CJavaScriptExpression) && strncmp($this->callback,'js:',3))
+ $options['callback']=new CJavaScriptExpression($this->callback);
else
$options['callback']=$this->callback;
}
View
29 framework/zii/widgets/CListView.php
@@ -161,11 +161,11 @@ class CListView extends CBaseListView
* @since 1.1.4
*/
public $itemsTagName='div';
-
+
/**
* @var boolean whether to leverage the {@link https://developer.mozilla.org/en/DOM/window.history DOM history object}. Set this property to true
- * to persist state of list across page revisits. Note, there are two limitations for this feature:
- * - this feature is only compatible with browsers that support HTML5.
+ * to persist state of list across page revisits. Note, there are two limitations for this feature:
+ * - this feature is only compatible with browsers that support HTML5.
* - expect unexpected functionality (e.g. multiple ajax calls) if there is more than one grid/list on a single page with enableHistory turned on.
* @since 1.1.11
*/
@@ -219,9 +219,28 @@ public function registerClientScript()
if($this->updateSelector!==null)
$options['updateSelector']=$this->updateSelector;
if($this->beforeAjaxUpdate!==null)
- $options['beforeAjaxUpdate']=(strpos($this->beforeAjaxUpdate,'js:')!==0 ? 'js:' : '').$this->beforeAjaxUpdate;
+ {
+
+ if(!($this->beforeAjaxUpdate instanceof CJavaScriptExpression) && strpos($this->beforeAjaxUpdate,'js:')!==0)
+ {
+ $options['beforeAjaxUpdate']=new CJavaScriptExpression($this->beforeAjaxUpdate);
+ }
+ else
+ {
+ $options['beforeAjaxUpdate']=$this->beforeAjaxUpdate;
+ }
+ }
if($this->afterAjaxUpdate!==null)
- $options['afterAjaxUpdate']=(strpos($this->afterAjaxUpdate,'js:')!==0 ? 'js:' : '').$this->afterAjaxUpdate;
+ {
+ if(!($this->afterAjaxUpdate instanceof CJavaScriptExpression) && strpos($this->afterAjaxUpdate,'js:')!==0)
+ {
+ $options['beforeAjaxUpdate']=new CJavaScriptExpression($this->afterAjaxUpdate);
+ }
+ else
+ {
+ $options['beforeAjaxUpdate']=$this->afterAjaxUpdate;
+ }
+ }
$options=CJavaScript::encode($options);
$cs=Yii::app()->getClientScript();
View
4 framework/zii/widgets/grid/CButtonColumn.php
@@ -175,8 +175,8 @@ public function init()
{
if(!isset($button['options']['class']))
$this->buttons[$id]['options']['class']=$id;
- if(strpos($button['click'],'js:')!==0)
- $this->buttons[$id]['click']='js:'.$button['click'];
+ if(!($button['click'] instanceof CJavaScriptExpression) && strpos($button['click'],'js:')!==0)
+ $this->buttons[$id]['click']=new CJavaScriptExpression($button['click']);
}
}
View
52 framework/zii/widgets/grid/CGridView.php
@@ -136,9 +136,9 @@ class CGridView extends CBaseListView
* These tokens are recognized: {page} and {sort}. They will be replaced with the pagination and sorting links selectors.
* Defaults to '{page}, {sort}', that means that the pagination links and the sorting links will trigger AJAX updates.
* Tokens are available from 1.1.11
- *
+ *
* Note: if this value is empty an exception will be thrown.
- *
+ *
* Example (adding a custom selector to the default ones):
* <pre>
* ...
@@ -272,8 +272,8 @@ class CGridView extends CBaseListView
public $hideHeader=false;
/**
* @var boolean whether to leverage the {@link https://developer.mozilla.org/en/DOM/window.history DOM history object}. Set this property to true
- * to persist state of grid across page revisits. Note, there are two limitations for this feature:
- * - this feature is only compatible with browsers that support HTML5.
+ * to persist state of grid across page revisits. Note, there are two limitations for this feature:
+ * - this feature is only compatible with browsers that support HTML5.
* - expect unexpected functionality (e.g. multiple ajax calls) if there is more than one grid/list on a single page with enableHistory turned on.
* @since 1.1.11
*/
@@ -392,13 +392,49 @@ public function registerClientScript()
if($this->enablePagination)
$options['pageVar']=$this->dataProvider->getPagination()->pageVar;
if($this->beforeAjaxUpdate!==null)
- $options['beforeAjaxUpdate']=(strpos($this->beforeAjaxUpdate,'js:')!==0 ? 'js:' : '').$this->beforeAjaxUpdate;
+ {
+ if((!$this->beforeAjaxUpdate instanceof CJavaScriptExpression) && strpos($this->beforeAjaxUpdate,'js:')!==0)
+ {
+ $options['beforeAjaxUpdate']=new CJavaScriptExpression($this->beforeAjaxUpdate);
+ }
+ else
+ {
+ $options['beforeAjaxUpdate']=$this->beforeAjaxUpdate;
+ }
+ }
if($this->afterAjaxUpdate!==null)
- $options['afterAjaxUpdate']=(strpos($this->afterAjaxUpdate,'js:')!==0 ? 'js:' : '').$this->afterAjaxUpdate;
+ {
+ if((!$this->afterAjaxUpdate instanceof CJavaScriptExpression) && strpos($this->afterAjaxUpdate,'js:')!==0)
+ {
+ $options['afterAjaxUpdate']=new CJavaScriptExpression($this->afterAjaxUpdate);
+ }
+ else
+ {
+ $options['afterAjaxUpdate']=$this->afterAjaxUpdate;
+ }
+ }
if($this->ajaxUpdateError!==null)
- $options['ajaxUpdateError']=(strpos($this->ajaxUpdateError,'js:')!==0 ? 'js:' : '').$this->ajaxUpdateError;
+ {
+ if((!$this->ajaxUpdateError instanceof CJavaScriptExpression) && strpos($this->ajaxUpdateError,'js:')!==0)
+ {
+ $options['ajaxUpdateError']=new CJavaScriptExpression($this->ajaxUpdateError);
+ }
+ else
+ {
+ $options['ajaxUpdateError']=$this->ajaxUpdateError;
+ }
+ }
if($this->selectionChanged!==null)
- $options['selectionChanged']=(strpos($this->selectionChanged,'js:')!==0 ? 'js:' : '').$this->selectionChanged;
+ {
+ if((!$this->ajaxUpdateError instanceof CJavaScriptExpression) && strpos($this->selectionChanged,'js:')!==0)
+ {
+ $options['selectionChanged']=new CJavaScriptExpression($this->selectionChanged);
+ }
+ else
+ {
+ $options['selectionChanged']=$this->selectionChanged;
+ }
+ }
$options=CJavaScript::encode($options);
$cs=Yii::app()->getClientScript();
View
3 framework/zii/widgets/jui/CJuiAutoComplete.php
@@ -53,7 +53,8 @@ class CJuiAutoComplete extends CJuiInputWidget
* <ul>
* <li>an Array with local data</li>
* <li>a String, specifying a URL that returns JSON data as the entries.</li>
- * <li>a javascript callback. Please make sure you prefix the callback name with "js:" in this case.</li>
+ * <li>a javascript callback. Please make sure you wrap the callback with
+ * {@link CJavaScriptExpression} in this case.</li>
* </ul>
*/
public $source = array();
View
8 framework/zii/widgets/jui/CJuiButton.php
@@ -22,7 +22,7 @@
* 'name'=>'submit',
* 'caption'=>'Save',
* 'options'=>array(
- * 'onclick'=>'js:function(){alert("Yes");}',
+ * 'onclick'=>new CJavaScriptExpression('function(){alert("Yes");}'),
* ),
* ));
* </pre>
@@ -34,7 +34,7 @@
* 'name'=>'button',
* 'caption'=>'Save',
* 'value'=>'asd',
- * 'onclick'=>'js:function(){alert("Save button clicked"); this.blur(); return false;}',
+ * 'onclick'=>new CJavaScriptExpression('function(){alert("Save button clicked"); this.blur(); return false;}'),
* )
* );
* </pre>
@@ -171,8 +171,8 @@ public function run()
$options=empty($this->options) ? '' : CJavaScript::encode($this->options);
if (isset($this->onclick))
{
- if(strpos($this->onclick,'js:')!==0)
- $this->onclick='js:'.$this->onclick;
+ if(!($this->onclick instanceof CJavaScriptExpression) && strpos($this->onclick,'js:')!==0)
+ $this->onclick=new CJavaScriptExpression($this->onclick);
$click = CJavaScript::encode($this->onclick);
$cs->registerScript(__CLASS__.'#'.$id,"jQuery('#{$id}').button($options).click($click);");
}
View
2 framework/zii/widgets/jui/CJuiDatePicker.php
@@ -103,7 +103,7 @@ public function run()
}
if (!isset($this->options['onSelect']))
- $this->options['onSelect']="js:function( selectedDate ) { jQuery('#{$id}').val(selectedDate);}";
+ $this->options['onSelect']=new CJavaScriptExpression("function( selectedDate ) { jQuery('#{$id}').val(selectedDate);}");
$id = $this->htmlOptions['id'] = $id.'_container';
$this->htmlOptions['name'] = $name.'_container';
View
2 framework/zii/widgets/jui/CJuiProgressBar.php
@@ -22,7 +22,7 @@
* 'value'=>75,
* // additional javascript options for the progress bar plugin
* 'options'=>array(
- * 'change'=>'js:function(event, ui) {...}',
+ * 'change'=>CJavaScriptExpression('function(event, ui) {...}'),
* ),
* 'htmlOptions'=>array(
* 'style'=>'height:20px;'
View
6 framework/zii/widgets/jui/CJuiSliderInput.php
@@ -124,7 +124,7 @@ public function run()
if($this->value!==null)
$this->options['value']=$this->value;
}
-
+
$idHidden = $this->htmlOptions['id'];
$nameHidden = $name;
@@ -136,8 +136,8 @@ public function run()
echo CHtml::closeTag($this->tagName);
$this->options[$this->event]= $isRange ?
- "js:function(e,ui){ v=ui.values; jQuery('#{$idHidden}').val(v[0]); jQuery('#{$idHidden}_end').val(v[1]); }":
- 'js:function(event, ui) { jQuery(\'#'. $idHidden .'\').val(ui.value); }';
+ new CJavaScriptExpression("function(e,ui){ v=ui.values; jQuery('#{$idHidden}').val(v[0]); jQuery('#{$idHidden}_end').val(v[1]); }"):
+ new CJavaScriptExpression('function(event, ui) { jQuery(\'#'. $idHidden .'\').val(ui.value); }');
$options=empty($this->options) ? '' : CJavaScript::encode($this->options);
View
4 framework/zii/widgets/jui/CJuiSortable.php
@@ -36,8 +36,8 @@
* the {@link http://jqueryui.com/demos/sortable/ JUI Sortable} documentation
* for possible options (name-value pairs).
*
- * If you are using javascript code anywhere in the code, please add "js:" at the
- * start of the js code definition and Yii will use this string as js code.
+ * If you are using JavaScript expressions anywhere in the code, please wrap it
+ * with {@link CJavaScriptExpression} and Yii will use it as code.
*
* @author Sebastian Thierer <sebathi@gmail.com>
* @version $Id$

0 comments on commit ada1ced

Please sign in to comment.
Something went wrong with that request. Please try again.