Marius Cramer
2015-06-03 3f19613b5ebca832e8f341980278df5f8427c1ca
commit | author | age
2dadd2 1 <?php
T 2
3 /*
4 Copyright (c) 2007, Till Brehm, projektfarm Gmbh
5 All rights reserved.
6
7 Redistribution and use in source and binary forms, with or without modification,
8 are permitted provided that the following conditions are met:
9
992797 10     * Redistributions of source code must retain the above copyright notice,
MC 11       this list of conditions and the following disclaimer.
12     * Redistributions in binary form must reproduce the above copyright notice,
13       this list of conditions and the following disclaimer in the documentation
14       and/or other materials provided with the distribution.
15     * Neither the name of ISPConfig nor the names of its contributors
16       may be used to endorse or promote products derived from this software without
17       specific prior written permission.
2dadd2 18
T 19 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
20 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22 IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
23 INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
24 BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
26 OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
27 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
28 EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31 /**
7fe908 32  * Formularbehandlung
MC 33  *
34  * Functions to validate, display and save form values
35  *
36  *        Database table field definitions
37  *
38  *        Datatypes:
39  *        - INTEGER (Converts data to int automatically)
40  *        - DOUBLE
41  *        - CURRENCY (Formats digits in currency notation)
42  *        - VARCHAR (No format check)
43  *        - DATE (Date format, converts from and to UNIX timestamps automatically)
44  *
45  *        Formtype:
46  *        - TEXT (Normal text field)
47  *        - PASSWORD (password field, the content will not be displayed again to the user)
48  *        - SELECT (Option fiield)
49  *        - MULTIPLE (Allows selection of multiple values)
50  *
51  *        VALUE:
52  *        - Value or array
53  *
54  *        SEPARATOR
55  *        - separator char used for fileds with multiple values
56  *
57  *        Hint: The auto increment (ID) filed of the table has not be be definied separately.
58  *
59  */
60
2dadd2 61
T 62 class tform {
63
7fe908 64     /**
MC 65      * Definition of the database table (array)
66      * @var tableDef
67      */
68     var $tableDef;
2dadd2 69
7fe908 70     /**
MC 71      * Private
72      * @var action
73      */
74     var $action;
2dadd2 75
7fe908 76     /**
MC 77      * Table name (String)
78      * @var table_name
79      */
80     var $table_name;
2dadd2 81
7fe908 82     /**
MC 83      * Debug Variable
84      * @var debug
85      */
86     var $debug = 0;
2dadd2 87
7fe908 88     /**
MC 89      * name of the primary field of the database table (string)
90      * @var table_index
91      */
92     var $table_index;
2dadd2 93
7fe908 94     /**
MC 95      * contains the error messages
96      * @var errorMessage
97      */
98     var $errorMessage = '';
2dadd2 99
7fe908 100     var $dateformat = "d.m.Y";
MC 101     var $formDef = array();
102     var $wordbook;
103     var $module;
104     var $primary_id;
105     var $diffrec = array();
2dadd2 106
7fe908 107     /**
MC 108      * Loading of the table definition
109      *
110      * @param file: path to the form definition file
111      * @return true
112      */
113     /*
992797 114         function loadTableDef($file) {
MC 115                 global $app,$conf;
2dadd2 116
992797 117                 include_once($file);
MC 118                 $this->tableDef = $table;
119                 $this->table_name = $table_name;
120                 $this->table_index = $table_index;
121                 return true;
122         }
123         */
2dadd2 124
7fe908 125     function loadFormDef($file, $module = '') {
MC 126         global $app, $conf;
2dadd2 127
7fe908 128         include $file;
MC 129         $this->formDef = $form;
2dadd2 130
7fe908 131         $this->module = $module;
MC 132         $wb = array();
b5a0dc 133
82e2a2 134         include ISPC_ROOT_PATH.'/lib/lang/'.$_SESSION['s']['language'].'.lng';
2dadd2 135
7fe908 136         if(is_array($wb)) $wb_global = $wb;
2dadd2 137
7fe908 138         if($module == '') {
MC 139             $lng_file = "lib/lang/".$_SESSION["s"]["language"]."_".$this->formDef["name"].".lng";
140             if(!file_exists($lng_file)) $lng_file = "lib/lang/en_".$this->formDef["name"].".lng";
141             include $lng_file;
142         } else {
143             $lng_file = "../$module/lib/lang/".$_SESSION["s"]["language"]."_".$this->formDef["name"].".lng";
144             if(!file_exists($lng_file)) $lng_file = "../$module/lib/lang/en_".$this->formDef["name"].".lng";
145             include $lng_file;
d5473b 146         }
7fe908 147
MC 148         if(is_array($wb_global)) {
7b3516 149             $wb = $app->functions->array_merge($wb_global, $wb);
7fe908 150         }
MC 151         if(isset($wb_global)) unset($wb_global);
152
153         $this->wordbook = $wb;
154
155         $this->dateformat = $app->lng('conf_format_dateshort');
156
157         return true;
158     }
159
160     /**
161      * Converts the data in the array to human readable format
162      * Datatype conversion e.g. to show the data in lists
163      *
164      * @param record
165      * @return record
166      */
167     function decode($record, $tab) {
168         global $conf, $app;
169         if(!is_array($this->formDef['tabs'][$tab])) $app->error("Tab does not exist or the tab is empty (TAB: $tab).");
170         $new_record = '';
171         $table_idx = $this->formDef['db_table_idx'];
172         if(isset($record[$table_idx])) $new_record[$table_idx] = $app->functions->intval($record[$table_idx ]);
173
174         if(is_array($record)) {
175             foreach($this->formDef['tabs'][$tab]['fields'] as $key => $field) {
176
177                 //* Apply filter to record value.
178                 if(isset($field['filters']) && is_array($field['filters'])) {
179                     $record[$key] = $this->filterField($key, (isset($record[$key]))?$record[$key]:'', $field['filters'], 'SHOW');
180                 }
181
182                 switch ($field['datatype']) {
183                 case 'VARCHAR':
184                     $new_record[$key] = $record[$key];
185                     break;
186
187                 case 'TEXT':
188                     $new_record[$key] = $record[$key];
189                     break;
190
191                 case 'DATETSTAMP':
192                     if($record[$key] > 0) {
193                         $new_record[$key] = date($this->dateformat, $record[$key]);
194                     }
195                     break;
196
197                 case 'DATE':
198                     if($record[$key] != '' && $record[$key] != '0000-00-00') {
199                         $tmp = explode('-', $record[$key]);
200                         $new_record[$key] = date($this->dateformat, mktime(0, 0, 0, $tmp[1]  , $tmp[2], $tmp[0]));
201                     }
202                     break;
203
204                 case 'INTEGER':
205                     $new_record[$key] = $app->functions->intval($record[$key]);
206                     break;
207
208                 case 'DOUBLE':
209                     $new_record[$key] = $record[$key];
210                     break;
211
212                 case 'CURRENCY':
213                     $new_record[$key] = $app->functions->currency_format($record[$key]);
214                     break;
215
216                 default:
217                     $new_record[$key] = $record[$key];
2dadd2 218                 }
T 219             }
7fe908 220
MC 221         }
222
223         return $new_record;
224     }
225
226
227     /**
228      * Get the key => value array of a form filled from a datasource definitiom
229      *
230      * @param field = array with field definition
231      * @param record = Dataset as array
232      * @return key => value array for the value field of a form
233      */
234     function getDatasourceData($field, $record) {
235         global $app;
236
237         $values = array();
238
239         if($field["datasource"]["type"] == 'SQL') {
240
241             // Preparing SQL string. We will replace some
242             // common placeholders
243             $querystring = $field["datasource"]["querystring"];
244             $querystring = str_replace("{USERID}", $_SESSION["s"]["user"]["userid"], $querystring);
245             $querystring = str_replace("{GROUPID}", $_SESSION["s"]["user"]["default_group"], $querystring);
246             $querystring = str_replace("{GROUPS}", $_SESSION["s"]["user"]["groups"], $querystring);
247             $table_idx = $this->formDef['db_table_idx'];
248
249             $tmp_recordid = (isset($record[$table_idx]))?$record[$table_idx]:0;
250             $querystring = str_replace("{RECORDID}", $tmp_recordid, $querystring);
251             unset($tmp_recordid);
252
253             $querystring = str_replace("{AUTHSQL}", $this->getAuthSQL('r'), $querystring);
b509d0 254             //$querystring = preg_replace_callback('@{AUTHSQL::(.+?)}@', "self::table_auth_sql", $querystring);
TB 255             //*Used the ld form to be compatible with php < 5.3
256             $querystring = preg_replace_callback('@{AUTHSQL::(.+?)}@', create_function('$matches','global $app; $tmp = $app->tform->getAuthSQL("r", $matches[1]); return $tmp;'), $querystring);
7fe908 257
MC 258             // Getting the records
259             $tmp_records = $app->db->queryAllRecords($querystring);
260             if($app->db->errorMessage != '') die($app->db->errorMessage);
261             if(is_array($tmp_records)) {
262                 $key_field = $field["datasource"]["keyfield"];
263                 $value_field = $field["datasource"]["valuefield"];
264                 foreach($tmp_records as $tmp_rec) {
265                     $tmp_id = $tmp_rec[$key_field];
266                     $values[$tmp_id] = $tmp_rec[$value_field];
267                 }
268             }
269         }
270
271         if($field["datasource"]["type"] == 'CUSTOM') {
272             // Calls a custom class to validate this record
273             if($field["datasource"]['class'] != '' and $field["datasource"]['function'] != '') {
274                 $datasource_class = $field["datasource"]['class'];
275                 $datasource_function = $field["datasource"]['function'];
276                 $app->uses($datasource_class);
277                 $values = $app->$datasource_class->$datasource_function($field, $record);
278             } else {
279                 $this->errorMessage .= "Custom datasource class or function is empty<br />\r\n";
280             }
281         }
282
283         if(isset($field['filters']) && is_array($field['filters'])) {
284             $new_values = array();
285             foreach($values as $index => $value) {
286                 $new_index = $this->filterField($index, $index, $field['filters'], 'SHOW');
287                 $new_values[$new_index] = $this->filterField($index, (isset($values[$index]))?$values[$index]:'', $field['filters'], 'SHOW');
288             }
289             $values = $new_values;
290             unset($new_values);
291             unset($new_index);
292         }
293
294         return $values;
295
296     }
b509d0 297     
TB 298     /*
7fe908 299     function table_auth_sql($matches){
MC 300         return $this->getAuthSQL('r', $matches[1]);
301     }
b509d0 302     */
7fe908 303
MC 304     //* If the parameter 'valuelimit' is set
305     function applyValueLimit($limit, $values) {
306
307         global $app;
308
309         $limit_parts = explode(':', $limit);
310
311         //* values are limited to a comma separated list
312         if($limit_parts[0] == 'list') {
313             $allowed = explode(',', $limit_parts[1]);
314         }
315
316         //* values are limited to a field in the client settings
317         if($limit_parts[0] == 'client') {
318             if($_SESSION["s"]["user"]["typ"] == 'admin') {
319                 return $values;
320             } else {
321                 $client_group_id = $_SESSION["s"]["user"]["default_group"];
322                 $client = $app->db->queryOneRecord("SELECT ".$limit_parts[1]." as lm FROM sys_group, client WHERE sys_group.client_id = client.client_id and sys_group.groupid = $client_group_id");
323                 $allowed = explode(',', $client['lm']);
324             }
325         }
326
327         //* values are limited to a field in the reseller settings
328         if($limit_parts[0] == 'reseller') {
329             if($_SESSION["s"]["user"]["typ"] == 'admin') {
330                 return $values;
331             } else {
332                 //* Get the limits of the client that is currently logged in
333                 $client_group_id = $_SESSION["s"]["user"]["default_group"];
334                 $client = $app->db->queryOneRecord("SELECT parent_client_id FROM sys_group, client WHERE sys_group.client_id = client.client_id and sys_group.groupid = $client_group_id");
335                 //echo "SELECT parent_client_id FROM sys_group, client WHERE sys_group.client_id = client.client_id and sys_group.groupid = $client_group_id";
336                 //* If the client belongs to a reseller, we will check against the reseller Limit too
337                 if($client['parent_client_id'] != 0) {
338
339                     //* first we need to know the groups of this reseller
340                     $tmp = $app->db->queryOneRecord("SELECT userid, groups FROM sys_user WHERE client_id = ".$client['parent_client_id']);
341                     $reseller_groups = $tmp["groups"];
342                     $reseller_userid = $tmp["userid"];
343
344                     // Get the limits of the reseller of the logged in client
67c4b3 345                     $client_group_id = $_SESSION["s"]["user"]["default_group"];
7fe908 346                     $reseller = $app->db->queryOneRecord("SELECT ".$limit_parts[1]." as lm FROM client WHERE client_id = ".$client['parent_client_id']);
MC 347                     $allowed = explode(',', $reseller['lm']);
348                 } else {
349                     return $values;
350                 }
351             } // end if admin
352         } // end if reseller
353
354         //* values are limited to a field in the system settings
355         if($limit_parts[0] == 'system') {
356             $app->uses('getconf');
357             $tmp_conf = $app->getconf->get_global_config($limit_parts[1]);
358             $tmp_key = $limit_parts[2];
359             $allowed = $tmp_conf[$tmp_key];
360         }
361
362         $values_new = array();
363         foreach($values as $key => $val) {
364             if(in_array($key, $allowed)) $values_new[$key] = $val;
365         }
366
367         return $values_new;
368     }
369
370
371     /**
372      * Prepare the data record to show the data in a form.
373      *
374      * @param record = Datensatz als Array
375      * @param action = NEW oder EDIT
376      * @return record
377      */
378     function getHTML($record, $tab, $action = 'NEW') {
379
380         global $app;
381
382         $this->action = $action;
383
384         if(!is_array($this->formDef)) $app->error("No form definition found.");
385         if(!is_array($this->formDef['tabs'][$tab])) $app->error("The tab is empty or does not exist (TAB: $tab).");
582cbf 386         
MC 387         /* CSRF PROTECTION */
388         // generate csrf protection id and key
389         $_csrf_id = uniqid($this->formDef['name'] . '_');
390         $_csrf_value = sha1(uniqid(microtime(true), true));
391         if(!isset($_SESSION['_csrf'])) $_SESSION['_csrf'] = array();
392         if(!isset($_SESSION['_csrf_timeout'])) $_SESSION['_csrf_timeout'] = array();
393         $_SESSION['_csrf'][$_csrf_id] = $_csrf_value;
394         $_SESSION['_csrf_timeout'][$_csrf_id] = time() + 3600; // timeout hash in 1 hour
395         $this->formDef['tabs'][$tab]['fields']['_csrf_id'] = array(
396             'datatype' => 'VARCHAR',
397             'formtype' => 'TEXT',
398             'default' => $_csrf_id,
399             'value' => $_csrf_id
400         );
401         $this->formDef['tabs'][$tab]['fields']['_csrf_key'] = array(
402             'datatype' => 'VARCHAR',
403             'formtype' => 'TEXT',
404             'default' => $_csrf_value,
405             'value' => $_csrf_value
406         );
407         $record['_csrf_id'] = $_csrf_id;
408         $record['_csrf_key'] = $_csrf_value;
409         /* CSRF PROTECTION */
410         
7fe908 411         $new_record = array();
MC 412         if($action == 'EDIT') {
413             $record = $this->decode($record, $tab);
414             if(is_array($record)) {
415                 foreach($this->formDef['tabs'][$tab]['fields'] as $key => $field) {
416
417                     if(isset($record[$key])) {
418                         $val = $record[$key];
67c4b3 419                     } else {
7fe908 420                         $val = '';
67c4b3 421                     }
2dadd2 422
7fe908 423                     // If Datasource is set, get the data from there
MC 424                     if(isset($field['datasource']) && is_array($field['datasource'])) {
425                         if(is_array($field["value"])) {
426                             //$field["value"] = array_merge($field["value"],$this->getDatasourceData($field, $record));
427                             $field["value"] = $app->functions->array_merge($field["value"], $this->getDatasourceData($field, $record));
428                         } else {
429                             $field["value"] = $this->getDatasourceData($field, $record);
430                         }
431                     }
2dadd2 432
7fe908 433                     // If a limitation for the values is set
MC 434                     if(isset($field['valuelimit']) && is_array($field["value"])) {
435                         $field["value"] = $this->applyValueLimit($field['valuelimit'], $field["value"]);
436                     }
2dadd2 437
7fe908 438                     switch ($field['formtype']) {
MC 439                     case 'SELECT':
440                         $out = '';
441                         if(is_array($field['value'])) {
442                             foreach($field['value'] as $k => $v) {
443                                 $selected = ($k == $val)?' SELECTED':'';
444                                 if(!empty($this->wordbook[$v]))
445                                     $v = $this->wordbook[$v];
446                                 $out .= "<option value='$k'$selected>".$this->lng($v)."</option>\r\n";
447                             }
448                         }
449                         $new_record[$key] = $out;
450                         break;
451                     case 'MULTIPLE':
452                         if(is_array($field['value'])) {
2dadd2 453
7fe908 454                             // Split
MC 455                             $vals = explode($field['separator'], $val);
2dadd2 456
7fe908 457                             // write HTML
MC 458                             $out = '';
459                             foreach($field['value'] as $k => $v) {
2dadd2 460
7fe908 461                                 $selected = '';
MC 462                                 foreach($vals as $tvl) {
463                                     if(trim($tvl) == trim($k)) $selected = ' SELECTED';
2dadd2 464                                 }
T 465
7fe908 466                                 $out .= "<option value='$k'$selected>$v</option>\r\n";
MC 467                             }
468                         }
469                         $new_record[$key] = $out;
470                         break;
2dadd2 471
7fe908 472                     case 'PASSWORD':
MC 473                         $new_record[$key] = '';
474                         break;
2dadd2 475
7fe908 476                     case 'CHECKBOX':
MC 477                         $checked = ($val == $field['value'][1])?' CHECKED':'';
478                         $new_record[$key] = "<input name=\"".$key."\" id=\"".$key."\" value=\"".$field['value'][1]."\" type=\"checkbox\" $checked />\r\n";
479                         break;
2dadd2 480
7fe908 481                     case 'CHECKBOXARRAY':
MC 482                         if(is_array($field['value'])) {
2dadd2 483
7fe908 484                             // aufsplitten ergebnisse
MC 485                             $vals = explode($field['separator'], $val);
2dadd2 486
7fe908 487                             // HTML schreiben
MC 488                             $out = '';
489                             $elementNo = 0;
490                             foreach($field['value'] as $k => $v) {
2dadd2 491
7fe908 492                                 $checked = '';
MC 493                                 foreach($vals as $tvl) {
494                                     if(trim($tvl) == trim($k)) $checked = ' CHECKED';
d370bb 495                                 }
7fe908 496                                 // $out .= "<label for=\"".$key."[]\" class=\"inlineLabel\"><input name=\"".$key."[]\" id=\"".$key."[]\" value=\"$k\" type=\"checkbox\" $checked /> $v</label>\r\n";
MC 497                                 $out .= "<label for=\"".$key.$elementNo."\" class=\"inlineLabel\"><input name=\"".$key."[]\" id=\"".$key.$elementNo."\" value=\"$k\" type=\"checkbox\" $checked /> $v</label><br/>\r\n";
498                                 $elementNo++;
499                             }
500                         }
501                         $new_record[$key] = $out;
502                         break;
2dadd2 503
7fe908 504                     case 'RADIO':
MC 505                         if(is_array($field['value'])) {
2dadd2 506
7fe908 507                             // HTML schreiben
MC 508                             $out = '';
509                             $elementNo = 0;
510                             foreach($field['value'] as $k => $v) {
511                                 $checked = ($k == $val)?' CHECKED':'';
512                                 //$out .= "<label for=\"".$key."[]\" class=\"inlineLabel\"><input name=\"".$key."[]\" id=\"".$key."[]\" value=\"$k\" type=\"radio\" $checked/> $v</label>\r\n";
513                                 $out .= "<label for=\"".$key.$elementNo."\" class=\"inlineLabel\"><input name=\"".$key."[]\" id=\"".$key.$elementNo."\" value=\"$k\" type=\"radio\" $checked/> $v </label>\r\n";
514                                 $elementNo++;
515                             }
516                         }
517                         $new_record[$key] = $out;
518                         break;
2332b2 519
7fe908 520                     case 'DATETIME':
MC 521                         if (strtotime($val) !== false) {
522                             $dt_value = $val;
523                         } elseif ( isset($field['default']) && (strtotime($field['default']) !== false) ) {
524                             $dt_value = $field['default'];
525                         } else {
526                             $dt_value = 0;
527                         }
d370bb 528
7fe908 529                         $display_seconds = (isset($field['display_seconds']) && $field['display_seconds'] == true) ? true : false;
MC 530
531                         $new_record[$key] = $this->_getDateTimeHTML($key, $dt_value, $display_seconds);
d370bb 532                         break;
7fe908 533
MC 534                     default:
535                         if(isset($record[$key])) {
536                             $new_record[$key] = htmlspecialchars($record[$key]);
537                         } else {
538                             $new_record[$key] = '';
539                         }
d370bb 540                     }
T 541                 }
542             }
7fe908 543         } else {
MC 544             // Action: NEW
545             foreach($this->formDef['tabs'][$tab]['fields'] as $key => $field) {
2dadd2 546
7fe908 547                 // If Datasource is set, get the data from there
MC 548                 if(@is_array($field['datasource'])) {
549                     if(is_array($field["value"])) {
550                         $field["value"] = $app->functions->array_merge($field["value"], $this->getDatasourceData($field, $record));
551                     } else {
552                         $field["value"] = $this->getDatasourceData($field, $record);
553                     }
554                 }
2dadd2 555
7fe908 556                 // If a limitation for the values is set
MC 557                 if(isset($field['valuelimit']) && is_array($field["value"])) {
558                     $field["value"] = $this->applyValueLimit($field['valuelimit'], $field["value"]);
559                 }
2dadd2 560
7fe908 561                 switch ($field['formtype']) {
MC 562                 case 'SELECT':
563                     if(is_array($field['value'])) {
564                         $out = '';
565                         foreach($field['value'] as $k => $v) {
566                             $selected = ($k == $field["default"])?' SELECTED':'';
567                             $out .= "<option value='$k'$selected>".$this->lng($v)."</option>\r\n";
568                         }
569                     }
570                     if(isset($out)) $new_record[$key] = $out;
571                     break;
572                 case 'MULTIPLE':
573                     if(is_array($field['value'])) {
2dadd2 574
7fe908 575                         // aufsplitten ergebnisse
MC 576                         $vals = explode($field['separator'], $val);
577
578                         // HTML schreiben
579                         $out = '';
580                         foreach($field['value'] as $k => $v) {
581
582                             $out .= "<option value='$k'>$v</option>\r\n";
583                         }
584                     }
585                     $new_record[$key] = $out;
586                     break;
587
588                 case 'PASSWORD':
589                     //$new_record[$key] = '';
590                     $new_record[$key] = htmlspecialchars($field['default']);
591                     break;
592
593                 case 'CHECKBOX':
594                     // $checked = (empty($field["default"]))?'':' CHECKED';
595                     $checked = ($field["default"] == $field['value'][1])?' CHECKED':'';
596                     $new_record[$key] = "<input name=\"".$key."\" id=\"".$key."\" value=\"".$field['value'][1]."\" type=\"checkbox\" $checked />\r\n";
597                     break;
598
599                 case 'CHECKBOXARRAY':
600                     if(is_array($field['value'])) {
601
602                         // aufsplitten ergebnisse
603                         $vals = explode($field['separator'], $field["default"]);
604
605                         // HTML schreiben
606                         $out = '';
607                         $elementNo = 0;
608                         foreach($field['value'] as $k => $v) {
609
610                             $checked = '';
611                             foreach($vals as $tvl) {
612                                 if(trim($tvl) == trim($k)) $checked = ' CHECKED';
613                             }
614                             // $out .= "<label for=\"".$key."[]\" class=\"inlineLabel\"><input name=\"".$key."[]\" id=\"".$key."[]\" value=\"$k\" type=\"checkbox\" $checked /> $v</label>\r\n";
615                             $out .= "<label for=\"".$key.$elementNo."\" class=\"inlineLabel\"><input name=\"".$key."[]\" id=\"".$key.$elementNo."\" value=\"$k\" type=\"checkbox\" $checked /> $v</label> &nbsp;\r\n";
616                             $elementNo++;
617                         }
618                     }
619                     $new_record[$key] = $out;
620                     break;
621
622                 case 'RADIO':
623                     if(is_array($field['value'])) {
624
625                         // HTML schreiben
626                         $out = '';
627                         $elementNo = 0;
628                         foreach($field['value'] as $k => $v) {
629                             $checked = ($k == $field["default"])?' CHECKED':'';
630                             //$out .= "<label for=\"".$key."[]\" class=\"inlineLabel\"><input name=\"".$key."[]\" id=\"".$key."[]\" value=\"$k\" type=\"radio\" $checked/> $v</label>\r\n";
631                             $out .= "<label for=\"".$key.$elementNo."\" class=\"inlineLabel\"><input name=\"".$key."[]\" id=\"".$key.$elementNo."\" value=\"$k\" type=\"radio\" $checked/> $v</label>\r\n";
632                             $elementNo++;
633                         }
634                     }
635                     $new_record[$key] = $out;
636                     break;
637
638                 case 'DATETIME':
639                     $dt_value = (isset($field['default'])) ? $field['default'] : 0;
640                     $display_seconds = (isset($field['display_seconds']) && $field['display_seconds'] == true) ? true : false;
641
642                     $new_record[$key] = $this->_getDateTimeHTML($key, $dt_value, $display_seconds);
643                     break;
644
645                 default:
646                     $new_record[$key] = htmlspecialchars($field['default']);
647                 }
648             }
649
650         }
651
652         if($this->debug == 1) $this->dbg($new_record);
653
654         return $new_record;
655     }
656
657
658     /**
659      * Rewrite the record data to be stored in the database
660      * and check values with regular expressions.
661      *
662      * @param record = Datensatz als Array
663      * @return record
664      */
665     function encode($record, $tab, $dbencode = true) {
666         global $app;
667
668         if(!is_array($this->formDef['tabs'][$tab])) $app->error("Tab is empty or does not exist (TAB: $tab).");
669         //$this->errorMessage = '';
582cbf 670         
MC 671         /* CSRF PROTECTION */
672         if(isset($_POST) && is_array($_POST)) {
673             $_csrf_valid = false;
674             if(isset($_POST['_csrf_id']) && isset($_POST['_csrf_key'])) {
675                 $_csrf_id = trim($_POST['_csrf_id']);
676                 $_csrf_key = trim($_POST['_csrf_key']);
677                 if(isset($_SESSION['_csrf']) && isset($_SESSION['_csrf'][$_csrf_id]) && isset($_SESSION['_csrf_timeout']) && isset($_SESSION['_csrf_timeout'][$_csrf_id])) {
678                     if($_SESSION['_csrf'][$_csrf_id] === $_csrf_key && $_SESSION['_csrf_timeout'] >= time()) $_csrf_valid = true;
679                 }
680             }
681             if($_csrf_valid !== true) {
682                 $app->log('CSRF attempt blocked. Referer: ' . (isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : 'unknown'), LOGLEVEL_WARN);
e8f943 683                 $errmsg = 'err_csrf_attempt_blocked';
MC 684                 $this->errorMessage .= ($api == true ? $errmsg : $this->wordbook[$errmsg]."<br />") . "\r\n";
582cbf 685                 unset($_POST);
MC 686                 unset($record);
687             }
f3cc2c 688             $_SESSION['_csrf'][$_csrf_id] = null;
MC 689             $_SESSION['_csrf_timeout'][$_csrf_id] = null;
582cbf 690             unset($_SESSION['_csrf'][$_csrf_id]);
MC 691             unset($_SESSION['_csrf_timeout'][$_csrf_id]);
692             
693             if(isset($_SESSION['_csrf_timeout']) && is_array($_SESSION['_csrf_timeout'])) {
694                 $to_unset = array();
695                 foreach($_SESSION['_csrf_timeout'] as $_csrf_id => $timeout) {
696                     if($timeout < time()) $to_unset[] = $_csrf_id;
697                 }
698                 foreach($to_unset as $_csrf_id) {
f3cc2c 699                     $_SESSION['_csrf'][$_csrf_id] = null;
MC 700                     $_SESSION['_csrf_timeout'][$_csrf_id] = null;
582cbf 701                     unset($_SESSION['_csrf'][$_csrf_id]);
MC 702                     unset($_SESSION['_csrf_timeout'][$_csrf_id]);
703                 }
704                 unset($to_unset);
705             }
706         }
707         /* CSRF PROTECTION */
708         
709         $new_record = array();
7fe908 710         if(is_array($record)) {
MC 711             foreach($this->formDef['tabs'][$tab]['fields'] as $key => $field) {
712
713                 //* Apply filter to record value
714                 if(isset($field['filters']) && is_array($field['filters'])) {
715                     $record[$key] = $this->filterField($key, (isset($record[$key]))?$record[$key]:'', $field['filters'], 'SAVE');
716                 }
717                 //* Validate record value
718                 if(isset($field['validators']) && is_array($field['validators'])) {
719                     $this->validateField($key, (isset($record[$key]))?$record[$key]:'', $field['validators']);
720                 }
721
722                 switch ($field['datatype']) {
723                 case 'VARCHAR':
724                     if(!@is_array($record[$key])) {
725                         $new_record[$key] = (isset($record[$key]))?$record[$key]:'';
726                     } else {
727                         $new_record[$key] = implode($field['separator'], $record[$key]);
728                     }
729                     break;
730                 case 'TEXT':
731                     if(!is_array($record[$key])) {
732                         $new_record[$key] = $record[$key];
733                     } else {
734                         $new_record[$key] = implode($field['separator'], $record[$key]);
735                     }
736                     break;
737                 case 'DATETSTAMP':
738                     if($record[$key] > 0) {
739                         list($tag, $monat, $jahr) = explode('.', $record[$key]);
740                         $new_record[$key] = mktime(0, 0, 0, $monat, $tag, $jahr);
741                     } else {
742                         $new_record[$key] = 0;
743                     }
744                     break;
745                 case 'DATE':
746                     if($record[$key] != '' && $record[$key] != '0000-00-00') {
747                         if(function_exists('date_parse_from_format')) {
748                             $date_parts = date_parse_from_format($this->dateformat, $record[$key]);
749                             //list($tag,$monat,$jahr) = explode('.',$record[$key]);
750                             $new_record[$key] = $date_parts['year'].'-'.$date_parts['month'].'-'.$date_parts['day'];
751                             //$tmp = strptime($record[$key],$this->dateformat);
752                             //$new_record[$key] = ($tmp['tm_year']+1900).'-'.($tmp['tm_mon']+1).'-'.$tmp['tm_mday'];
753                         } else {
754                             //$tmp = strptime($record[$key],$this->dateformat);
755                             //$new_record[$key] = ($tmp['tm_year']+1900).'-'.($tmp['tm_mon']+1).'-'.$tmp['tm_mday'];
756                             $tmp = strtotime($record[$key]);
757                             $new_record[$key] = date('Y-m-d', $tmp);
758                         }
759                     } else {
760                         $new_record[$key] = '0000-00-00';
761                     }
762                     break;
763                 case 'INTEGER':
764                     $new_record[$key] = (isset($record[$key]))?$app->functions->intval($record[$key]):0;
765                     //if($new_record[$key] != $record[$key]) $new_record[$key] = $field['default'];
766                     //if($key == 'refresh') die($record[$key]);
767                     break;
768                 case 'DOUBLE':
769                     $new_record[$key] = $record[$key];
770                     break;
771                 case 'CURRENCY':
772                     $new_record[$key] = str_replace(",", ".", $record[$key]);
773                     break;
774
775                 case 'DATETIME':
776                     if (is_array($record[$key]))
777                     {
778                         $filtered_values = array_map(create_function('$item', 'return (int)$item;'), $record[$key]);
779                         extract($filtered_values, EXTR_PREFIX_ALL, '_dt');
780
781                         if ($_dt_day != 0 && $_dt_month != 0 && $_dt_year != 0) {
782                             $new_record[$key] = date( 'Y-m-d H:i:s', mktime($_dt_hour, $_dt_minute, $_dt_second, $_dt_month, $_dt_day, $_dt_year) );
783                         }
784                     }
785                     break;
786                 }
787
788                 // The use of the field value is deprecated, use validators instead
789                 if(isset($field['regex']) && $field['regex'] != '') {
790                     // Enable that "." matches also newlines
791                     $field['regex'] .= 's';
792                     if(!preg_match($field['regex'], $record[$key])) {
793                         $errmsg = $field['errmsg'];
794                         $this->errorMessage .= $this->wordbook[$errmsg]."<br />\r\n";
795                     }
796                 }
797
798                 //* Add slashes to all records, when we encode data which shall be inserted into mysql.
799                 if($dbencode == true) $new_record[$key] = $app->db->quote($new_record[$key]);
800             }
801         }
802         return $new_record;
803     }
804
805
806
807
808
809     /**
810      * process the filters for a given field.
811      *
812      * @param field_name = Name of the field
813      * @param field_value = value of the field
814      * @param filters = Array of filters
815      * @param filter_event = 'SAVE'or 'SHOW'
816      * @return record
817      */
818     function filterField($field_name, $field_value, $filters, $filter_event) {
819
820         global $app;
821         $returnval = $field_value;
822
823         //* Loop trough all filters
824         foreach($filters as $filter) {
825             if($filter['event'] == $filter_event) {
826                 switch ($filter['type']) {
827                 case 'TOLOWER':
828                     $returnval = strtolower($returnval);
829                     break;
830                 case 'TOUPPER':
831                     $returnval = strtoupper($returnval);
832                     break;
833                 case 'IDNTOASCII':
834                     $returnval = $app->functions->idn_encode($returnval);
835                     break;
836                 case 'IDNTOUTF8':
837                     $returnval = $app->functions->idn_decode($returnval);
838                     break;
839                 default:
840                     $this->errorMessage .= "Unknown Filter: ".$filter['type'];
841                     break;
842                 }
843             }
844         }
845         return $returnval;
846     }
847
848
849     /**
850      * process the validators for a given field.
851      *
852      * @param field_name = Name of the field
853      * @param field_value = value of the field
854      * @param validatoors = Array of validators
855      * @return record
856      */
857     function validateField($field_name, $field_value, $validators) {
858
859         global $app;
860
861         $escape = '`';
862
863         // loop trough the validators
864         foreach($validators as $validator) {
865
866             switch ($validator['type']) {
867             case 'REGEX':
868                 $validator['regex'] .= 's';
869                 if(!preg_match($validator['regex'], $field_value)) {
870                     $errmsg = $validator['errmsg'];
871                     if(isset($this->wordbook[$errmsg])) {
872                         $this->errorMessage .= $this->wordbook[$errmsg]."<br />\r\n";
873                     } else {
874                         $this->errorMessage .= $errmsg."<br />\r\n";
875                     }
876                 }
877                 break;
878             case 'UNIQUE':
879                 if($validator['allowempty'] != 'y') $validator['allowempty'] = 'n';
880                 if($validator['allowempty'] == 'n' || ($validator['allowempty'] == 'y' && $field_value != '')){
881                     if($this->action == 'NEW') {
882                         $num_rec = $app->db->queryOneRecord("SELECT count(*) as number FROM ".$escape.$this->formDef['db_table'].$escape. " WHERE $field_name = '".$app->db->quote($field_value)."'");
883                         if($num_rec["number"] > 0) {
884                             $errmsg = $validator['errmsg'];
885                             if(isset($this->wordbook[$errmsg])) {
886                                 $this->errorMessage .= $this->wordbook[$errmsg]."<br />\r\n";
887                             } else {
888                                 $this->errorMessage .= $errmsg."<br />\r\n";
889                             }
890                         }
891                     } else {
892                         $num_rec = $app->db->queryOneRecord("SELECT count(*) as number FROM ".$escape.$this->formDef['db_table'].$escape. " WHERE $field_name = '".$app->db->quote($field_value)."' AND ".$this->formDef['db_table_idx']." != ".$this->primary_id);
893                         if($num_rec["number"] > 0) {
894                             $errmsg = $validator['errmsg'];
895                             if(isset($this->wordbook[$errmsg])) {
896                                 $this->errorMessage .= $this->wordbook[$errmsg]."<br />\r\n";
897                             } else {
898                                 $this->errorMessage .= $errmsg."<br />\r\n";
899                             }
900                         }
901                     }
902                 }
903                 break;
904             case 'NOTEMPTY':
905                 if(empty($field_value)) {
906                     $errmsg = $validator['errmsg'];
907                     if(isset($this->wordbook[$errmsg])) {
908                         $this->errorMessage .= $this->wordbook[$errmsg]."<br />\r\n";
909                     } else {
910                         $this->errorMessage .= $errmsg."<br />\r\n";
911                     }
912                 }
913                 break;
0bfbaa 914             case 'ISASCII':
MC 915                 if(preg_match("/[^\x20-\x7F]/", $field_value)) {
916                     $errmsg = $validator['errmsg'];
917                     if(isset($this->wordbook[$errmsg])) {
918                         $this->errorMessage .= $this->wordbook[$errmsg]."<br />\r\n";
919                     } else {
920                         $this->errorMessage .= $errmsg."<br />\r\n";
921                     }
922                 }
7fe908 923             case 'ISEMAIL':
MC 924                 if(function_exists('filter_var')) {
925                     if(filter_var($field_value, FILTER_VALIDATE_EMAIL) === false) {
926                         $errmsg = $validator['errmsg'];
927                         if(isset($this->wordbook[$errmsg])) {
928                             $this->errorMessage .= $this->wordbook[$errmsg]."<br />\r\n";
929                         } else {
930                             $this->errorMessage .= $errmsg."<br />\r\n";
931                         }
932                     }
933                 } else {
934                     if(!preg_match("/^\w+[\w\.\-\+]*\w{0,}@\w+[\w.-]*\w+\.[a-zA-Z0-9\-]{2,30}$/i", $field_value)) {
935                         $errmsg = $validator['errmsg'];
936                         if(isset($this->wordbook[$errmsg])) {
937                             $this->errorMessage .= $this->wordbook[$errmsg]."<br />\r\n";
938                         } else {
939                             $this->errorMessage .= $errmsg."<br />\r\n";
940                         }
941                     }
942                 }
943                 break;
944             case 'ISINT':
945                 if(function_exists('filter_var') && $field_value < 2147483647) {
946                     if($field_value != '' && filter_var($field_value, FILTER_VALIDATE_INT) === false) {
947                         $errmsg = $validator['errmsg'];
948                         if(isset($this->wordbook[$errmsg])) {
949                             $this->errorMessage .= $this->wordbook[$errmsg]."<br />\r\n";
950                         } else {
951                             $this->errorMessage .= $errmsg."<br />\r\n";
952                         }
953                     }
954                 } else {
955                     $tmpval = $app->functions->intval($field_value);
956                     if($tmpval === 0 and !empty($field_value)) {
957                         $errmsg = $validator['errmsg'];
958                         if(isset($this->wordbook[$errmsg])) {
959                             $this->errorMessage .= $this->wordbook[$errmsg]."<br />\r\n";
960                         } else {
961                             $this->errorMessage .= $errmsg."<br />\r\n";
962                         }
963                     }
964                 }
965                 break;
966             case 'ISPOSITIVE':
967                 if(!is_numeric($field_value) || $field_value <= 0){
968                     $errmsg = $validator['errmsg'];
969                     if(isset($this->wordbook[$errmsg])) {
970                         $this->errorMessage .= $this->wordbook[$errmsg]."<br />\r\n";
971                     } else {
972                         $this->errorMessage .= $errmsg."<br />\r\n";
973                     }
974                 }
975                 break;
992797 976                 /*
146783 977                 case 'ISV6PREFIX':
MC 978                     $v6_prefix_ok = 0;
979                     $explode_field_value = explode(':',$field_value);
980                     if ($explode_field_value[count($explode_field_value)-1]=='' && $explode_field_value[count($explode_field_value)-2]=='' ){
981                             if ( count($explode_field_value) <= 9 ) {
982                                     if(filter_var(substr($field_value,0,strlen($field_value)-2),FILTER_VALIDATE_IP,FILTER_FLAG_IPV6) or filter_var(substr($field_value,0,strlen($field_value)-2).'::0',FILTER_VALIDATE_IP,FILTER_FLAG_IPV6) or filter_var(substr($field_value,0,strlen($field_value)-2).':0',FILTER_VALIDATE_IP,FILTER_FLAG_IPV6) ) {
983                                             $v6_prefix_ok = 1;
984                                     }
985                             }
7fe908 986                     } else {
MC 987                         $v6_prefix_ok = 2;
146783 988                     }
MC 989                     // check subnet against defined server-ipv6
990                     $sql_v6 = $app->db->queryOneRecord("SELECT ip_address FROM server_ip WHERE ip_type = 'IPv6' AND virtualhost = 'y' LIMIT 0,1");
991                     $sql_v6_explode=explode(':',$sql_v6['ip_address']);
7fe908 992                     if ( count($sql_v6_explode) < count($explode_field_value) && isset($sql_v6['ip_address']) )  {
MC 993                         $v6_prefix_ok = 3;
146783 994                     }
7fe908 995                     if($v6_prefix_ok == 0) {
MC 996                         $errmsg = $validator['errmsg'];
146783 997                     }
7fe908 998                     if($v6_prefix_ok == 2) {
MC 999                         $errmsg = 'IPv6 Prefix must end with ::';
146783 1000                     }
7fe908 1001                     if($v6_prefix_ok == 3) {
MC 1002                         $errmsg = 'IPv6 Prefix too long (according to Server IP Addresses)';
146783 1003                     }
MC 1004                     if($v6_prefix_ok <> 1){
7fe908 1005                         $this->errorMessage .= $errmsg."<br />\r\n";
146783 1006                     }
30fc1b 1007                 break;
146783 1008                 */
7fe908 1009             case 'ISIPV4':
MC 1010                 $vip=1;
1011                 if(preg_match("/^[0-9]{1,3}(\.)[0-9]{1,3}(\.)[0-9]{1,3}(\.)[0-9]{1,3}$/", $field_value)){
1012                     $groups=explode(".", $field_value);
1013                     foreach($groups as $group){
1014                         if($group<0 or $group>255)
1015                             $vip=0;
2dadd2 1016                     }
7fe908 1017                 }else{$vip=0;}
MC 1018                 if($vip==0) {
1019                     $errmsg = $validator['errmsg'];
1020                     if(isset($this->wordbook[$errmsg])) {
1021                         $this->errorMessage .= $this->wordbook[$errmsg]."<br />\r\n";
1022                     } else {
1023                         $this->errorMessage .= $errmsg."<br />\r\n";
1024                     }
1025                 }
1026                 break;
1027             case 'ISIP':
1028                 if($validator['allowempty'] != 'y') $validator['allowempty'] = 'n';
1029                 if($validator['allowempty'] == 'y' && $field_value == '') {
1030                     //* Do nothing
1031                 } else {
1032                     //* Check if its a IPv4 or IPv6 address
1033                     if(isset($validator['separator']) && $validator['separator'] != '') {
1034                         //* When the field may contain several IP addresses, split them by the char defined as separator
1035                         $field_value_array = explode($validator['separator'], $field_value);
1036                     } else {
1037                         $field_value_array[] = $field_value;
1038                     }
1039                     foreach($field_value_array as $field_value) {
1040                         $field_value = trim($field_value);
1041                         if(function_exists('filter_var')) {
1042                             if(!filter_var($field_value, FILTER_VALIDATE_IP)) {
1043                                 $errmsg = $validator['errmsg'];
1044                                 if(isset($this->wordbook[$errmsg])) {
1045                                     $this->errorMessage .= $this->wordbook[$errmsg]."<br />\r\n";
1046                                 } else {
1047                                     $this->errorMessage .= $errmsg."<br />\r\n";
1048                                 }
1049                             }
1050                         } else {
1051                             //* Check content with regex, if we use php < 5.2
1052                             $ip_ok = 0;
1053                             if(preg_match("/^(\:\:([a-f0-9]{1,4}\:){0,6}?[a-f0-9]{0,4}|[a-f0-9]{1,4}(\:[a-f0-9]{1,4}){0,6}?\:\:|[a-f0-9]{1,4}(\:[a-f0-9]{1,4}){1,6}?\:\:([a-f0-9]{1,4}\:){1,6}?[a-f0-9]{1,4})(\/\d{1,3})?$/i", $field_value)){
1054                                 $ip_ok = 1;
1055                             }
1056                             if(preg_match("/^[0-9]{1,3}(\.)[0-9]{1,3}(\.)[0-9]{1,3}(\.)[0-9]{1,3}$/", $field_value)){
1057                                 $ip_ok = 1;
1058                             }
1059                             if($ip_ok == 0) {
1060                                 $errmsg = $validator['errmsg'];
1061                                 if(isset($this->wordbook[$errmsg])) {
1062                                     $this->errorMessage .= $this->wordbook[$errmsg]."<br />\r\n";
1063                                 } else {
1064                                     $this->errorMessage .= $errmsg."<br />\r\n";
1065                                 }
1066                             }
1067                         }
1068                     }
1069                 }
1070                 break;
1071             case 'RANGE':
1072                 //* Checks if the value is within the given range or above / below a value
1073                 //* Range examples: < 10 = ":10", between 2 and 10 = "2:10", above 5 = "5:".
1074                 $range_parts = explode(':', trim($validator['range']));
1075                 $ok = true;
1076                 if($range_parts[0] != '' && $field_value < $range_parts[0]) {
1077                     $ok = false;
1078                 }
1079                 if($range_parts[1] != '' && $field_value > $range_parts[1]) {
1080                     $ok = false;
1081                 }
1082                 if($ok != true) {
1083                     $errmsg = $validator['errmsg'];
1084                     if(isset($this->wordbook[$errmsg])) {
1085                         $this->errorMessage .= $this->wordbook[$errmsg]."<br />\r\n";
1086                     } else {
1087                         $this->errorMessage .= $errmsg."<br />\r\n";
1088                     }
1089                 }
1090                 unset($range_parts);
1091                 break;
1092             case 'CUSTOM':
1093                 // Calls a custom class to validate this record
1094                 if($validator['class'] != '' and $validator['function'] != '') {
1095                     $validator_class = $validator['class'];
1096                     $validator_function = $validator['function'];
1097                     $app->uses($validator_class);
1098                     $this->errorMessage .= $app->$validator_class->$validator_function($field_name, $field_value, $validator);
1099                 } else {
1100                     $this->errorMessage .= "Custom validator class or function is empty<br />\r\n";
1101                 }
1102                 break;
1103             default:
1104                 $this->errorMessage .= "Unknown Validator: ".$validator['type'];
1105                 break;
1106             }
2dadd2 1107
T 1108
7fe908 1109         }
2dadd2 1110
7fe908 1111         return true;
MC 1112     }
2dadd2 1113
T 1114
7fe908 1115     /**
MC 1116      * Create SQL statement
1117      *
1118      * @param record = Datensatz als Array
1119      * @param action = INSERT oder UPDATE
1120      * @param primary_id
1121      * @return record
1122      */
1123     function getSQL($record, $tab, $action = 'INSERT', $primary_id = 0, $sql_ext_where = '') {
2dadd2 1124
7fe908 1125         global $app;
35509d 1126         
TB 1127         $primary_id = $app->functions->intval($primary_id);
7fe908 1128
MC 1129         // If there are no data records on the tab, return empty sql string
1130         if(count($this->formDef['tabs'][$tab]['fields']) == 0) return '';
1131
1132         // checking permissions
1133         if($this->formDef['auth'] == 'yes' && $_SESSION["s"]["user"]["typ"] != 'admin') {
1134             if($action == "INSERT") {
1135                 if(!$this->checkPerm($primary_id, 'i')) $this->errorMessage .= "Insert denied.<br />\r\n";
1136             } else {
1137                 if(!$this->checkPerm($primary_id, 'u')) $this->errorMessage .= "Update denied.<br />\r\n";
1138             }
1139         }
1140
1141         $this->action = $action;
1142         $this->primary_id = $primary_id;
1143
1144         $record = $this->encode($record, $tab, true);
1145         $sql_insert_key = '';
1146         $sql_insert_val = '';
1147         $sql_update = '';
1148
1149         if(!is_array($this->formDef)) $app->error("Form definition not found.");
1150         if(!is_array($this->formDef['tabs'][$tab])) $app->error("The tab is empty or does not exist (TAB: $tab).");
1151
1152         // go trough all fields of the tab
1153         if(is_array($record)) {
1154             foreach($this->formDef['tabs'][$tab]['fields'] as $key => $field) {
1155                 // Wenn es kein leeres Passwortfeld ist
1156                 if (!($field['formtype'] == 'PASSWORD' and $record[$key] == '')) {
1157                     // Erzeuge Insert oder Update Quelltext
1158                     if($action == "INSERT") {
1159                         if($field['formtype'] == 'PASSWORD') {
1160                             $sql_insert_key .= "`$key`, ";
1161                             if($field['encryption'] == 'CRYPT') {
1162                                 $record[$key] = $app->auth->crypt_password(stripslashes($record[$key]));
1163                                 $sql_insert_val .= "'".$app->db->quote($record[$key])."', ";
1164                             } elseif ($field['encryption'] == 'MYSQL') {
1165                                 $tmp = $app->db->queryOneRecord("SELECT PASSWORD('".$app->db->quote(stripslashes($record[$key]))."') as `crypted`");
1166                                 $record[$key] = $tmp['crypted'];
1167                                 $sql_insert_val .= "'".$app->db->quote($record[$key])."', ";
1168                             } elseif ($field['encryption'] == 'CLEARTEXT') {
1169                                 $sql_insert_val .= "'".$app->db->quote($record[$key])."', ";
1170                             } else {
1171                                 $record[$key] = md5(stripslashes($record[$key]));
1172                                 $sql_insert_val .= "'".$app->db->quote($record[$key])."', ";
1173                             }
1174
1175                         } elseif ($field['formtype'] == 'CHECKBOX') {
1176                             $sql_insert_key .= "`$key`, ";
1177                             if($record[$key] == '') {
1178                                 // if a checkbox is not set, we set it to the unchecked value
1179                                 $sql_insert_val .= "'".$field['value'][0]."', ";
1180                                 $record[$key] = $field['value'][0];
1181                             } else {
1182                                 $sql_insert_val .= "'".$record[$key]."', ";
1183                             }
1184                         } else {
1185                             $sql_insert_key .= "`$key`, ";
1186                             $sql_insert_val .= "'".$record[$key]."', ";
1187                         }
1188                     } else {
1189                         if($field['formtype'] == 'PASSWORD') {
1190                             if(isset($field['encryption']) && $field['encryption'] == 'CRYPT') {
1191                                 $record[$key] = $app->auth->crypt_password(stripslashes($record[$key]));
1192                                 $sql_update .= "`$key` = '".$app->db->quote($record[$key])."', ";
1193                             } elseif (isset($field['encryption']) && $field['encryption'] == 'MYSQL') {
1194                                 $tmp = $app->db->queryOneRecord("SELECT PASSWORD('".$app->db->quote(stripslashes($record[$key]))."') as `crypted`");
1195                                 $record[$key] = $tmp['crypted'];
1196                                 $sql_update .= "`$key` = '".$app->db->quote($record[$key])."', ";
1197                             } elseif (isset($field['encryption']) && $field['encryption'] == 'CLEARTEXT') {
1198                                 $sql_update .= "`$key` = '".$app->db->quote($record[$key])."', ";
1199                             } else {
1200                                 $record[$key] = md5(stripslashes($record[$key]));
1201                                 $sql_update .= "`$key` = '".$app->db->quote($record[$key])."', ";
1202                             }
1203
1204                         } elseif ($field['formtype'] == 'CHECKBOX') {
1205                             if($record[$key] == '') {
1206                                 // if a checkbox is not set, we set it to the unchecked value
1207                                 $sql_update .= "`$key` = '".$field['value'][0]."', ";
1208                                 $record[$key] = $field['value'][0];
1209                             } else {
1210                                 $sql_update .= "`$key` = '".$record[$key]."', ";
1211                             }
1212                         } else {
1213                             $sql_update .= "`$key` = '".$record[$key]."', ";
1214                         }
1215                     }
1216                 } else {
1217                     // we unset the password filed, if empty to tell the datalog function
1218                     // that the password has not been changed
1219                     unset($record[$key]);
1220                 }
1221             }
1222         }
1223
1224
1225         // Add backticks for incomplete table names
1226         if(stristr($this->formDef['db_table'], '.')) {
1227             $escape = '';
1228         } else {
1229             $escape = '`';
1230         }
1231
1232
1233         if($action == "INSERT") {
1234             if($this->formDef['auth'] == 'yes') {
1235                 // Set user and group
1236                 $sql_insert_key .= "`sys_userid`, ";
1237                 $sql_insert_val .= ($this->formDef["auth_preset"]["userid"] > 0)?"'".$this->formDef["auth_preset"]["userid"]."', ":"'".$_SESSION["s"]["user"]["userid"]."', ";
1238                 $sql_insert_key .= "`sys_groupid`, ";
1239                 $sql_insert_val .= ($this->formDef["auth_preset"]["groupid"] > 0)?"'".$this->formDef["auth_preset"]["groupid"]."', ":"'".$_SESSION["s"]["user"]["default_group"]."', ";
1240                 $sql_insert_key .= "`sys_perm_user`, ";
1241                 $sql_insert_val .= "'".$this->formDef["auth_preset"]["perm_user"]."', ";
1242                 $sql_insert_key .= "`sys_perm_group`, ";
1243                 $sql_insert_val .= "'".$this->formDef["auth_preset"]["perm_group"]."', ";
1244                 $sql_insert_key .= "`sys_perm_other`, ";
1245                 $sql_insert_val .= "'".$this->formDef["auth_preset"]["perm_other"]."', ";
1246             }
1247             $sql_insert_key = substr($sql_insert_key, 0, -2);
1248             $sql_insert_val = substr($sql_insert_val, 0, -2);
1249             $sql = "INSERT INTO ".$escape.$this->formDef['db_table'].$escape." ($sql_insert_key) VALUES ($sql_insert_val)";
1250         } else {
1251             if($this->formDef['auth'] == 'yes') {
1252                 if($primary_id != 0) {
1253                     $sql_update = substr($sql_update, 0, -2);
1254                     $sql = "UPDATE ".$escape.$this->formDef['db_table'].$escape." SET ".$sql_update." WHERE ".$this->getAuthSQL('u')." AND ".$this->formDef['db_table_idx']." = ".$primary_id;
1255                     if($sql_ext_where != '') $sql .= " and ".$sql_ext_where;
1256                 } else {
1257                     $app->error("Primary ID fehlt!");
1258                 }
1259             } else {
1260                 if($primary_id != 0) {
1261                     $sql_update = substr($sql_update, 0, -2);
1262                     $sql = "UPDATE ".$escape.$this->formDef['db_table'].$escape." SET ".$sql_update." WHERE ".$this->formDef['db_table_idx']." = ".$primary_id;
1263                     if($sql_ext_where != '') $sql .= " and ".$sql_ext_where;
1264                 } else {
1265                     $app->error("Primary ID fehlt!");
1266                 }
1267             }
1268             //* return a empty string if there is nothing to update
1269             if(trim($sql_update) == '') $sql = '';
1270         }
1271
1272         return $sql;
1273     }
1274
1275
1276     /**
1277      * Debugging arrays.
1278      *
1279      * @param array_data
1280      */
1281     function dbg($array_data) {
1282
1283         echo "<pre>";
1284         print_r($array_data);
1285         echo "</pre>";
1286
1287     }
1288
1289
1290     function showForm() {
1291         global $app, $conf;
1292
1293         if(!is_array($this->formDef)) die("Form Definition wurde nicht geladen.");
1294
1295         $active_tab = $this->getNextTab();
1296
1297         // go trough the tabs
1298         foreach( $this->formDef["tabs"] as $key => $tab) {
1299
1300             $tab['name'] = $key;
40dd9f 1301             // Translate the title of the tab
T 1302             $tab['title'] = $this->lng($tab['title']);
2dadd2 1303
7fe908 1304             if($tab['name'] == $active_tab) {
2dadd2 1305
7fe908 1306                 // If module is set, then set the template path relative to the module..
MC 1307                 if($this->module != '') $tab["template"] = "../".$this->module."/".$tab["template"];
2dadd2 1308
7fe908 1309                 // Generate the template if it does not exist yet.
2dadd2 1310
T 1311
1312
7fe908 1313                 if(!is_file($tab["template"])) {
MC 1314                     $app->uses('tform_tpl_generator');
1315                     $app->tform_tpl_generator->buildHTML($this->formDef, $tab['name']);
2dadd2 1316                 }
7fe908 1317                 $app->tpl->setVar('readonly_tab', (isset($tab['readonly']) && $tab['readonly'] == true));
MC 1318                 $app->tpl->setInclude('content_tpl', $tab["template"]);
1319                 $tab["active"] = 1;
1320                 $_SESSION["s"]["form"]["tab"] = $tab['name'];
1321             } else {
1322                 $tab["active"] = 0;
1323             }
2dadd2 1324
7fe908 1325             // Unset unused variables.
MC 1326             unset($tab["fields"]);
1327             unset($tab["plugins"]);
1328
1329             $frmTab[] = $tab;
1330         }
1331
1332         // setting form tabs
1333         $app->tpl->setLoop("formTab", $frmTab);
1334
1335         // Set form action
1336         $app->tpl->setVar('form_action', $this->formDef["action"]);
1337         $app->tpl->setVar('form_active_tab', $active_tab);
1338
1339         // Set form title
1340         $form_hint = $this->lng($this->formDef["title"]);
1341         if($this->formDef["description"] != '') $form_hint .= '<div class="pageForm_description">'.$this->lng($this->formDef["description"]).'</div>';
1342         $app->tpl->setVar('form_hint', $form_hint);
1343
1344         // Set Wordbook for this form
1345
1346         $app->tpl->setVar($this->wordbook);
1347     }
1348
1349     function getDataRecord($primary_id) {
1350         global $app;
1351         $escape = '`';
35509d 1352         $primary_id = $app->functions->intval($primary_id);
7fe908 1353         $sql = "SELECT * FROM ".$escape.$this->formDef['db_table'].$escape." WHERE ".$this->formDef['db_table_idx']." = ".$primary_id." AND ".$this->getAuthSQL('r', $this->formDef['db_table']);
MC 1354         return $app->db->queryOneRecord($sql);
1355     }
1356
1357
1358     function datalogSave($action, $primary_id, $record_old, $record_new) {
1359         global $app, $conf;
1360
1361         $app->db->datalogSave($this->formDef['db_table'], $action, $this->formDef['db_table_idx'], $primary_id, $record_old, $record_new);
1362         return true;
1363     }
1364
1365     function getAuthSQL($perm, $table = '') {
35509d 1366         global $app;
TB 1367         
1368         $perm = $app->db->quote($perm);
1369         $table = $app->db->quote($table);
1370         
f798aa 1371         if($_SESSION["s"]["user"]["typ"] == 'admin' || $_SESSION['s']['user']['mailuser_id'] > 0) {
7fe908 1372             return '1';
MC 1373         } else {
1374             if ($table != ''){
1375                 $table = ' ' . $table . '.';
1376             }
1377             $groups = ( $_SESSION["s"]["user"]["groups"] ) ? $_SESSION["s"]["user"]["groups"] : 0;
1378             $sql = '(';
1379             $sql .= "(" . $table . "sys_userid = ".$_SESSION["s"]["user"]["userid"]." AND " . $table . "sys_perm_user like '%$perm%') OR  ";
1380             $sql .= "(" . $table . "sys_groupid IN (".$groups.") AND " . $table ."sys_perm_group like '%$perm%') OR ";
1381             $sql .= $table . "sys_perm_other like '%$perm%'";
1382             $sql .= ')';
1383
1384             return $sql;
1385         }
1386     }
1387
1388     /*
992797 1389         This function checks if a user has the parmissions $perm for the data record with the ID $record_id
MC 1390         If record_id = 0, the the permissions are tested against the defaults of the form file.
1391         */
7fe908 1392     function checkPerm($record_id, $perm) {
MC 1393         global $app;
2dadd2 1394
35509d 1395         $record_id = $app->functions->intval($record_id);
7fe908 1396         if($record_id > 0) {
2dadd2 1397             // Add backticks for incomplete table names.
7fe908 1398             if(stristr($this->formDef['db_table'], '.')) {
MC 1399                 $escape = '';
1400             } else {
1401                 $escape = '`';
1402             }
1403
1404             $sql = "SELECT ".$this->formDef['db_table_idx']." FROM ".$escape.$this->formDef['db_table'].$escape." WHERE ".$this->formDef['db_table_idx']." = ".$record_id." AND ".$this->getAuthSQL($perm);
1405             if($record = $app->db->queryOneRecord($sql)) {
2dadd2 1406                 return true;
T 1407             } else {
1408                 return false;
1409             }
7fe908 1410         } else {
MC 1411             $result = false;
1412             if(@$this->formDef["auth_preset"]["userid"] == $_SESSION["s"]["user"]["userid"] && stristr($perm, $this->formDef["auth_preset"]["perm_user"])) $result = true;
1413             if(@$this->formDef["auth_preset"]["groupid"] == $_SESSION["s"]["user"]["groupid"] && stristr($perm, $this->formDef["auth_preset"]["perm_group"])) $result = true;
1414             if(@stristr($this->formDef["auth_preset"]["perm_other"], $perm)) $result = true;
1415
1416             // if preset == 0, everyone can insert a record of this type
1417             if($this->formDef["auth_preset"]["userid"] == 0 and $this->formDef["auth_preset"]["groupid"] == 0 and (@stristr($this->formDef["auth_preset"]["perm_user"], $perm) or @stristr($this->formDef["auth_preset"]["perm_group"], $perm))) $result = true;
1418
1419             return $result;
1420
2dadd2 1421         }
7fe908 1422
MC 1423     }
1424
1425     function getNextTab() {
1426         // Which tab is shown
1427         if($this->errorMessage == '') {
1428             // If there is no error
1429             if(isset($_REQUEST["next_tab"]) && $_REQUEST["next_tab"] != '') {
1430                 // If the next tab is known
1431                 $active_tab = $_REQUEST["next_tab"];
1432             } else {
1433                 // else use the default tab
1434                 $active_tab = $this->formDef['tab_default'];
1435             }
1436         } else {
1437             // Show the same tab again in case of an error
1438             $active_tab = $_SESSION["s"]["form"]["tab"];
1439         }
1440
1441         return $active_tab;
1442     }
1443
1444     function getCurrentTab() {
1445         return $_SESSION["s"]["form"]["tab"];
1446     }
1447
1448     function isReadonlyTab($tab, $primary_id) {
1449         global $app, $conf;
1450
1451         // Add backticks for incomplete table names.
1452         if(stristr($this->formDef['db_table'], '.')) {
1453             $escape = '';
1454         } else {
1455             $escape = '`';
1456         }
1457
1458         $sql = "SELECT sys_userid FROM ".$escape.$this->formDef['db_table'].$escape." WHERE ".$this->formDef['db_table_idx']." = ".$primary_id;
1459         $record = $app->db->queryOneRecord($sql);
1460
1461         // return true if the readonly flag of the form is set and the current loggedin user is not the owner of the record.
1462         if(isset($this->formDef['tabs'][$tab]['readonly']) && $this->formDef['tabs'][$tab]['readonly'] == true && $record['sys_userid'] != $_SESSION["s"]["user"]["userid"]) {
1463             return true;
1464         } else {
1465             return false;
1466         }
1467     }
1468
1469
1470     // translation function for forms, tries the form wordbook first and if this fails, it tries the global wordbook
1471     function lng($msg) {
1472         global $app, $conf;
1473
1474         if(isset($this->wordbook[$msg])) {
1475             return $this->wordbook[$msg];
1476         } else {
1477             return $app->lng($msg);
1478         }
1479
1480     }
1481
1482     function checkClientLimit($limit_name, $sql_where = '') {
1483         global $app;
1484
1485         $check_passed = true;
1486         $limit_name = $app->db->quote($limit_name);
1487         if($limit_name == '') $app->error('Limit name missing in function checkClientLimit.');
1488
1489         // Get the limits of the client that is currently logged in
35509d 1490         $client_group_id = $app->functions->intval($_SESSION["s"]["user"]["default_group"]);
7fe908 1491         $client = $app->db->queryOneRecord("SELECT $limit_name as number, parent_client_id FROM sys_group, client WHERE sys_group.client_id = client.client_id and sys_group.groupid = $client_group_id");
MC 1492
1493         // Check if the user may add another item
1494         if($client["number"] >= 0) {
1495             $sql = "SELECT count(".$this->formDef['db_table_idx'].") as number FROM ".$this->formDef['db_table']." WHERE ".$this->getAuthSQL('u');
1496             if($sql_where != '') $sql .= ' and '.$sql_where;
1497             $tmp = $app->db->queryOneRecord($sql);
1498             if($tmp["number"] >= $client["number"]) $check_passed = false;
1499         }
1500
1501         return $check_passed;
1502     }
1503
1504     function checkResellerLimit($limit_name, $sql_where = '') {
1505         global $app;
1506
1507         $check_passed = true;
1508         $limit_name = $app->db->quote($limit_name);
1509         if($limit_name == '') $app->error('Limit name missing in function checkClientLimit.');
1510
1511         // Get the limits of the client that is currently logged in
35509d 1512         $client_group_id = $app->functions->intval($_SESSION["s"]["user"]["default_group"]);
7fe908 1513         $client = $app->db->queryOneRecord("SELECT parent_client_id FROM sys_group, client WHERE sys_group.client_id = client.client_id and sys_group.groupid = $client_group_id");
MC 1514
1515         //* If the client belongs to a reseller, we will check against the reseller Limit too
1516         if($client['parent_client_id'] != 0) {
1517
1518             //* first we need to know the groups of this reseller
1519             $tmp = $app->db->queryOneRecord("SELECT userid, groups FROM sys_user WHERE client_id = ".$client['parent_client_id']);
1520             $reseller_groups = $tmp["groups"];
1521             $reseller_userid = $tmp["userid"];
1522
1523             // Get the limits of the reseller of the logged in client
3cebc3 1524             $client_group_id = $_SESSION["s"]["user"]["default_group"];
7fe908 1525             $reseller = $app->db->queryOneRecord("SELECT $limit_name as number FROM client WHERE client_id = ".$client['parent_client_id']);
MC 1526
3cebc3 1527             // Check if the user may add another item
7fe908 1528             if($reseller["number"] >= 0) {
MC 1529                 $sql = "SELECT count(".$this->formDef['db_table_idx'].") as number FROM ".$this->formDef['db_table']." WHERE (sys_groupid IN (".$reseller_groups.") or sys_userid = ".$reseller_userid.")";
3cebc3 1530                 if($sql_where != '') $sql .= ' and '.$sql_where;
T 1531                 $tmp = $app->db->queryOneRecord($sql);
7fe908 1532                 if($tmp["number"] >= $reseller["number"]) $check_passed = false;
3cebc3 1533             }
T 1534         }
7fe908 1535
MC 1536         return $check_passed;
1537     }
1538
1539     //* get the difference record of two arrays
1540     function getDiffRecord($record_old, $record_new) {
1541
1542         if(is_array($record_new) && count($record_new) > 0) {
11b3da 1543             foreach($record_new as $key => $val) {
T 1544                 if(@$record_old[$key] != $val) {
1545                     // Record has changed
7fe908 1546                     $diffrec[$key] = array( 'old' => @$record_old[$key],
MC 1547                         'new' => $val);
11b3da 1548                 }
7fe908 1549             }
MC 1550         } elseif(is_array($record_old)) {
1551             foreach($record_old as $key => $val) {
1552                 if($record_new[$key] != $val) {
1553                     // Record has changed
1554                     $diffrec[$key] = array( 'new' => $record_new[$key],
1555                         'old' => $val);
11b3da 1556                 }
7fe908 1557             }
11b3da 1558         }
7fe908 1559         return $diffrec;
2dadd2 1560
7fe908 1561     }
MC 1562
1563
1564
1565
1566
1567     /**
1568      * Generate HTML for DATETIME fields.
1569      *
1570      * @access private
1571      * @param string $form_element Name of the form element.
1572      * @param string $default_value Selected value for fields.
1573      * @param bool $display_secons Include seconds selection.
1574      * @return string HTML
1575      */
1576     function _getDateTimeHTML($form_element, $default_value, $display_seconds=false)
1577     {
eebe76 1578         $_datetime = ($default_value && $default_value != '0000-00-00 00:00:00' ? strtotime($default_value) : false);
7fe908 1579         $_showdate = ($_datetime === false) ? false : true;
MC 1580
1581         $dselect = array('day', 'month', 'year', 'hour', 'minute');
1582         if ($display_seconds === true) {
1583             $dselect[] = 'second';
1584         }
1585
1586         $out = '';
1587
1588         foreach ($dselect as $dt_element)
1589         {
1590             $dt_options = array();
1591             $dt_space = 1;
1592
1593             switch ($dt_element) {
1594             case 'day':
1595                 for ($i = 1; $i <= 31; $i++) {
1596                     $dt_options[] = array('name' =>  sprintf('%02d', $i),
1597                         'value' => sprintf('%d', $i));
75ae20 1598                 }
7fe908 1599                 $selected_value = date('d', $_datetime);
MC 1600                 break;
1601
1602             case 'month':
1603                 for ($i = 1; $i <= 12; $i++) {
1604                     $dt_options[] = array('name' => strftime('%b', mktime(0, 0, 0, $i, 1, 2000)),
1605                         'value' => strftime('%m', mktime(0, 0, 0, $i, 1, 2000)));
1606                 }
1607                 $selected_value = date('n', $_datetime);
1608                 break;
1609
1610             case 'year':
1611                 $start_year = strftime("%Y");
1612                 $years = range((int)$start_year, (int)($start_year+3));
1613
1614                 foreach ($years as $year) {
1615                     $dt_options[] = array('name' => $year,
1616                         'value' => $year);
1617                 }
1618                 $selected_value = date('Y', $_datetime);
1619                 $dt_space = 2;
1620                 break;
1621
1622             case 'hour':
1623                 foreach(range(0, 23) as $hour) {
1624                     $dt_options[] = array('name' =>  sprintf('%02d', $hour),
1625                         'value' => sprintf('%d', $hour));
1626                 }
1627                 $selected_value = date('G', $_datetime);
1628                 break;
1629
1630             case 'minute':
1631                 foreach(range(0, 59) as $minute) {
1632                     if (($minute % 5) == 0) {
1633                         $dt_options[] = array('name' =>  sprintf('%02d', $minute),
1634                             'value' => sprintf('%d', $minute));
75ae20 1635                     }
W 1636                 }
7fe908 1637                 $selected_value = (int)floor(date('i', $_datetime));
MC 1638                 break;
1639
1640             case 'second':
1641                 foreach(range(0, 59) as $second) {
1642                     $dt_options[] = array('name' =>  sprintf('%02d', $second),
1643                         'value' => sprintf('%d', $second));
1644                 }
1645                 $selected_value = (int)floor(date('s', $_datetime));
1646                 break;
75ae20 1647             }
7fe908 1648
MC 1649             $out .= "<select name=\"".$form_element."[$dt_element]\" id=\"".$form_element."_$dt_element\" class=\"selectInput\" style=\"width: auto; float: none;\">";
1650             if (!$_showdate) {
1651                 $out .= "<option value=\"-\" selected=\"selected\">--</option>" . PHP_EOL;
1652             } else {
1653                 $out .= "<option value=\"-\">--</option>" . PHP_EOL;
1654             }
1655
1656             foreach ($dt_options as $dt_opt) {
1657                 if ( $_showdate && ($selected_value == $dt_opt['value']) ) {
1658                     $out .= "<option value=\"{$dt_opt['value']}\" selected=\"selected\">{$dt_opt['name']}</option>" . PHP_EOL;
1659                 } else {
1660                     $out .= "<option value=\"{$dt_opt['value']}\">{$dt_opt['name']}</option>" . PHP_EOL;
1661                 }
1662             }
1663
1664             $out .= '</select>' . str_repeat('&nbsp;', $dt_space);
75ae20 1665         }
7fe908 1666
MC 1667         return $out;
1668     }
1669
2dadd2 1670 }
T 1671
d7ef36 1672 ?>