Till Brehm
2015-06-03 5af0cfd99a13fda9afad3380b0c50a3428acd299
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
5af0cf 389         /*$_csrf_id = uniqid($this->formDef['name'] . '_');
582cbf 390         $_csrf_value = sha1(uniqid(microtime(true), true));
MC 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
5af0cf 395         */
TB 396         $csrf_token = $app->auth->csrf_token_get($this->formDef['name']);
397         $_csrf_id = $csrf_token['csrf_id'];
398         $_csrf_value = $csrf_token['csrf_key'];
399         
582cbf 400         $this->formDef['tabs'][$tab]['fields']['_csrf_id'] = array(
MC 401             'datatype' => 'VARCHAR',
402             'formtype' => 'TEXT',
403             'default' => $_csrf_id,
404             'value' => $_csrf_id
405         );
406         $this->formDef['tabs'][$tab]['fields']['_csrf_key'] = array(
407             'datatype' => 'VARCHAR',
408             'formtype' => 'TEXT',
409             'default' => $_csrf_value,
410             'value' => $_csrf_value
411         );
412         $record['_csrf_id'] = $_csrf_id;
413         $record['_csrf_key'] = $_csrf_value;
414         /* CSRF PROTECTION */
415         
7fe908 416         $new_record = array();
MC 417         if($action == 'EDIT') {
418             $record = $this->decode($record, $tab);
419             if(is_array($record)) {
420                 foreach($this->formDef['tabs'][$tab]['fields'] as $key => $field) {
421
422                     if(isset($record[$key])) {
423                         $val = $record[$key];
67c4b3 424                     } else {
7fe908 425                         $val = '';
67c4b3 426                     }
2dadd2 427
7fe908 428                     // If Datasource is set, get the data from there
MC 429                     if(isset($field['datasource']) && is_array($field['datasource'])) {
430                         if(is_array($field["value"])) {
431                             //$field["value"] = array_merge($field["value"],$this->getDatasourceData($field, $record));
432                             $field["value"] = $app->functions->array_merge($field["value"], $this->getDatasourceData($field, $record));
433                         } else {
434                             $field["value"] = $this->getDatasourceData($field, $record);
435                         }
436                     }
2dadd2 437
7fe908 438                     // If a limitation for the values is set
MC 439                     if(isset($field['valuelimit']) && is_array($field["value"])) {
440                         $field["value"] = $this->applyValueLimit($field['valuelimit'], $field["value"]);
441                     }
2dadd2 442
7fe908 443                     switch ($field['formtype']) {
MC 444                     case 'SELECT':
445                         $out = '';
446                         if(is_array($field['value'])) {
447                             foreach($field['value'] as $k => $v) {
448                                 $selected = ($k == $val)?' SELECTED':'';
449                                 if(!empty($this->wordbook[$v]))
450                                     $v = $this->wordbook[$v];
451                                 $out .= "<option value='$k'$selected>".$this->lng($v)."</option>\r\n";
452                             }
453                         }
454                         $new_record[$key] = $out;
455                         break;
456                     case 'MULTIPLE':
457                         if(is_array($field['value'])) {
2dadd2 458
7fe908 459                             // Split
MC 460                             $vals = explode($field['separator'], $val);
2dadd2 461
7fe908 462                             // write HTML
MC 463                             $out = '';
464                             foreach($field['value'] as $k => $v) {
2dadd2 465
7fe908 466                                 $selected = '';
MC 467                                 foreach($vals as $tvl) {
468                                     if(trim($tvl) == trim($k)) $selected = ' SELECTED';
2dadd2 469                                 }
T 470
7fe908 471                                 $out .= "<option value='$k'$selected>$v</option>\r\n";
MC 472                             }
473                         }
474                         $new_record[$key] = $out;
475                         break;
2dadd2 476
7fe908 477                     case 'PASSWORD':
MC 478                         $new_record[$key] = '';
479                         break;
2dadd2 480
7fe908 481                     case 'CHECKBOX':
MC 482                         $checked = ($val == $field['value'][1])?' CHECKED':'';
483                         $new_record[$key] = "<input name=\"".$key."\" id=\"".$key."\" value=\"".$field['value'][1]."\" type=\"checkbox\" $checked />\r\n";
484                         break;
2dadd2 485
7fe908 486                     case 'CHECKBOXARRAY':
MC 487                         if(is_array($field['value'])) {
2dadd2 488
7fe908 489                             // aufsplitten ergebnisse
MC 490                             $vals = explode($field['separator'], $val);
2dadd2 491
7fe908 492                             // HTML schreiben
MC 493                             $out = '';
494                             $elementNo = 0;
495                             foreach($field['value'] as $k => $v) {
2dadd2 496
7fe908 497                                 $checked = '';
MC 498                                 foreach($vals as $tvl) {
499                                     if(trim($tvl) == trim($k)) $checked = ' CHECKED';
d370bb 500                                 }
7fe908 501                                 // $out .= "<label for=\"".$key."[]\" class=\"inlineLabel\"><input name=\"".$key."[]\" id=\"".$key."[]\" value=\"$k\" type=\"checkbox\" $checked /> $v</label>\r\n";
MC 502                                 $out .= "<label for=\"".$key.$elementNo."\" class=\"inlineLabel\"><input name=\"".$key."[]\" id=\"".$key.$elementNo."\" value=\"$k\" type=\"checkbox\" $checked /> $v</label><br/>\r\n";
503                                 $elementNo++;
504                             }
505                         }
506                         $new_record[$key] = $out;
507                         break;
2dadd2 508
7fe908 509                     case 'RADIO':
MC 510                         if(is_array($field['value'])) {
2dadd2 511
7fe908 512                             // HTML schreiben
MC 513                             $out = '';
514                             $elementNo = 0;
515                             foreach($field['value'] as $k => $v) {
516                                 $checked = ($k == $val)?' CHECKED':'';
517                                 //$out .= "<label for=\"".$key."[]\" class=\"inlineLabel\"><input name=\"".$key."[]\" id=\"".$key."[]\" value=\"$k\" type=\"radio\" $checked/> $v</label>\r\n";
518                                 $out .= "<label for=\"".$key.$elementNo."\" class=\"inlineLabel\"><input name=\"".$key."[]\" id=\"".$key.$elementNo."\" value=\"$k\" type=\"radio\" $checked/> $v </label>\r\n";
519                                 $elementNo++;
520                             }
521                         }
522                         $new_record[$key] = $out;
523                         break;
2332b2 524
7fe908 525                     case 'DATETIME':
MC 526                         if (strtotime($val) !== false) {
527                             $dt_value = $val;
528                         } elseif ( isset($field['default']) && (strtotime($field['default']) !== false) ) {
529                             $dt_value = $field['default'];
530                         } else {
531                             $dt_value = 0;
532                         }
d370bb 533
7fe908 534                         $display_seconds = (isset($field['display_seconds']) && $field['display_seconds'] == true) ? true : false;
MC 535
536                         $new_record[$key] = $this->_getDateTimeHTML($key, $dt_value, $display_seconds);
d370bb 537                         break;
7fe908 538
MC 539                     default:
540                         if(isset($record[$key])) {
541                             $new_record[$key] = htmlspecialchars($record[$key]);
542                         } else {
543                             $new_record[$key] = '';
544                         }
d370bb 545                     }
T 546                 }
547             }
7fe908 548         } else {
MC 549             // Action: NEW
550             foreach($this->formDef['tabs'][$tab]['fields'] as $key => $field) {
2dadd2 551
7fe908 552                 // If Datasource is set, get the data from there
MC 553                 if(@is_array($field['datasource'])) {
554                     if(is_array($field["value"])) {
555                         $field["value"] = $app->functions->array_merge($field["value"], $this->getDatasourceData($field, $record));
556                     } else {
557                         $field["value"] = $this->getDatasourceData($field, $record);
558                     }
559                 }
2dadd2 560
7fe908 561                 // If a limitation for the values is set
MC 562                 if(isset($field['valuelimit']) && is_array($field["value"])) {
563                     $field["value"] = $this->applyValueLimit($field['valuelimit'], $field["value"]);
564                 }
2dadd2 565
7fe908 566                 switch ($field['formtype']) {
MC 567                 case 'SELECT':
568                     if(is_array($field['value'])) {
569                         $out = '';
570                         foreach($field['value'] as $k => $v) {
571                             $selected = ($k == $field["default"])?' SELECTED':'';
572                             $out .= "<option value='$k'$selected>".$this->lng($v)."</option>\r\n";
573                         }
574                     }
575                     if(isset($out)) $new_record[$key] = $out;
576                     break;
577                 case 'MULTIPLE':
578                     if(is_array($field['value'])) {
2dadd2 579
7fe908 580                         // aufsplitten ergebnisse
MC 581                         $vals = explode($field['separator'], $val);
582
583                         // HTML schreiben
584                         $out = '';
585                         foreach($field['value'] as $k => $v) {
586
587                             $out .= "<option value='$k'>$v</option>\r\n";
588                         }
589                     }
590                     $new_record[$key] = $out;
591                     break;
592
593                 case 'PASSWORD':
594                     //$new_record[$key] = '';
595                     $new_record[$key] = htmlspecialchars($field['default']);
596                     break;
597
598                 case 'CHECKBOX':
599                     // $checked = (empty($field["default"]))?'':' CHECKED';
600                     $checked = ($field["default"] == $field['value'][1])?' CHECKED':'';
601                     $new_record[$key] = "<input name=\"".$key."\" id=\"".$key."\" value=\"".$field['value'][1]."\" type=\"checkbox\" $checked />\r\n";
602                     break;
603
604                 case 'CHECKBOXARRAY':
605                     if(is_array($field['value'])) {
606
607                         // aufsplitten ergebnisse
608                         $vals = explode($field['separator'], $field["default"]);
609
610                         // HTML schreiben
611                         $out = '';
612                         $elementNo = 0;
613                         foreach($field['value'] as $k => $v) {
614
615                             $checked = '';
616                             foreach($vals as $tvl) {
617                                 if(trim($tvl) == trim($k)) $checked = ' CHECKED';
618                             }
619                             // $out .= "<label for=\"".$key."[]\" class=\"inlineLabel\"><input name=\"".$key."[]\" id=\"".$key."[]\" value=\"$k\" type=\"checkbox\" $checked /> $v</label>\r\n";
620                             $out .= "<label for=\"".$key.$elementNo."\" class=\"inlineLabel\"><input name=\"".$key."[]\" id=\"".$key.$elementNo."\" value=\"$k\" type=\"checkbox\" $checked /> $v</label> &nbsp;\r\n";
621                             $elementNo++;
622                         }
623                     }
624                     $new_record[$key] = $out;
625                     break;
626
627                 case 'RADIO':
628                     if(is_array($field['value'])) {
629
630                         // HTML schreiben
631                         $out = '';
632                         $elementNo = 0;
633                         foreach($field['value'] as $k => $v) {
634                             $checked = ($k == $field["default"])?' CHECKED':'';
635                             //$out .= "<label for=\"".$key."[]\" class=\"inlineLabel\"><input name=\"".$key."[]\" id=\"".$key."[]\" value=\"$k\" type=\"radio\" $checked/> $v</label>\r\n";
636                             $out .= "<label for=\"".$key.$elementNo."\" class=\"inlineLabel\"><input name=\"".$key."[]\" id=\"".$key.$elementNo."\" value=\"$k\" type=\"radio\" $checked/> $v</label>\r\n";
637                             $elementNo++;
638                         }
639                     }
640                     $new_record[$key] = $out;
641                     break;
642
643                 case 'DATETIME':
644                     $dt_value = (isset($field['default'])) ? $field['default'] : 0;
645                     $display_seconds = (isset($field['display_seconds']) && $field['display_seconds'] == true) ? true : false;
646
647                     $new_record[$key] = $this->_getDateTimeHTML($key, $dt_value, $display_seconds);
648                     break;
649
650                 default:
651                     $new_record[$key] = htmlspecialchars($field['default']);
652                 }
653             }
654
655         }
656
657         if($this->debug == 1) $this->dbg($new_record);
658
659         return $new_record;
660     }
661
662
663     /**
664      * Rewrite the record data to be stored in the database
665      * and check values with regular expressions.
666      *
667      * @param record = Datensatz als Array
668      * @return record
669      */
670     function encode($record, $tab, $dbencode = true) {
671         global $app;
672
673         if(!is_array($this->formDef['tabs'][$tab])) $app->error("Tab is empty or does not exist (TAB: $tab).");
674         //$this->errorMessage = '';
582cbf 675         
MC 676         /* CSRF PROTECTION */
5af0cf 677         
582cbf 678         if(isset($_POST) && is_array($_POST)) {
MC 679             $_csrf_valid = false;
680             if(isset($_POST['_csrf_id']) && isset($_POST['_csrf_key'])) {
681                 $_csrf_id = trim($_POST['_csrf_id']);
682                 $_csrf_key = trim($_POST['_csrf_key']);
683                 if(isset($_SESSION['_csrf']) && isset($_SESSION['_csrf'][$_csrf_id]) && isset($_SESSION['_csrf_timeout']) && isset($_SESSION['_csrf_timeout'][$_csrf_id])) {
684                     if($_SESSION['_csrf'][$_csrf_id] === $_csrf_key && $_SESSION['_csrf_timeout'] >= time()) $_csrf_valid = true;
685                 }
686             }
687             if($_csrf_valid !== true) {
688                 $app->log('CSRF attempt blocked. Referer: ' . (isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : 'unknown'), LOGLEVEL_WARN);
e8f943 689                 $errmsg = 'err_csrf_attempt_blocked';
MC 690                 $this->errorMessage .= ($api == true ? $errmsg : $this->wordbook[$errmsg]."<br />") . "\r\n";
582cbf 691                 unset($_POST);
MC 692                 unset($record);
693             }
f3cc2c 694             $_SESSION['_csrf'][$_csrf_id] = null;
MC 695             $_SESSION['_csrf_timeout'][$_csrf_id] = null;
582cbf 696             unset($_SESSION['_csrf'][$_csrf_id]);
MC 697             unset($_SESSION['_csrf_timeout'][$_csrf_id]);
698             
699             if(isset($_SESSION['_csrf_timeout']) && is_array($_SESSION['_csrf_timeout'])) {
700                 $to_unset = array();
701                 foreach($_SESSION['_csrf_timeout'] as $_csrf_id => $timeout) {
702                     if($timeout < time()) $to_unset[] = $_csrf_id;
703                 }
704                 foreach($to_unset as $_csrf_id) {
f3cc2c 705                     $_SESSION['_csrf'][$_csrf_id] = null;
MC 706                     $_SESSION['_csrf_timeout'][$_csrf_id] = null;
582cbf 707                     unset($_SESSION['_csrf'][$_csrf_id]);
MC 708                     unset($_SESSION['_csrf_timeout'][$_csrf_id]);
709                 }
710                 unset($to_unset);
711             }
712         }
713         /* CSRF PROTECTION */
714         
715         $new_record = array();
7fe908 716         if(is_array($record)) {
MC 717             foreach($this->formDef['tabs'][$tab]['fields'] as $key => $field) {
718
719                 //* Apply filter to record value
720                 if(isset($field['filters']) && is_array($field['filters'])) {
721                     $record[$key] = $this->filterField($key, (isset($record[$key]))?$record[$key]:'', $field['filters'], 'SAVE');
722                 }
723                 //* Validate record value
724                 if(isset($field['validators']) && is_array($field['validators'])) {
725                     $this->validateField($key, (isset($record[$key]))?$record[$key]:'', $field['validators']);
726                 }
727
728                 switch ($field['datatype']) {
729                 case 'VARCHAR':
730                     if(!@is_array($record[$key])) {
731                         $new_record[$key] = (isset($record[$key]))?$record[$key]:'';
732                     } else {
733                         $new_record[$key] = implode($field['separator'], $record[$key]);
734                     }
735                     break;
736                 case 'TEXT':
737                     if(!is_array($record[$key])) {
738                         $new_record[$key] = $record[$key];
739                     } else {
740                         $new_record[$key] = implode($field['separator'], $record[$key]);
741                     }
742                     break;
743                 case 'DATETSTAMP':
744                     if($record[$key] > 0) {
745                         list($tag, $monat, $jahr) = explode('.', $record[$key]);
746                         $new_record[$key] = mktime(0, 0, 0, $monat, $tag, $jahr);
747                     } else {
748                         $new_record[$key] = 0;
749                     }
750                     break;
751                 case 'DATE':
752                     if($record[$key] != '' && $record[$key] != '0000-00-00') {
753                         if(function_exists('date_parse_from_format')) {
754                             $date_parts = date_parse_from_format($this->dateformat, $record[$key]);
755                             //list($tag,$monat,$jahr) = explode('.',$record[$key]);
756                             $new_record[$key] = $date_parts['year'].'-'.$date_parts['month'].'-'.$date_parts['day'];
757                             //$tmp = strptime($record[$key],$this->dateformat);
758                             //$new_record[$key] = ($tmp['tm_year']+1900).'-'.($tmp['tm_mon']+1).'-'.$tmp['tm_mday'];
759                         } else {
760                             //$tmp = strptime($record[$key],$this->dateformat);
761                             //$new_record[$key] = ($tmp['tm_year']+1900).'-'.($tmp['tm_mon']+1).'-'.$tmp['tm_mday'];
762                             $tmp = strtotime($record[$key]);
763                             $new_record[$key] = date('Y-m-d', $tmp);
764                         }
765                     } else {
766                         $new_record[$key] = '0000-00-00';
767                     }
768                     break;
769                 case 'INTEGER':
770                     $new_record[$key] = (isset($record[$key]))?$app->functions->intval($record[$key]):0;
771                     //if($new_record[$key] != $record[$key]) $new_record[$key] = $field['default'];
772                     //if($key == 'refresh') die($record[$key]);
773                     break;
774                 case 'DOUBLE':
775                     $new_record[$key] = $record[$key];
776                     break;
777                 case 'CURRENCY':
778                     $new_record[$key] = str_replace(",", ".", $record[$key]);
779                     break;
780
781                 case 'DATETIME':
782                     if (is_array($record[$key]))
783                     {
784                         $filtered_values = array_map(create_function('$item', 'return (int)$item;'), $record[$key]);
785                         extract($filtered_values, EXTR_PREFIX_ALL, '_dt');
786
787                         if ($_dt_day != 0 && $_dt_month != 0 && $_dt_year != 0) {
788                             $new_record[$key] = date( 'Y-m-d H:i:s', mktime($_dt_hour, $_dt_minute, $_dt_second, $_dt_month, $_dt_day, $_dt_year) );
789                         }
790                     }
791                     break;
792                 }
793
794                 // The use of the field value is deprecated, use validators instead
795                 if(isset($field['regex']) && $field['regex'] != '') {
796                     // Enable that "." matches also newlines
797                     $field['regex'] .= 's';
798                     if(!preg_match($field['regex'], $record[$key])) {
799                         $errmsg = $field['errmsg'];
800                         $this->errorMessage .= $this->wordbook[$errmsg]."<br />\r\n";
801                     }
802                 }
803
804                 //* Add slashes to all records, when we encode data which shall be inserted into mysql.
805                 if($dbencode == true) $new_record[$key] = $app->db->quote($new_record[$key]);
806             }
807         }
808         return $new_record;
809     }
810
811
812
813
814
815     /**
816      * process the filters for a given field.
817      *
818      * @param field_name = Name of the field
819      * @param field_value = value of the field
820      * @param filters = Array of filters
821      * @param filter_event = 'SAVE'or 'SHOW'
822      * @return record
823      */
824     function filterField($field_name, $field_value, $filters, $filter_event) {
825
826         global $app;
827         $returnval = $field_value;
828
829         //* Loop trough all filters
830         foreach($filters as $filter) {
831             if($filter['event'] == $filter_event) {
832                 switch ($filter['type']) {
833                 case 'TOLOWER':
834                     $returnval = strtolower($returnval);
835                     break;
836                 case 'TOUPPER':
837                     $returnval = strtoupper($returnval);
838                     break;
839                 case 'IDNTOASCII':
840                     $returnval = $app->functions->idn_encode($returnval);
841                     break;
842                 case 'IDNTOUTF8':
843                     $returnval = $app->functions->idn_decode($returnval);
844                     break;
845                 default:
846                     $this->errorMessage .= "Unknown Filter: ".$filter['type'];
847                     break;
848                 }
849             }
850         }
851         return $returnval;
852     }
853
854
855     /**
856      * process the validators for a given field.
857      *
858      * @param field_name = Name of the field
859      * @param field_value = value of the field
860      * @param validatoors = Array of validators
861      * @return record
862      */
863     function validateField($field_name, $field_value, $validators) {
864
865         global $app;
866
867         $escape = '`';
868
869         // loop trough the validators
870         foreach($validators as $validator) {
871
872             switch ($validator['type']) {
873             case 'REGEX':
874                 $validator['regex'] .= 's';
875                 if(!preg_match($validator['regex'], $field_value)) {
876                     $errmsg = $validator['errmsg'];
877                     if(isset($this->wordbook[$errmsg])) {
878                         $this->errorMessage .= $this->wordbook[$errmsg]."<br />\r\n";
879                     } else {
880                         $this->errorMessage .= $errmsg."<br />\r\n";
881                     }
882                 }
883                 break;
884             case 'UNIQUE':
885                 if($validator['allowempty'] != 'y') $validator['allowempty'] = 'n';
886                 if($validator['allowempty'] == 'n' || ($validator['allowempty'] == 'y' && $field_value != '')){
887                     if($this->action == 'NEW') {
888                         $num_rec = $app->db->queryOneRecord("SELECT count(*) as number FROM ".$escape.$this->formDef['db_table'].$escape. " WHERE $field_name = '".$app->db->quote($field_value)."'");
889                         if($num_rec["number"] > 0) {
890                             $errmsg = $validator['errmsg'];
891                             if(isset($this->wordbook[$errmsg])) {
892                                 $this->errorMessage .= $this->wordbook[$errmsg]."<br />\r\n";
893                             } else {
894                                 $this->errorMessage .= $errmsg."<br />\r\n";
895                             }
896                         }
897                     } else {
898                         $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);
899                         if($num_rec["number"] > 0) {
900                             $errmsg = $validator['errmsg'];
901                             if(isset($this->wordbook[$errmsg])) {
902                                 $this->errorMessage .= $this->wordbook[$errmsg]."<br />\r\n";
903                             } else {
904                                 $this->errorMessage .= $errmsg."<br />\r\n";
905                             }
906                         }
907                     }
908                 }
909                 break;
910             case 'NOTEMPTY':
911                 if(empty($field_value)) {
912                     $errmsg = $validator['errmsg'];
913                     if(isset($this->wordbook[$errmsg])) {
914                         $this->errorMessage .= $this->wordbook[$errmsg]."<br />\r\n";
915                     } else {
916                         $this->errorMessage .= $errmsg."<br />\r\n";
917                     }
918                 }
919                 break;
0bfbaa 920             case 'ISASCII':
MC 921                 if(preg_match("/[^\x20-\x7F]/", $field_value)) {
922                     $errmsg = $validator['errmsg'];
923                     if(isset($this->wordbook[$errmsg])) {
924                         $this->errorMessage .= $this->wordbook[$errmsg]."<br />\r\n";
925                     } else {
926                         $this->errorMessage .= $errmsg."<br />\r\n";
927                     }
928                 }
7fe908 929             case 'ISEMAIL':
MC 930                 if(function_exists('filter_var')) {
931                     if(filter_var($field_value, FILTER_VALIDATE_EMAIL) === false) {
932                         $errmsg = $validator['errmsg'];
933                         if(isset($this->wordbook[$errmsg])) {
934                             $this->errorMessage .= $this->wordbook[$errmsg]."<br />\r\n";
935                         } else {
936                             $this->errorMessage .= $errmsg."<br />\r\n";
937                         }
938                     }
939                 } else {
940                     if(!preg_match("/^\w+[\w\.\-\+]*\w{0,}@\w+[\w.-]*\w+\.[a-zA-Z0-9\-]{2,30}$/i", $field_value)) {
941                         $errmsg = $validator['errmsg'];
942                         if(isset($this->wordbook[$errmsg])) {
943                             $this->errorMessage .= $this->wordbook[$errmsg]."<br />\r\n";
944                         } else {
945                             $this->errorMessage .= $errmsg."<br />\r\n";
946                         }
947                     }
948                 }
949                 break;
950             case 'ISINT':
951                 if(function_exists('filter_var') && $field_value < 2147483647) {
952                     if($field_value != '' && filter_var($field_value, FILTER_VALIDATE_INT) === false) {
953                         $errmsg = $validator['errmsg'];
954                         if(isset($this->wordbook[$errmsg])) {
955                             $this->errorMessage .= $this->wordbook[$errmsg]."<br />\r\n";
956                         } else {
957                             $this->errorMessage .= $errmsg."<br />\r\n";
958                         }
959                     }
960                 } else {
961                     $tmpval = $app->functions->intval($field_value);
962                     if($tmpval === 0 and !empty($field_value)) {
963                         $errmsg = $validator['errmsg'];
964                         if(isset($this->wordbook[$errmsg])) {
965                             $this->errorMessage .= $this->wordbook[$errmsg]."<br />\r\n";
966                         } else {
967                             $this->errorMessage .= $errmsg."<br />\r\n";
968                         }
969                     }
970                 }
971                 break;
972             case 'ISPOSITIVE':
973                 if(!is_numeric($field_value) || $field_value <= 0){
974                     $errmsg = $validator['errmsg'];
975                     if(isset($this->wordbook[$errmsg])) {
976                         $this->errorMessage .= $this->wordbook[$errmsg]."<br />\r\n";
977                     } else {
978                         $this->errorMessage .= $errmsg."<br />\r\n";
979                     }
980                 }
981                 break;
992797 982                 /*
146783 983                 case 'ISV6PREFIX':
MC 984                     $v6_prefix_ok = 0;
985                     $explode_field_value = explode(':',$field_value);
986                     if ($explode_field_value[count($explode_field_value)-1]=='' && $explode_field_value[count($explode_field_value)-2]=='' ){
987                             if ( count($explode_field_value) <= 9 ) {
988                                     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) ) {
989                                             $v6_prefix_ok = 1;
990                                     }
991                             }
7fe908 992                     } else {
MC 993                         $v6_prefix_ok = 2;
146783 994                     }
MC 995                     // check subnet against defined server-ipv6
996                     $sql_v6 = $app->db->queryOneRecord("SELECT ip_address FROM server_ip WHERE ip_type = 'IPv6' AND virtualhost = 'y' LIMIT 0,1");
997                     $sql_v6_explode=explode(':',$sql_v6['ip_address']);
7fe908 998                     if ( count($sql_v6_explode) < count($explode_field_value) && isset($sql_v6['ip_address']) )  {
MC 999                         $v6_prefix_ok = 3;
146783 1000                     }
7fe908 1001                     if($v6_prefix_ok == 0) {
MC 1002                         $errmsg = $validator['errmsg'];
146783 1003                     }
7fe908 1004                     if($v6_prefix_ok == 2) {
MC 1005                         $errmsg = 'IPv6 Prefix must end with ::';
146783 1006                     }
7fe908 1007                     if($v6_prefix_ok == 3) {
MC 1008                         $errmsg = 'IPv6 Prefix too long (according to Server IP Addresses)';
146783 1009                     }
MC 1010                     if($v6_prefix_ok <> 1){
7fe908 1011                         $this->errorMessage .= $errmsg."<br />\r\n";
146783 1012                     }
30fc1b 1013                 break;
146783 1014                 */
7fe908 1015             case 'ISIPV4':
MC 1016                 $vip=1;
1017                 if(preg_match("/^[0-9]{1,3}(\.)[0-9]{1,3}(\.)[0-9]{1,3}(\.)[0-9]{1,3}$/", $field_value)){
1018                     $groups=explode(".", $field_value);
1019                     foreach($groups as $group){
1020                         if($group<0 or $group>255)
1021                             $vip=0;
2dadd2 1022                     }
7fe908 1023                 }else{$vip=0;}
MC 1024                 if($vip==0) {
1025                     $errmsg = $validator['errmsg'];
1026                     if(isset($this->wordbook[$errmsg])) {
1027                         $this->errorMessage .= $this->wordbook[$errmsg]."<br />\r\n";
1028                     } else {
1029                         $this->errorMessage .= $errmsg."<br />\r\n";
1030                     }
1031                 }
1032                 break;
1033             case 'ISIP':
1034                 if($validator['allowempty'] != 'y') $validator['allowempty'] = 'n';
1035                 if($validator['allowempty'] == 'y' && $field_value == '') {
1036                     //* Do nothing
1037                 } else {
1038                     //* Check if its a IPv4 or IPv6 address
1039                     if(isset($validator['separator']) && $validator['separator'] != '') {
1040                         //* When the field may contain several IP addresses, split them by the char defined as separator
1041                         $field_value_array = explode($validator['separator'], $field_value);
1042                     } else {
1043                         $field_value_array[] = $field_value;
1044                     }
1045                     foreach($field_value_array as $field_value) {
1046                         $field_value = trim($field_value);
1047                         if(function_exists('filter_var')) {
1048                             if(!filter_var($field_value, FILTER_VALIDATE_IP)) {
1049                                 $errmsg = $validator['errmsg'];
1050                                 if(isset($this->wordbook[$errmsg])) {
1051                                     $this->errorMessage .= $this->wordbook[$errmsg]."<br />\r\n";
1052                                 } else {
1053                                     $this->errorMessage .= $errmsg."<br />\r\n";
1054                                 }
1055                             }
1056                         } else {
1057                             //* Check content with regex, if we use php < 5.2
1058                             $ip_ok = 0;
1059                             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)){
1060                                 $ip_ok = 1;
1061                             }
1062                             if(preg_match("/^[0-9]{1,3}(\.)[0-9]{1,3}(\.)[0-9]{1,3}(\.)[0-9]{1,3}$/", $field_value)){
1063                                 $ip_ok = 1;
1064                             }
1065                             if($ip_ok == 0) {
1066                                 $errmsg = $validator['errmsg'];
1067                                 if(isset($this->wordbook[$errmsg])) {
1068                                     $this->errorMessage .= $this->wordbook[$errmsg]."<br />\r\n";
1069                                 } else {
1070                                     $this->errorMessage .= $errmsg."<br />\r\n";
1071                                 }
1072                             }
1073                         }
1074                     }
1075                 }
1076                 break;
1077             case 'RANGE':
1078                 //* Checks if the value is within the given range or above / below a value
1079                 //* Range examples: < 10 = ":10", between 2 and 10 = "2:10", above 5 = "5:".
1080                 $range_parts = explode(':', trim($validator['range']));
1081                 $ok = true;
1082                 if($range_parts[0] != '' && $field_value < $range_parts[0]) {
1083                     $ok = false;
1084                 }
1085                 if($range_parts[1] != '' && $field_value > $range_parts[1]) {
1086                     $ok = false;
1087                 }
1088                 if($ok != true) {
1089                     $errmsg = $validator['errmsg'];
1090                     if(isset($this->wordbook[$errmsg])) {
1091                         $this->errorMessage .= $this->wordbook[$errmsg]."<br />\r\n";
1092                     } else {
1093                         $this->errorMessage .= $errmsg."<br />\r\n";
1094                     }
1095                 }
1096                 unset($range_parts);
1097                 break;
1098             case 'CUSTOM':
1099                 // Calls a custom class to validate this record
1100                 if($validator['class'] != '' and $validator['function'] != '') {
1101                     $validator_class = $validator['class'];
1102                     $validator_function = $validator['function'];
1103                     $app->uses($validator_class);
1104                     $this->errorMessage .= $app->$validator_class->$validator_function($field_name, $field_value, $validator);
1105                 } else {
1106                     $this->errorMessage .= "Custom validator class or function is empty<br />\r\n";
1107                 }
1108                 break;
1109             default:
1110                 $this->errorMessage .= "Unknown Validator: ".$validator['type'];
1111                 break;
1112             }
2dadd2 1113
T 1114
7fe908 1115         }
2dadd2 1116
7fe908 1117         return true;
MC 1118     }
2dadd2 1119
T 1120
7fe908 1121     /**
MC 1122      * Create SQL statement
1123      *
1124      * @param record = Datensatz als Array
1125      * @param action = INSERT oder UPDATE
1126      * @param primary_id
1127      * @return record
1128      */
1129     function getSQL($record, $tab, $action = 'INSERT', $primary_id = 0, $sql_ext_where = '') {
2dadd2 1130
7fe908 1131         global $app;
35509d 1132         
TB 1133         $primary_id = $app->functions->intval($primary_id);
7fe908 1134
MC 1135         // If there are no data records on the tab, return empty sql string
1136         if(count($this->formDef['tabs'][$tab]['fields']) == 0) return '';
1137
1138         // checking permissions
1139         if($this->formDef['auth'] == 'yes' && $_SESSION["s"]["user"]["typ"] != 'admin') {
1140             if($action == "INSERT") {
1141                 if(!$this->checkPerm($primary_id, 'i')) $this->errorMessage .= "Insert denied.<br />\r\n";
1142             } else {
1143                 if(!$this->checkPerm($primary_id, 'u')) $this->errorMessage .= "Update denied.<br />\r\n";
1144             }
1145         }
1146
1147         $this->action = $action;
1148         $this->primary_id = $primary_id;
1149
1150         $record = $this->encode($record, $tab, true);
1151         $sql_insert_key = '';
1152         $sql_insert_val = '';
1153         $sql_update = '';
1154
1155         if(!is_array($this->formDef)) $app->error("Form definition not found.");
1156         if(!is_array($this->formDef['tabs'][$tab])) $app->error("The tab is empty or does not exist (TAB: $tab).");
1157
1158         // go trough all fields of the tab
1159         if(is_array($record)) {
1160             foreach($this->formDef['tabs'][$tab]['fields'] as $key => $field) {
1161                 // Wenn es kein leeres Passwortfeld ist
1162                 if (!($field['formtype'] == 'PASSWORD' and $record[$key] == '')) {
1163                     // Erzeuge Insert oder Update Quelltext
1164                     if($action == "INSERT") {
1165                         if($field['formtype'] == 'PASSWORD') {
1166                             $sql_insert_key .= "`$key`, ";
1167                             if($field['encryption'] == 'CRYPT') {
1168                                 $record[$key] = $app->auth->crypt_password(stripslashes($record[$key]));
1169                                 $sql_insert_val .= "'".$app->db->quote($record[$key])."', ";
1170                             } elseif ($field['encryption'] == 'MYSQL') {
1171                                 $tmp = $app->db->queryOneRecord("SELECT PASSWORD('".$app->db->quote(stripslashes($record[$key]))."') as `crypted`");
1172                                 $record[$key] = $tmp['crypted'];
1173                                 $sql_insert_val .= "'".$app->db->quote($record[$key])."', ";
1174                             } elseif ($field['encryption'] == 'CLEARTEXT') {
1175                                 $sql_insert_val .= "'".$app->db->quote($record[$key])."', ";
1176                             } else {
1177                                 $record[$key] = md5(stripslashes($record[$key]));
1178                                 $sql_insert_val .= "'".$app->db->quote($record[$key])."', ";
1179                             }
1180
1181                         } elseif ($field['formtype'] == 'CHECKBOX') {
1182                             $sql_insert_key .= "`$key`, ";
1183                             if($record[$key] == '') {
1184                                 // if a checkbox is not set, we set it to the unchecked value
1185                                 $sql_insert_val .= "'".$field['value'][0]."', ";
1186                                 $record[$key] = $field['value'][0];
1187                             } else {
1188                                 $sql_insert_val .= "'".$record[$key]."', ";
1189                             }
1190                         } else {
1191                             $sql_insert_key .= "`$key`, ";
1192                             $sql_insert_val .= "'".$record[$key]."', ";
1193                         }
1194                     } else {
1195                         if($field['formtype'] == 'PASSWORD') {
1196                             if(isset($field['encryption']) && $field['encryption'] == 'CRYPT') {
1197                                 $record[$key] = $app->auth->crypt_password(stripslashes($record[$key]));
1198                                 $sql_update .= "`$key` = '".$app->db->quote($record[$key])."', ";
1199                             } elseif (isset($field['encryption']) && $field['encryption'] == 'MYSQL') {
1200                                 $tmp = $app->db->queryOneRecord("SELECT PASSWORD('".$app->db->quote(stripslashes($record[$key]))."') as `crypted`");
1201                                 $record[$key] = $tmp['crypted'];
1202                                 $sql_update .= "`$key` = '".$app->db->quote($record[$key])."', ";
1203                             } elseif (isset($field['encryption']) && $field['encryption'] == 'CLEARTEXT') {
1204                                 $sql_update .= "`$key` = '".$app->db->quote($record[$key])."', ";
1205                             } else {
1206                                 $record[$key] = md5(stripslashes($record[$key]));
1207                                 $sql_update .= "`$key` = '".$app->db->quote($record[$key])."', ";
1208                             }
1209
1210                         } elseif ($field['formtype'] == 'CHECKBOX') {
1211                             if($record[$key] == '') {
1212                                 // if a checkbox is not set, we set it to the unchecked value
1213                                 $sql_update .= "`$key` = '".$field['value'][0]."', ";
1214                                 $record[$key] = $field['value'][0];
1215                             } else {
1216                                 $sql_update .= "`$key` = '".$record[$key]."', ";
1217                             }
1218                         } else {
1219                             $sql_update .= "`$key` = '".$record[$key]."', ";
1220                         }
1221                     }
1222                 } else {
1223                     // we unset the password filed, if empty to tell the datalog function
1224                     // that the password has not been changed
1225                     unset($record[$key]);
1226                 }
1227             }
1228         }
1229
1230
1231         // Add backticks for incomplete table names
1232         if(stristr($this->formDef['db_table'], '.')) {
1233             $escape = '';
1234         } else {
1235             $escape = '`';
1236         }
1237
1238
1239         if($action == "INSERT") {
1240             if($this->formDef['auth'] == 'yes') {
1241                 // Set user and group
1242                 $sql_insert_key .= "`sys_userid`, ";
1243                 $sql_insert_val .= ($this->formDef["auth_preset"]["userid"] > 0)?"'".$this->formDef["auth_preset"]["userid"]."', ":"'".$_SESSION["s"]["user"]["userid"]."', ";
1244                 $sql_insert_key .= "`sys_groupid`, ";
1245                 $sql_insert_val .= ($this->formDef["auth_preset"]["groupid"] > 0)?"'".$this->formDef["auth_preset"]["groupid"]."', ":"'".$_SESSION["s"]["user"]["default_group"]."', ";
1246                 $sql_insert_key .= "`sys_perm_user`, ";
1247                 $sql_insert_val .= "'".$this->formDef["auth_preset"]["perm_user"]."', ";
1248                 $sql_insert_key .= "`sys_perm_group`, ";
1249                 $sql_insert_val .= "'".$this->formDef["auth_preset"]["perm_group"]."', ";
1250                 $sql_insert_key .= "`sys_perm_other`, ";
1251                 $sql_insert_val .= "'".$this->formDef["auth_preset"]["perm_other"]."', ";
1252             }
1253             $sql_insert_key = substr($sql_insert_key, 0, -2);
1254             $sql_insert_val = substr($sql_insert_val, 0, -2);
1255             $sql = "INSERT INTO ".$escape.$this->formDef['db_table'].$escape." ($sql_insert_key) VALUES ($sql_insert_val)";
1256         } else {
1257             if($this->formDef['auth'] == 'yes') {
1258                 if($primary_id != 0) {
1259                     $sql_update = substr($sql_update, 0, -2);
1260                     $sql = "UPDATE ".$escape.$this->formDef['db_table'].$escape." SET ".$sql_update." WHERE ".$this->getAuthSQL('u')." AND ".$this->formDef['db_table_idx']." = ".$primary_id;
1261                     if($sql_ext_where != '') $sql .= " and ".$sql_ext_where;
1262                 } else {
1263                     $app->error("Primary ID fehlt!");
1264                 }
1265             } else {
1266                 if($primary_id != 0) {
1267                     $sql_update = substr($sql_update, 0, -2);
1268                     $sql = "UPDATE ".$escape.$this->formDef['db_table'].$escape." SET ".$sql_update." WHERE ".$this->formDef['db_table_idx']." = ".$primary_id;
1269                     if($sql_ext_where != '') $sql .= " and ".$sql_ext_where;
1270                 } else {
1271                     $app->error("Primary ID fehlt!");
1272                 }
1273             }
1274             //* return a empty string if there is nothing to update
1275             if(trim($sql_update) == '') $sql = '';
1276         }
1277
1278         return $sql;
1279     }
1280
1281
1282     /**
1283      * Debugging arrays.
1284      *
1285      * @param array_data
1286      */
1287     function dbg($array_data) {
1288
1289         echo "<pre>";
1290         print_r($array_data);
1291         echo "</pre>";
1292
1293     }
1294
1295
1296     function showForm() {
1297         global $app, $conf;
1298
1299         if(!is_array($this->formDef)) die("Form Definition wurde nicht geladen.");
1300
1301         $active_tab = $this->getNextTab();
1302
1303         // go trough the tabs
1304         foreach( $this->formDef["tabs"] as $key => $tab) {
1305
1306             $tab['name'] = $key;
40dd9f 1307             // Translate the title of the tab
T 1308             $tab['title'] = $this->lng($tab['title']);
2dadd2 1309
7fe908 1310             if($tab['name'] == $active_tab) {
2dadd2 1311
7fe908 1312                 // If module is set, then set the template path relative to the module..
MC 1313                 if($this->module != '') $tab["template"] = "../".$this->module."/".$tab["template"];
2dadd2 1314
7fe908 1315                 // Generate the template if it does not exist yet.
2dadd2 1316
T 1317
1318
7fe908 1319                 if(!is_file($tab["template"])) {
MC 1320                     $app->uses('tform_tpl_generator');
1321                     $app->tform_tpl_generator->buildHTML($this->formDef, $tab['name']);
2dadd2 1322                 }
7fe908 1323                 $app->tpl->setVar('readonly_tab', (isset($tab['readonly']) && $tab['readonly'] == true));
MC 1324                 $app->tpl->setInclude('content_tpl', $tab["template"]);
1325                 $tab["active"] = 1;
1326                 $_SESSION["s"]["form"]["tab"] = $tab['name'];
1327             } else {
1328                 $tab["active"] = 0;
1329             }
2dadd2 1330
7fe908 1331             // Unset unused variables.
MC 1332             unset($tab["fields"]);
1333             unset($tab["plugins"]);
1334
1335             $frmTab[] = $tab;
1336         }
1337
1338         // setting form tabs
1339         $app->tpl->setLoop("formTab", $frmTab);
1340
1341         // Set form action
1342         $app->tpl->setVar('form_action', $this->formDef["action"]);
1343         $app->tpl->setVar('form_active_tab', $active_tab);
1344
1345         // Set form title
1346         $form_hint = $this->lng($this->formDef["title"]);
1347         if($this->formDef["description"] != '') $form_hint .= '<div class="pageForm_description">'.$this->lng($this->formDef["description"]).'</div>';
1348         $app->tpl->setVar('form_hint', $form_hint);
1349
1350         // Set Wordbook for this form
1351
1352         $app->tpl->setVar($this->wordbook);
1353     }
1354
1355     function getDataRecord($primary_id) {
1356         global $app;
1357         $escape = '`';
35509d 1358         $primary_id = $app->functions->intval($primary_id);
7fe908 1359         $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 1360         return $app->db->queryOneRecord($sql);
1361     }
1362
1363
1364     function datalogSave($action, $primary_id, $record_old, $record_new) {
1365         global $app, $conf;
1366
1367         $app->db->datalogSave($this->formDef['db_table'], $action, $this->formDef['db_table_idx'], $primary_id, $record_old, $record_new);
1368         return true;
1369     }
1370
1371     function getAuthSQL($perm, $table = '') {
35509d 1372         global $app;
TB 1373         
1374         $perm = $app->db->quote($perm);
1375         $table = $app->db->quote($table);
1376         
f798aa 1377         if($_SESSION["s"]["user"]["typ"] == 'admin' || $_SESSION['s']['user']['mailuser_id'] > 0) {
7fe908 1378             return '1';
MC 1379         } else {
1380             if ($table != ''){
1381                 $table = ' ' . $table . '.';
1382             }
1383             $groups = ( $_SESSION["s"]["user"]["groups"] ) ? $_SESSION["s"]["user"]["groups"] : 0;
1384             $sql = '(';
1385             $sql .= "(" . $table . "sys_userid = ".$_SESSION["s"]["user"]["userid"]." AND " . $table . "sys_perm_user like '%$perm%') OR  ";
1386             $sql .= "(" . $table . "sys_groupid IN (".$groups.") AND " . $table ."sys_perm_group like '%$perm%') OR ";
1387             $sql .= $table . "sys_perm_other like '%$perm%'";
1388             $sql .= ')';
1389
1390             return $sql;
1391         }
1392     }
1393
1394     /*
992797 1395         This function checks if a user has the parmissions $perm for the data record with the ID $record_id
MC 1396         If record_id = 0, the the permissions are tested against the defaults of the form file.
1397         */
7fe908 1398     function checkPerm($record_id, $perm) {
MC 1399         global $app;
2dadd2 1400
35509d 1401         $record_id = $app->functions->intval($record_id);
7fe908 1402         if($record_id > 0) {
2dadd2 1403             // Add backticks for incomplete table names.
7fe908 1404             if(stristr($this->formDef['db_table'], '.')) {
MC 1405                 $escape = '';
1406             } else {
1407                 $escape = '`';
1408             }
1409
1410             $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);
1411             if($record = $app->db->queryOneRecord($sql)) {
2dadd2 1412                 return true;
T 1413             } else {
1414                 return false;
1415             }
7fe908 1416         } else {
MC 1417             $result = false;
1418             if(@$this->formDef["auth_preset"]["userid"] == $_SESSION["s"]["user"]["userid"] && stristr($perm, $this->formDef["auth_preset"]["perm_user"])) $result = true;
1419             if(@$this->formDef["auth_preset"]["groupid"] == $_SESSION["s"]["user"]["groupid"] && stristr($perm, $this->formDef["auth_preset"]["perm_group"])) $result = true;
1420             if(@stristr($this->formDef["auth_preset"]["perm_other"], $perm)) $result = true;
1421
1422             // if preset == 0, everyone can insert a record of this type
1423             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;
1424
1425             return $result;
1426
2dadd2 1427         }
7fe908 1428
MC 1429     }
1430
1431     function getNextTab() {
1432         // Which tab is shown
1433         if($this->errorMessage == '') {
1434             // If there is no error
1435             if(isset($_REQUEST["next_tab"]) && $_REQUEST["next_tab"] != '') {
1436                 // If the next tab is known
1437                 $active_tab = $_REQUEST["next_tab"];
1438             } else {
1439                 // else use the default tab
1440                 $active_tab = $this->formDef['tab_default'];
1441             }
1442         } else {
1443             // Show the same tab again in case of an error
1444             $active_tab = $_SESSION["s"]["form"]["tab"];
1445         }
1446
1447         return $active_tab;
1448     }
1449
1450     function getCurrentTab() {
1451         return $_SESSION["s"]["form"]["tab"];
1452     }
1453
1454     function isReadonlyTab($tab, $primary_id) {
1455         global $app, $conf;
1456
1457         // Add backticks for incomplete table names.
1458         if(stristr($this->formDef['db_table'], '.')) {
1459             $escape = '';
1460         } else {
1461             $escape = '`';
1462         }
1463
1464         $sql = "SELECT sys_userid FROM ".$escape.$this->formDef['db_table'].$escape." WHERE ".$this->formDef['db_table_idx']." = ".$primary_id;
1465         $record = $app->db->queryOneRecord($sql);
1466
1467         // return true if the readonly flag of the form is set and the current loggedin user is not the owner of the record.
1468         if(isset($this->formDef['tabs'][$tab]['readonly']) && $this->formDef['tabs'][$tab]['readonly'] == true && $record['sys_userid'] != $_SESSION["s"]["user"]["userid"]) {
1469             return true;
1470         } else {
1471             return false;
1472         }
1473     }
1474
1475
1476     // translation function for forms, tries the form wordbook first and if this fails, it tries the global wordbook
1477     function lng($msg) {
1478         global $app, $conf;
1479
1480         if(isset($this->wordbook[$msg])) {
1481             return $this->wordbook[$msg];
1482         } else {
1483             return $app->lng($msg);
1484         }
1485
1486     }
1487
1488     function checkClientLimit($limit_name, $sql_where = '') {
1489         global $app;
1490
1491         $check_passed = true;
1492         $limit_name = $app->db->quote($limit_name);
1493         if($limit_name == '') $app->error('Limit name missing in function checkClientLimit.');
1494
1495         // Get the limits of the client that is currently logged in
35509d 1496         $client_group_id = $app->functions->intval($_SESSION["s"]["user"]["default_group"]);
7fe908 1497         $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 1498
1499         // Check if the user may add another item
1500         if($client["number"] >= 0) {
1501             $sql = "SELECT count(".$this->formDef['db_table_idx'].") as number FROM ".$this->formDef['db_table']." WHERE ".$this->getAuthSQL('u');
1502             if($sql_where != '') $sql .= ' and '.$sql_where;
1503             $tmp = $app->db->queryOneRecord($sql);
1504             if($tmp["number"] >= $client["number"]) $check_passed = false;
1505         }
1506
1507         return $check_passed;
1508     }
1509
1510     function checkResellerLimit($limit_name, $sql_where = '') {
1511         global $app;
1512
1513         $check_passed = true;
1514         $limit_name = $app->db->quote($limit_name);
1515         if($limit_name == '') $app->error('Limit name missing in function checkClientLimit.');
1516
1517         // Get the limits of the client that is currently logged in
35509d 1518         $client_group_id = $app->functions->intval($_SESSION["s"]["user"]["default_group"]);
7fe908 1519         $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 1520
1521         //* If the client belongs to a reseller, we will check against the reseller Limit too
1522         if($client['parent_client_id'] != 0) {
1523
1524             //* first we need to know the groups of this reseller
1525             $tmp = $app->db->queryOneRecord("SELECT userid, groups FROM sys_user WHERE client_id = ".$client['parent_client_id']);
1526             $reseller_groups = $tmp["groups"];
1527             $reseller_userid = $tmp["userid"];
1528
1529             // Get the limits of the reseller of the logged in client
3cebc3 1530             $client_group_id = $_SESSION["s"]["user"]["default_group"];
7fe908 1531             $reseller = $app->db->queryOneRecord("SELECT $limit_name as number FROM client WHERE client_id = ".$client['parent_client_id']);
MC 1532
3cebc3 1533             // Check if the user may add another item
7fe908 1534             if($reseller["number"] >= 0) {
MC 1535                 $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 1536                 if($sql_where != '') $sql .= ' and '.$sql_where;
T 1537                 $tmp = $app->db->queryOneRecord($sql);
7fe908 1538                 if($tmp["number"] >= $reseller["number"]) $check_passed = false;
3cebc3 1539             }
T 1540         }
7fe908 1541
MC 1542         return $check_passed;
1543     }
1544
1545     //* get the difference record of two arrays
1546     function getDiffRecord($record_old, $record_new) {
1547
1548         if(is_array($record_new) && count($record_new) > 0) {
11b3da 1549             foreach($record_new as $key => $val) {
T 1550                 if(@$record_old[$key] != $val) {
1551                     // Record has changed
7fe908 1552                     $diffrec[$key] = array( 'old' => @$record_old[$key],
MC 1553                         'new' => $val);
11b3da 1554                 }
7fe908 1555             }
MC 1556         } elseif(is_array($record_old)) {
1557             foreach($record_old as $key => $val) {
1558                 if($record_new[$key] != $val) {
1559                     // Record has changed
1560                     $diffrec[$key] = array( 'new' => $record_new[$key],
1561                         'old' => $val);
11b3da 1562                 }
7fe908 1563             }
11b3da 1564         }
7fe908 1565         return $diffrec;
2dadd2 1566
7fe908 1567     }
MC 1568
1569
1570
1571
1572
1573     /**
1574      * Generate HTML for DATETIME fields.
1575      *
1576      * @access private
1577      * @param string $form_element Name of the form element.
1578      * @param string $default_value Selected value for fields.
1579      * @param bool $display_secons Include seconds selection.
1580      * @return string HTML
1581      */
1582     function _getDateTimeHTML($form_element, $default_value, $display_seconds=false)
1583     {
eebe76 1584         $_datetime = ($default_value && $default_value != '0000-00-00 00:00:00' ? strtotime($default_value) : false);
7fe908 1585         $_showdate = ($_datetime === false) ? false : true;
MC 1586
1587         $dselect = array('day', 'month', 'year', 'hour', 'minute');
1588         if ($display_seconds === true) {
1589             $dselect[] = 'second';
1590         }
1591
1592         $out = '';
1593
1594         foreach ($dselect as $dt_element)
1595         {
1596             $dt_options = array();
1597             $dt_space = 1;
1598
1599             switch ($dt_element) {
1600             case 'day':
1601                 for ($i = 1; $i <= 31; $i++) {
1602                     $dt_options[] = array('name' =>  sprintf('%02d', $i),
1603                         'value' => sprintf('%d', $i));
75ae20 1604                 }
7fe908 1605                 $selected_value = date('d', $_datetime);
MC 1606                 break;
1607
1608             case 'month':
1609                 for ($i = 1; $i <= 12; $i++) {
1610                     $dt_options[] = array('name' => strftime('%b', mktime(0, 0, 0, $i, 1, 2000)),
1611                         'value' => strftime('%m', mktime(0, 0, 0, $i, 1, 2000)));
1612                 }
1613                 $selected_value = date('n', $_datetime);
1614                 break;
1615
1616             case 'year':
1617                 $start_year = strftime("%Y");
1618                 $years = range((int)$start_year, (int)($start_year+3));
1619
1620                 foreach ($years as $year) {
1621                     $dt_options[] = array('name' => $year,
1622                         'value' => $year);
1623                 }
1624                 $selected_value = date('Y', $_datetime);
1625                 $dt_space = 2;
1626                 break;
1627
1628             case 'hour':
1629                 foreach(range(0, 23) as $hour) {
1630                     $dt_options[] = array('name' =>  sprintf('%02d', $hour),
1631                         'value' => sprintf('%d', $hour));
1632                 }
1633                 $selected_value = date('G', $_datetime);
1634                 break;
1635
1636             case 'minute':
1637                 foreach(range(0, 59) as $minute) {
1638                     if (($minute % 5) == 0) {
1639                         $dt_options[] = array('name' =>  sprintf('%02d', $minute),
1640                             'value' => sprintf('%d', $minute));
75ae20 1641                     }
W 1642                 }
7fe908 1643                 $selected_value = (int)floor(date('i', $_datetime));
MC 1644                 break;
1645
1646             case 'second':
1647                 foreach(range(0, 59) as $second) {
1648                     $dt_options[] = array('name' =>  sprintf('%02d', $second),
1649                         'value' => sprintf('%d', $second));
1650                 }
1651                 $selected_value = (int)floor(date('s', $_datetime));
1652                 break;
75ae20 1653             }
7fe908 1654
MC 1655             $out .= "<select name=\"".$form_element."[$dt_element]\" id=\"".$form_element."_$dt_element\" class=\"selectInput\" style=\"width: auto; float: none;\">";
1656             if (!$_showdate) {
1657                 $out .= "<option value=\"-\" selected=\"selected\">--</option>" . PHP_EOL;
1658             } else {
1659                 $out .= "<option value=\"-\">--</option>" . PHP_EOL;
1660             }
1661
1662             foreach ($dt_options as $dt_opt) {
1663                 if ( $_showdate && ($selected_value == $dt_opt['value']) ) {
1664                     $out .= "<option value=\"{$dt_opt['value']}\" selected=\"selected\">{$dt_opt['name']}</option>" . PHP_EOL;
1665                 } else {
1666                     $out .= "<option value=\"{$dt_opt['value']}\">{$dt_opt['name']}</option>" . PHP_EOL;
1667                 }
1668             }
1669
1670             $out .= '</select>' . str_repeat('&nbsp;', $dt_space);
75ae20 1671         }
7fe908 1672
MC 1673         return $out;
1674     }
1675
2dadd2 1676 }
T 1677
d7ef36 1678 ?>