Simple Groupware PHP Cross Reference Groupware Applications

Source: /src/core/classes/sgsml.php - 640 lines - 25270 bytes - Summary - Text - Print

   1  <?php
   2      /**************************************************************************\
   3      * Simple Groupware 0.743                                                   *
   4      * http://www.simple-groupware.de                                           *
   5      * Copyright (C) 2002-2012 by Thomas Bley                                   *
   6      * ------------------------------------------------------------------------ *
   7      *  This program is free software; you can redistribute it and/or           *
   8      *  modify it under the terms of the GNU General Public License Version 2   *
   9      *  as published by the Free Software Foundation; only version 2            *
  10      *  of the License, no later version.                                       *
  11      *                                                                          *
  12      *  This program is distributed in the hope that it will be useful,         *
  13      *  but WITHOUT ANY WARRANTY; without even the implied warranty of          *
  14      *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            *
  15      *  GNU General Public License for more details.                            *
  16      *                                                                          *
  17      *  You should have received a copy of the GNU General Public License       *
  18      *  Version 2 along with this program; if not, write to the Free Software   *
  19      *  Foundation, Inc., 59 Temple Place - Suite 330, Boston,                  *
  20      *  MA  02111-1307, USA.                                                    *
  21      \**************************************************************************/
  22  
  23  class sgsml {
  24  
  25  function __construct($folder,$view,$items=array(),$writeable=true) {
  26  
  27    // Mountpoint
  28    $folders = array($folder);
  29    if (!is_numeric($folder)) {
  30       $url = sys_parse_folder($folder);
  31      $type = "sys_nodb_".$url["handler"];
  32      $mfolder = $url["mfolder"];
  33      sys_credentials($mfolder);
  34    } else {
  35      $row = db_select_first("simple_sys_tree",array("ftype","folders"),"id=@id@","",array("id"=>$folder));
  36      if (empty($row["ftype"])) throw new Exception("{t}Folder not found.{/t}");
  37      $type = $row["ftype"];
  38      if ($row["folders"]!="") {
  39        $folders = array();
  40        foreach (explode("|",trim($row["folders"],"|")) as $val) {
  41          if (empty($val) or !db_get_right($val, $writeable ? "write" : "read", $view)) continue;
  42          $folders[] = $val;
  43        }
  44      }
  45      $mfolder = "";
  46    }
  47    
  48    if (isset($_SESSION["disabled_modules"][$type])) exit("{t}Module disabled.{/t}");
  49  
  50    $this->schema = db_get_schema(sys_find_module($type),$folder,$view);
  51    $view = sys_array_shift(array_keys($this->schema["views"]));
  52    $this->current_view = &$this->schema["views"][$view];
  53    
  54    if (isset($this->current_view["SCHEMA"]) and $this->current_view["SCHEMA"]!="") {
  55      $this->schema = db_get_schema(sys_find_module($this->current_view["SCHEMA"]),"",$view);
  56      $view = sys_array_shift(array_keys($this->schema["views"]));
  57      $this->current_view = &$this->schema["views"][$view];
  58    }
  59    $this->folder = $folder;
  60    $this->view = $view;
  61    $this->fields = &$this->schema["fields"];
  62    $this->att = &$this->schema["att"];
  63    
  64    $this->tname = $this->att["NAME"];
  65    $this->where = $this->current_view["SQLWHERE"];
  66    $this->handler = $this->current_view["SQL_HANDLER"];
  67    $this->buttons = $this->current_view["buttons"];
  68    $this->rowvalidates = $this->current_view["rowvalidates"];
  69    $this->rowfilters = $this->current_view["rowfilters"];
  70    $this->current_fields = &$this->current_view["fields"];
  71    $this->notification = true;
  72  
  73    $this->vars = array("item"=>$items, "folder"=>$this->folder, "folders"=>$folders, "mfolder"=>$mfolder);
  74  
  75    $this->vars_noquote = array();
  76    if (!empty($this->att["ENABLE_ASSET_RIGHTS"])) {
  77      if ($writeable) $this->where[] = "@permission_sql_write_nq@";
  78      $this->vars_noquote["permission_sql_read_nq"] = $_SESSION["permission_sql_read"];
  79      $this->vars_noquote["permission_sql_write_nq"] = $_SESSION["permission_sql_write"];
  80    }
  81  
  82    if (is_array($this->where) and count($this->where)>0) {
  83      foreach ($this->where as $key=>$val) {
  84        if (!preg_match_all("|@(.*?)@|i",$val,$matches,PREG_SET_ORDER)) continue;
  85        foreach ($matches as $match) {
  86          if (count($match)!=2) continue;
  87          $wkey = $match[1];
  88          if (empty($this->vars[$wkey]) and empty($this->vars_noquote[$wkey])) $this->where[$key] = "1=1";
  89    } } }
  90  }
  91  
  92  /**
  93   * Changes the current sgsML fields with an array of path steps
  94   *
  95   * @param array $patch_array Steps, e.g. array(origin, SIMPLE_DEFAULT=email)
  96   */
  97  function patch_fields(array $patch_array) {
  98    $pointer = $this->fields;
  99    foreach ($patch_array as $elem) {
 100      $elem = explode("=", $elem, 2);
 101      if (count($elem)==2) {
 102        $pointer[$elem[0]] = $elem[1];
 103        break;
 104      }
 105      $pointer = &$pointer[$elem[0]];
 106    }    
 107  }
 108  
 109  function get_rows($fields, $order="", $limit="") {
 110    $optional = array("handler"=>$this->handler,"sqlvarsnoquote"=>$this->vars_noquote,"default_sql"=>$this->current_view["DEFAULT_SQL"],"custom_name"=>$this->att["CUSTOM_NAME"]);
 111    return db_select($this->tname,$fields,$this->where,$order,$limit,$this->vars,$optional);
 112  }
 113  
 114  function get_count() {
 115    $optional = array("handler"=>$this->handler,"sqlvarsnoquote"=>$this->vars_noquote,"default_sql"=>$this->current_view["DEFAULT_SQL"],"custom_name"=>$this->att["CUSTOM_NAME"]);
 116    
 117    // TODO optimize
 118    return db_count($this->tname,$this->where,$this->vars,$optional);
 119  }
 120  
 121  function set_filter($filters) {
 122    if ($filters=="") return;
 123    $ops = array("eq","neq","lt","gt","like","nlike","starts","oneof");
 124    foreach (explode("||",$filters) as $key=>$filter) {
 125      $filter = explode("|",$filter);
 126      if (count($filter)!=3 or !isset($this->current_fields[$filter[0]])) continue;
 127      if (!in_array($filter[1],$ops) or trim($filter[2])=="") continue;
 128  
 129      if ($this->current_fields[$filter[0]]["SIMPLE_TYPE"]=="checkbox") {
 130        $filter[2] = $filter[2]==sys_remove_trans("{t}yes{/t}")?"1":"0";
 131      }
 132      if ($filter[1]=="oneof") $filter[2] = explode(",",$filter[2]);
 133      if (in_array($this->current_fields[$filter[0]]["SIMPLE_TYPE"],array("date","dateselect","time","datetime"))) {
 134        $filter[2] = modify::datetime_to_int($filter[2]);
 135      }
 136      $op = "=";
 137      switch ($filter[1]) {
 138        case "neq": $op = "!="; break;
 139        case "oneof": $op = "in"; break;
 140        case "lt": $op = "<"; break;
 141        case "gt": $op = ">"; break;
 142        case "like": $op = "like"; $filter[2] = "%".$filter[2]."%"; break;
 143        case "nlike": $op = "not like"; $filter[2] = "%".$filter[2]."%"; break;
 144        case "starts": $op = "like"; $filter[2] = $filter[2]."%"; break;
 145      }
 146      $this->vars["filter_value_".$key] = $filter[2];
 147      $this->where[] = $filter[0]." ".$op." (@filter_value_".$key."@)";
 148    }
 149  }
 150  
 151  function insert(array &$data) {
 152    return $this->_save($data);
 153  }
 154  
 155  function update(array &$data, $id) {
 156    return $this->_save($data, $id);
 157  }
 158  
 159  function validate($data, $id=-1) {
 160    list($rdata, $unused, $error) = $this->_complete_data($data, $id);
 161    if ($error) return $error;
 162    return $this->_validate($rdata, $id);
 163  }
 164  
 165  function filter_field($field_name, $value, $row) {
 166    if ($field_name=="" or !isset($this->fields[$field_name])) return $value;
 167  
 168    $field = $this->current_fields[$field_name];
 169    $type = $field["SIMPLE_TYPE"];
 170    if (!empty($field["NO_CHECKS"])) return $value;
 171  
 172    $filters = array();
 173    if (isset($this->current_view["filters"][$field_name])) {
 174      $filters = $this->current_view["filters"][$field_name];
 175    }
 176  
 177    if (is_call_type($type)) {
 178      $filters[] = array("FUNCTION"=>"modify::nl2br");
 179      $filters[] = array("FUNCTION"=>"modify::htmlquote");
 180  
 181  /* TODO implement
 182      $filters[] = array("FUNCTION"=>"type_".$type."::render_page");
 183      $filters[] = array("FUNCTION"=>"modify::htmlfield");
 184      $filters[] = array("FUNCTION"=>"modify::htmlquote");
 185      $filters[] = array("FUNCTION"=>"type_".$type."::render_value");
 186      $values[$key] = call_user_func(array($class, $function), $val, $value, $params, self::_explode($row));
 187  */
 188    } else if ($type == "textarea") {
 189      $filters[] = array("FUNCTION"=>"modify::nl2br");
 190      $filters[] = array("FUNCTION"=>"modify::htmlquote");
 191    } else {
 192      $filters[] = array("FUNCTION"=>"modify::field");
 193      $filters[] = array("FUNCTION"=>"modify::htmlquote");
 194    }
 195    if (empty($filters)) return $value;
 196    
 197    if (sgsml::type_is_multiple($type)) {
 198      $values = explode("|",trim($value,"|"));
 199    } else {
 200      $values = (array)$value;
 201    }
 202  
 203    foreach ($filters as $filter) {
 204      list($class, $function, $params) = sys_find_callback("modify", $filter["FUNCTION"]);
 205      if (isset($filter["TYPE"])) continue; // TODO implement
 206      foreach ($values as $key=>$value) {
 207        $values[$key] = call_user_func(array($class, $function), $value, $params, self::_explode($row));
 208      }
 209    }
 210    return $values;
 211  }
 212  
 213  function restore_field($field_name, $value, $row) {
 214    if ($field_name=="" or !isset($this->fields[$field_name])) return $value;
 215    if (empty($this->current_view["restore"][$field_name])) return $value;
 216    
 217    $restore_filters = $this->current_view["restore"][$field_name];
 218    $field = $this->fields[$field_name];
 219  
 220    $value = explode("|",trim($value,"|"));
 221    foreach ($restore_filters as $filter) {
 222      list($class, $function, $params) = sys_find_callback("modify", $filter["FUNCTION"]);
 223      foreach (array_keys($value) as $key) {
 224        $value[$key] = call_user_func(array($class, $function), $value[$key], $params, $row, $field_name);
 225      }
 226    }
 227    return self::scalarize($value, $field);
 228  }
 229  
 230  function validate_field($field_name, $value, $id=-1) {
 231    if ($field_name=="" or !isset($this->fields[$field_name])) return array();
 232  
 233    $error = array();  
 234    $field = $this->fields[$field_name];
 235    $key_name = isset($field["DISPLAYNAME"])?$field["DISPLAYNAME"]:$field["NAME"];
 236  
 237    $value = (array)$value;
 238    $value_str = self::scalarize($value, $field);
 239    
 240    if (isset($field["REQUIRED"]) and $value_str=="") $error[] = array($key_name,"{t}missing field{/t}");
 241    if (isset($field["VALIDATE"])) {
 242      foreach ($field["VALIDATE"] as $validate) {
 243        list($class, $function, $params) = sys_find_callback("validate", $validate["FUNCTION"]);
 244        foreach ($value as $value_item) {
 245          if ($value_item!="" or isset($field["REQUIRED"])) {
 246            $result = call_user_func(array($class, $function), $value_item, $params, $field);
 247            if ($result!="") $error[] = array($key_name,$result);
 248    } } } }
 249    
 250    if (isset($field["KEY"]) or ((isset($field["IS_UNIQUE"]) or isset($field["IS_UNIQUE_WITH_TRASH"])) and $value_str!="")) {
 251      $check_trash = isset($field["IS_UNIQUE_WITH_TRASH"]);
 252      if ($result = validate::itemexists($this->tname, array($field_name=>$value_str), $id, $check_trash) and $result!="") {
 253        $error[] = array($key_name,$result);
 254    } }
 255    return $error;
 256  }
 257  
 258  function get_fields_by_type($type) {
 259    if ($type=="") return array();
 260    $type = (array)$type;
 261    $fields = array();
 262    foreach ($this->fields as $key=>$field) {
 263      if (in_array($field["SIMPLE_TYPE"],$type)) $fields[] = $key;
 264    }
 265    return $fields;
 266  }
 267  
 268  function build_history($new_data, $old_data) {
 269    $cdata = "";
 270    $cfields = array();
 271    $no_history = array("created","createdby","lastmodified","lastmodifiedby","history","notification_summary","dsize","id");
 272    
 273    foreach ($new_data as $data_key=>$data_value) {
 274      $field = $this->fields[$data_key];
 275      if (isset($old_data[$data_key]) and strcmp(trim($old_data[$data_key], "|"), trim($data_value, "|"))==0) {
 276        unset($new_data[$data_key]);
 277        continue;
 278      }
 279      if (in_array($data_key, $no_history)) continue;
 280      if (isset($field["SIMPLE_TYPE"]) and (strlen($data_value)>0 or !empty($old_data[$data_key]))) {
 281        $data_value = asset::build_history($field["SIMPLE_TYPE"], $data_value, @$old_data[$data_key]);
 282      }
 283      if (!empty($field["NO_SEARCH_INDEX"])) $data_value = "";
 284      if (!empty($field["DISPLAYNAME"])) $key = $field["DISPLAYNAME"]; else $key = $data_key;
 285  
 286      if (trim($data_value)!="") $cdata .= $key.": ".$data_value."\n";
 287      $cfields[] = $key;
 288    }
 289    $new_data["history"] = str_replace("@fields@", implode(", ", $cfields), $new_data["history"]).$cdata."\n";  
 290    return $new_data;
 291  }
 292  
 293  private function _complete_data($data, $id=-1) {
 294    $data_row = array();
 295    $insert = ($id>0 or !is_numeric($id)) ? false : true;
 296    if (!$insert) {
 297      $this->vars["item"] = (array)$id;
 298      $data_row = array_pop($this->get_rows("*"));
 299      if (!$data_row) return array(false,false,self::_error("{t}Data{/t}","{t}Item(s) not found or access denied.{/t}"));
 300    }
 301    $rdata = array();
 302    foreach ($this->current_fields as $field_name => $field) {
 303      $rdata[$field_name] = "";
 304      if (isset($data[$field_name])) {
 305        $rdata[$field_name] = $data[$field_name];
 306      } else if ($insert) {
 307        $rdata[$field_name] = $field["SIMPLE_DEFAULT"];
 308        if (!empty($field["SIMPLE_DEFAULT_FUNCTION"])) {
 309          list($class, $function, $params) = sys_find_callback("modify", $field["SIMPLE_DEFAULT_FUNCTION"]);
 310          $rdata[$field_name] = call_user_func(array($class, $function), $params);
 311        }
 312      } else if (isset($data_row[$field_name])) {
 313        $rdata[$field_name] = $this->restore_field($field_name,$data_row[$field_name],$data);
 314      }
 315      if (isset($data[$field_name."_remove"])) {
 316        $rdata[$field_name] = str_replace("|".$rdata[$field_name]."|","|",$data_row[$field_name]);
 317      }
 318      if (isset($data[$field_name."_append"])) {
 319        $rdata[$field_name] = $data_row[$field_name].$rdata[$field_name];
 320      }
 321      if (isset($data[$field_name."_prepend"])) {
 322        $rdata[$field_name] = $rdata[$field_name].$data_row[$field_name];
 323      }
 324      if (self::type_is_multiple($field["SIMPLE_TYPE"]) and !is_array($rdata[$field_name])) {
 325        $rdata[$field_name] = array_unique(explode("|",trim($rdata[$field_name],"|")));
 326      }
 327      if ($field["SIMPLE_TYPE"]=="id") $rdata[$field_name] = $id ? $id : -1;
 328      
 329      if ($field["SIMPLE_TYPE"]=="files" and !empty($rdata[$field_name])) { // download from URL
 330        foreach ($rdata[$field_name] as $filekey=>$file) {
 331          if (!preg_match("|^https?://.+|i",$file)) continue;
 332          $target = self::getfile_url($file);
 333          if ($target=="" or !file_exists($target)) {
 334            return array(false,false,self::_error("{t}Data{/t}","{t}Upload failed{/t}: {t}The url doesn't exist.{/t} ".$file));
 335          }
 336          $rdata[$field_name][$filekey] = $target;
 337    } } }
 338    return array($rdata, $data_row, false);
 339  }
 340  
 341  private function _save(array &$data, $id=-1) {
 342    $insert = ($id>0 or !is_numeric($id)) ? false : true;
 343    if (count($data)==0) return array();
 344    
 345    if (!empty($this->att["DEFAULT_SQL"]) and $this->att["DEFAULT_SQL"]=="no_select") {
 346      return self::_error("{t}Module{/t}","{t}Access denied.{/t}");
 347    }
 348  
 349    if (!empty($data["folder"])) {
 350      // check permissions
 351      if (!db_get_right($data["folder"], "write", $this->view)) return self::_error("{t}Folder{/t}","{t}Access denied.{/t}","folder");
 352      $this->folder = $data["folder"];
 353    } else {
 354      $data["folder"] = $this->folder;
 355    }
 356  
 357    // fill data array
 358    list($rdata, $data_row, $error) = $this->_complete_data($data, $id);
 359    if ($error) return $error;
 360  
 361    // validate
 362    if (($result = $this->_validate($rdata,$id))) return $result;
 363    
 364    if ($insert) {
 365      $id = sql_genID($this->tname)*100+$_SESSION["serverid"];
 366      $sql_data = array("id"=>$id,"dsize"=>0,"history"=>sprintf("{t}Item created by %s at %s{/t}\n",$_SESSION["username"],sys_date("{t}m/d/y g:i:s a{/t}")));
 367    } else {
 368      $sql_data = array("dsize"=>0,"history"=>sprintf("{t}Item edited (%s) by %s at %s{/t}\n","@fields@",$_SESSION["username"],sys_date("{t}m/d/y g:i:s a{/t}")));
 369    }
 370  
 371    // count sizes, move files to store, delete old files
 372    foreach ($this->current_fields as $field_name => $field) {
 373      if ($field["SIMPLE_TYPE"]=="id") continue;
 374      
 375      if ($field["SIMPLE_TYPE"]=="files" and !empty($rdata[$field_name])) {
 376      
 377        foreach ($rdata[$field_name] as $val) {
 378          if (file_exists($val)) $sql_data["dsize"] += filesize($val);
 379        }
 380  
 381        // TODO 2 store handler?
 382        if (!empty($data_row[$field_name])) {
 383          $data_old = explode("|",trim($data_row[$field_name],"|"));
 384          foreach ($data_old as $filekey=>$file) {
 385            if (in_array($file,$rdata[$field_name])) continue;
 386            if (ARCHIVE_DELETED_FILES and file_exists($file)) {
 387              $i = 1;
 388              $m = "";
 389              $trash_name = SIMPLE_STORE."/trash/".$this->folder."_".$id."_";
 390              $trash_file = modify::basename($file);
 391              while (file_exists($trash_name.$m.$trash_file)) $m = ($i++)."_";
 392              rename($file, $trash_name.$m.$trash_file);
 393              touch($trash_name.$m.$trash_file);
 394            } else {
 395              @unlink($file);
 396        } } }
 397  
 398        foreach ($rdata[$field_name] as $filekey=>$file) {
 399          if ($file=="") {
 400            unset($rdata[$field_name][$filekey]);
 401            $data[$field_name] = implode("|", $rdata[$field_name]);
 402            continue;
 403          }
 404          if (file_exists(SIMPLE_CACHE."/upload/".basename($file))) {
 405            $filebase = modify::basename(basename($file));
 406              list($target,$filename) = sys_build_filename($filebase, $this->tname);
 407  
 408            dirs_checkdir($target);
 409            $target .= sys_get_pathnum($id)."/";
 410            dirs_checkdir($target);
 411            $target .= md5($id).$filename;
 412          
 413            rename(SIMPLE_CACHE."/upload/".basename($file), $target);
 414            $rdata[$field_name][$filekey] = $target;
 415            $data[$field_name] = implode("|", $rdata[$field_name]);
 416          }
 417        }
 418        $basenames = array();
 419        foreach (array_reverse($rdata[$field_name]) as $filekey=>$file) {
 420          $basename = modify::basename($file);
 421          if (isset($basenames[$basename])) {
 422            $old_filekey = $basenames[$basename];
 423            $basename = preg_replace("|_rev\d+|","",$basename);
 424            $base = $basename;
 425            $i = 1;
 426            while (isset($basenames[$basename])) {
 427              if (($pos = strrpos($base,"."))) {
 428                $basename = substr($base,0,$pos)."_rev".($i++).substr($base,$pos);
 429              } else $basename = $base."_rev".($i++);
 430            }
 431            $target = str_replace(modify::basename($file), $basename, $file);
 432            if (rename($file,$target)) {
 433              // swap
 434              $rdata[$field_name][$filekey] = $rdata[$field_name][$old_filekey];
 435              $rdata[$field_name][$old_filekey] = $target;
 436              $data[$field_name] = implode("|", $rdata[$field_name]);
 437            }
 438          }
 439          $basenames[$basename] = $filekey;
 440        }
 441      }
 442      
 443      if (!empty($field["STORE"]) and is_array($field["STORE"])) {
 444        foreach ($field["STORE"] as $store) {
 445          list($class, $function, $params) = sys_find_callback("modify", $store["FUNCTION"]);
 446          $rdata[$field_name] = call_user_func(array($class, $function), $rdata[$field_name], $rdata, $params);
 447        }
 448      }
 449      if (!isset($sql_data[$field_name]) and !is_null($rdata[$field_name])) $sql_data[$field_name] = $rdata[$field_name];
 450    }
 451    
 452    // transform
 453    foreach ($sql_data as $key=>$value) {
 454      $sql_data[$key] = self::scalarize($value, $this->fields[$key]);
 455    }
 456    
 457    // reduce to new values
 458    $sys_fields = array("history"=>"","dsize"=>"","seen"=>"");
 459    foreach ($sql_data as $data_key=>$data_value) {
 460      if (isset($sys_fields[$data_key])) continue;
 461  
 462      $addfield = true;
 463      $field = $this->fields[$data_key];
 464      if (!isset($this->current_fields[$data_key])) $addfield = false;
 465      if (isset($field["NOTINALL"])) $addfield = false;
 466      if (isset($field["NOTIN"]) and in_array($this->view,$field["NOTIN"])) $addfield = false;
 467      if (isset($field["READONLYIN"]) and (in_array($this->view,$field["READONLYIN"]) or in_array("all",$field["READONLYIN"]))) {
 468        $addfield = false;
 469      }
 470      if (isset($field["ONLYIN"])) {
 471        if (in_array($this->view,$field["ONLYIN"])) $addfield = true; else $addfield = false;
 472      }
 473      if (!$addfield) unset($sql_data[$data_key]);
 474    }
 475    
 476    // build history  
 477    $sql_data = $this->build_history($sql_data, $data_row);
 478    if (!array_diff(array_keys($sql_data), array("history", "seen"))) $sql_data = array();
 479  
 480    // save in db
 481    if ($insert) {
 482      $error_sql = db_insert($this->tname,$sql_data,array("handler"=>$this->handler));
 483      if ($error_sql!="") return self::_error("{t}SQL failed.{/t}",$error_sql);
 484      if ($this->notification) sys_notification("{t}Item successfully created.{/t} (".$id.")");
 485    } else {
 486      if (count($sql_data)==0) return $id;
 487      $error_sql = db_update($this->tname,$sql_data,array("id=@id@"),array("id"=>$id,"folder"=>$this->folder),array("handler"=>$this->handler));
 488      if ($error_sql!="") return self::_error("{t}SQL failed.{/t}",$error_sql);
 489      if ($this->notification) sys_notification("{t}Item successfully updated.{/t} (".(is_numeric($id)?$id:1).")");
 490    }
 491  
 492    if (empty($this->handler)) {
 493      db_update("simple_sys_tree",array("history"=>"[".$id."/details] ".$sql_data["history"]),array("id=@id@"),array("id"=>$this->folder));
 494      db_update_treesize($this->tname,$this->folder);
 495      
 496      if (!$insert and $this->folder!=$data_row["folder"]) {
 497        db_update("simple_sys_tree",array("history"=>"[".$id."/details] ".$sql_data["history"]),array("id=@id@"),array("id"=>$data_row["folder"]));
 498        db_update_treesize($this->tname,$data_row["folder"]);
 499        db_search_delete($this->tname,$id,$data_row["folder"]);
 500      }
 501      if (empty($this->att["NO_SEARCH_INDEX"])) db_search_update($this->tname,$id,$this->fields);
 502      sys_log_stat($insert ? "new_records" : "changed_records",1);
 503    }
 504  
 505    // call triggers
 506    $trigger = "";
 507    if ($insert and !empty($this->att["TRIGGER_NEW"])) $trigger = $this->att["TRIGGER_NEW"];
 508    if (!$insert and !empty($this->att["TRIGGER_EDIT"])) $trigger = $this->att["TRIGGER_EDIT"];
 509    
 510    if ($trigger and ($result = asset_process_trigger($trigger,$id,$rdata,$this->tname))) {
 511      return self::_error("{t}Trigger failed{/t}",$result);
 512    }
 513  
 514    // send notification
 515    $tree_notification = db_select_value("simple_sys_tree","notification","id=@id@",array("id"=>$this->folder));
 516    if ($tree_notification!="") $rdata["notification"] .= ",".$tree_notification;
 517    
 518    if (!$insert and $this->folder!=$data_row["folder"]) {
 519      $tree_notification = db_select_value("simple_sys_tree","notification","id=@id@",array("id"=>$data_row["folder"]));
 520      if ($tree_notification!="") $rdata["notification"] .= ",".$tree_notification;
 521    }
 522    
 523    if (!empty($rdata["notification"])) {
 524      $rdata["notification"] = trim($rdata["notification"],",");
 525      $smtp_data = asset::build_notification($this->att["NAME"],$this->current_fields,$rdata,$sql_data,$id,$data_row);
 526        if (($result = asset_process_trigger("sendmail",$id,$smtp_data))) return self::_error("{t}Trigger failed{/t}",$result);
 527    }
 528  
 529    // update stats
 530    if (!empty($this->handler)) {
 531      foreach ($sql_data as $data_key=>$data_value) {
 532        $field = $this->fields[$data_key];
 533        if ($field["SIMPLE_TYPE"]!="files") continue;
 534        foreach (explode("|",$data_value) as $file) {
 535          if (sys_strbegins($file, SIMPLE_CACHE."/upload/")) @unlink($file);
 536    } } }
 537    return $id;
 538  }
 539  
 540  private function _validate($data, $id) {
 541    $error = array();
 542    foreach (array_keys($this->current_fields) as $field_name) {
 543      if (($result = $this->validate_field($field_name,$data[$field_name],$id))) $error[$field_name] = $result;
 544    }
 545    foreach ($this->rowvalidates as $validate) {
 546      list($class, $function, $params) = sys_find_callback("validate", $validate["FUNCTION"]);
 547      $result = call_user_func(array($class, $function), $data, $params);
 548      if ($result!="") {
 549        $vfields = array();
 550        foreach (explode("|",$validate["FIELDS"]) as $vfield) {
 551          $tfield = $this->fields[$vfield];
 552          $vfields[] = isset($tfield["DISPLAYNAME"])?$tfield["DISPLAYNAME"]:$tfield["NAME"];
 553          $error[$vfield][] = array();
 554        }
 555        $error[$validate["FIELDS"]][] = array(implode(", ",$vfields),$result);
 556      }
 557    }
 558    return $error;
 559  }
 560  
 561  static function type_is_multiple($type) {
 562    if (in_array($type,array("files","select","dateselect"))) return true;
 563    return false;
 564  }
 565  
 566  static function getfile_url($url) {
 567    $filename = self::_url_getfilename($url);
 568    list($target,$filename) = sys_build_filename($filename);
 569    dirs_checkdir($target);
 570    $target .= $_SESSION["username"]."__".$filename;
 571  
 572    if (sys_is_internal_url($url)) {
 573      $vars = array();
 574      parse_str(parse_url($url, PHP_URL_QUERY), $vars);
 575      if (!empty($vars["folder2"]) and !empty($vars["item"]) and !empty($vars["field"])) {
 576        $source = ajax::file_download($vars["folder2"], @$vars["view2"], $vars["item"], $vars["field"], @$vars["subitem"], false);
 577        if (file_exists($source) and copy($source, $target)) return $target;
 578      }
 579    }
 580    if ($f_in = @fopen($url,"rb") and $f_out = fopen($target,"wb")) {
 581      while (!feof($f_in)) fwrite($f_out, fread($f_in, 8192));
 582      fclose($f_out);
 583      fclose($f_in);
 584      return $target;
 585    }
 586    return "";
 587  }
 588  
 589  static function getfile_upload($filename) {
 590    list($target,$filename) = sys_build_filename($filename);
 591    dirs_checkdir($target);
 592    $target .= $_SESSION["username"]."__".$filename;
 593  
 594    if (($fp = fopen("php://input", "r")) and ($ft = fopen($target, "w"))) {
 595      while (!feof($fp)) fwrite($ft, fread($fp, 1024));
 596      fclose($ft);
 597      fclose($fp);
 598      return $target;
 599    }
 600    return "";
 601  }
 602  
 603  static function scalarize($value, $field) {
 604    if (is_array($value)) {
 605      $value = implode("|",$value);
 606      if (!self::type_is_multiple($field["SIMPLE_TYPE"]) or $value=="") return $value;
 607      if (empty($field["SIMPLE_SIZE"]) or $field["SIMPLE_SIZE"]!="1") return "|".$value."|";
 608    }
 609    return $value;
 610  }
 611  
 612  private static function _error($name,$desc,$field="") {
 613    if ($field=="") $field = $name;
 614    return array($field=>array(array($name,$desc)));
 615  }
 616  
 617  private static function _explode($row) {
 618    $result = array();
 619    foreach ($row as $key=>$value) {
 620      $value = explode("|",trim($value,"|"));
 621      $result[$key] = array("data"=>$value, "filter"=>$value);
 622    }
 623    return $result;
 624  }
 625  
 626  private static function _url_getfilename($url) {
 627    $filename = basename($url);
 628    if ($filename=="") $filename = "default.txt";
 629    if (preg_match("|filename=(.*?)&|",$url,$match) and isset($match[1])) {
 630      $filename = rawurldecode($match[1]);
 631    } else {
 632      $filename = preg_replace("|([^a-z0-9-_.])|i","_",$filename);
 633      $ext = modify::getfileext($filename);
 634      if ($ext=="" or strlen($ext)>5) $filename .= ".txt";
 635      if (strlen($filename)>50) $filename = substr($filename,strlen($filename)-50);
 636    }
 637    return $filename;
 638  }
 639  
 640  }

title

Description

title

Description

title

Description

title

title

Body