function recursive_del($dir, $recursive = true, $extLimit = "", $maxDel = 0, $carryDel = 0) { // USE AT YOUR OWN RISK while ($dir != '' && $dir[0] == "/") { $dir = substr($dir, 1); } // remove initial "/" if ($dir != '' && $dir[strlen($dir) - 1] != "/") { $dir .= "/"; } if ($dir == "/" || $dir == "") { // SOME degree of safety return false; } $pattern = $dir . "*" . ($extLimit != '' ? '.' . $extLimit : ''); $count = $carryDel; if ($recursive) { // we divide in two for performance reasons (less testing) foreach (glob($pattern) as $file) { if ($maxDel > 0) { $count++; if ($count > $maxDel) { return false; } } if (is_dir($file)) { @recursive_del($file, true, $extLimit, $maxDel, $count); } else { @unlink($file); } @rmdir($dir); } } else { foreach (glob($pattern) as $file) { if ($maxDel > 0) { $count++; if ($count > $maxDel) { return false; } } if (is_file($file)) { @unlink($file); } @rmdir($dir); } } return true; }
function dumpTemplateCaches($alsoDumpLogs = false, $allSites = false) { # Some core controler asked all caches to be dumped (also happens on nocache) if (CONS_PATH_CACHE != "CONS_PATH_CACHE" && isset($_SESSION['CODE'])) { // this bug could be disastrous if ($allSites) { $d = cReadFile(CONS_PATH_CACHE . "domains.dat"); recursive_del(CONS_PATH_CACHE, true, "cache"); cWriteFile(CONS_PATH_CACHE . "domains.dat", $d); } else { recursive_del(CONS_PATH_CACHE . $_SESSION['CODE'] . "/caches/", true, "cache"); } makeDirs(CONS_PATH_CACHE . $_SESSION['CODE'] . "/caches/"); if ($alsoDumpLogs) { // just .log to keep .dat, always allsites $listFiles = listFiles(CONS_PATH_LOGS, "/^([^a]).*(\\.log)\$/i", false, false, true); foreach ($listFiles as $file) { @unlink(CONS_PATH_LOGS . $file); } } } }
case ZipArchive::ER_INCONS: return 'Zip archive inconsistent'; case ZipArchive::ER_REMOVE: return 'Can\'t remove file'; case ZipArchive::ER_DELETED: return 'Entry has been deleted'; default: return sprintf('Unknown status %s', $status); } } $core->log[] = $core->langOut("mup_error") . ": " . ZipStatusString($zHn); $core->setLog(CONS_LOGGING_ERROR); $ok = false; } # kill files and zip file recursive_del(CONS_FMANAGER . "upload/mpu", true); } else { // error 9 = unable to make destination path $core->log[] = $core->langOut("mup_error") . ": code #" . $ok . " (" . $core->langOut("e20" . $ok) . ")"; if (is_file($zipFile)) { @unlink($zipFile); } if (is_file($destination)) { @unlink($destination); } $ok = false; if ($ok == 9) { $core->log[] = CONS_ERROR_TAG . " Error while creating MPU folder"; } $core->setLog(CONS_LOGGING_ERROR); }
private function dev_maint($die = true, $quick = false) { $this->parent->safety = false; $this->parent->dbo->quickmode = true; $report = array(); # output $report[] = "Integrity Check starting at " . date("H:i:s d/m/Y"); # 1 # gets all modules which are linked from other modules in a mandatory manner $linkable = array(); foreach ($this->parent->modules as $name => $module) { foreach ($module->fields as $fname => $field) { if ($field[CONS_XML_TIPO] == CONS_TIPO_LINK && (!isset($field[CONS_XML_JOIN]) || $field[CONS_XML_JOIN] == "inner") && !in_array($field[CONS_XML_MODULE], $linkable)) { $linkable[] = $field[CONS_XML_MODULE]; } # <-- for link test if ($field[CONS_XML_TIPO] == CONS_TIPO_UPLOAD && !in_array($name, $linkable)) { $linkable[] = $name; } # <-- for upload test (will load keys at step 2) } } $report[] = "Preloading keys on " . count($linkable) . " tables ..."; $keystore = array(); # 2 # Loads all keys from all linkable OR uploadable fields into memory for faster access foreach ($linkable as $module) { # for each module that is linked $keys = array(); foreach ($this->parent->modules[$module]->keys as $key) { $keys[] = $key; } # SELECT keys $sql = "SELECT " . implode(",", $keys) . " FROM " . $this->parent->modules[$module]->dbname; $this->parent->dbo->query($sql, $r, $n); $report[] = "-Module '" . $this->parent->modules[$module]->dbname . "' opened with {$n} entries, each with " . count($keys) . " key" . (count($keys) > 1 ? "s" : ""); $keystore[$this->parent->modules[$module]->name] = array(); for ($c = 0; $c < $n; $c++) { $keystore[$this->parent->modules[$module]->name][] = implode("_", $this->parent->dbo->fetch_row($r)); } # fills up memory with searchable keys } if ($this->parent->nearTimeLimit()) { $report[] = "Aborted due to timeout. Integrity.log saved at cache folder. Displaying now"; cWriteFile(CONS_PATH_CACHE . $_SESSION['CODE'] . "/integrity.log", implode("\r\n", $report)); echo "<pre>" . implode("<br/>", $report) . "</pre>"; return false; } # 3 # Performs the integrity check per se $report[] = "Performing foreign key integrity check..."; $hadError = false; foreach ($this->parent->modules as $name => $module) { #now again for ALL modules $desired = array(); # what fields I want $moduleLinks = array(); # what modules this links foreach ($module->keys as $key) { $desired[] = $key; } # retrieve keys foreach ($module->fields as $fname => $field) { # for each field ... if ($field[CONS_XML_TIPO] == CONS_TIPO_LINK && (!isset($field[CONS_XML_JOIN]) || $field[CONS_XML_JOIN] == "inner") && !in_array($fname, $desired)) { # which is a mandatory link and is not yet on list $desired[] = $fname; # add first key $moduleLinks[] = $field[CONS_XML_MODULE]; # add module to wanted modules if ($this->parent->modules[$field[CONS_XML_MODULE]]->keys > 1) { # more than one key ... $rk = $this->parent->modules[$field[CONS_XML_MODULE]]->keys; # get all keys array_shift($rk); // first key is set with my local name foreach ($rk as $fkey) { $desired[] = $fname . "_" . $fkey; } # 2+ key to a multikey item } } } if (count($moduleLinks) > 0) { # I want something from this module $sql = "SELECT " . implode(",", $desired) . " FROM " . $module->dbname; $this->parent->dbo->query($sql, $r, $n); $report[] = "-Performing integrity check on table '" . $module->dbname . "' with {$n} entries"; for ($c = 0; $c < $n; $c++) { $data = $this->parent->dbo->fetch_row($r); # keys, then desired in module order $delKey = array(); $myKeys = array(); foreach ($module->keys as $key) { $delKey[$key] = array_shift($data); if (in_array($key, $module->keys)) { $myKeys[] = $delKey[$key]; } } $myKeys = implode("_", $myKeys); // removed keys from start of $data, now test remove keys foreach ($moduleLinks as $modLink) { $searchableKeys = array(); foreach ($this->parent->modules[$modLink]->keys as $rK) { $searchableKeys[] = array_shift($data); } $searchableKeys = implode("_", $searchableKeys); if ($searchableKeys == "") { $report[] = "--Unable to find keys at {$modLink}"; } else { if (!in_array($searchableKeys, $keystore[$modLink])) { $module->runAction(CONS_ACTION_DELETE, $delKey, true, false); $report[] = "--Missing keys {$searchableKeys} to {$modLink} @ {$name} keys {$myKeys} (<strong>Item deleted since mandatory link cannot be null</strong>)"; } } } } #for each item } # which have something I need to check if ($this->parent->nearTimeLimit()) { $report[] = "Aborted due to timeout. Integrity.log saved at cache folder. Displaying now"; cWriteFile(CONS_PATH_CACHE . $_SESSION['CODE'] . "/integrity.log", implode("\r\n", $report)); echo "<pre>" . implode("<br/>", $report) . "</pre>"; return false; } } # for each module if ($hadError) { $report[] = "<strong>*** (ERR) DATABASE Integrity reported errors! ***</strong>"; } else { $report[] = "<strong>No DB Integrity errors!</strong>"; } # 4 # Performs file integrity check: lists all files on fmanager and checks if there are orphan files. Also update database with file existense $report[] = "Performing file orphan check and updating file markers on database..."; $hadError2 = false; $filesChecked = 0; $orphans = 0; $notorphans = 0; foreach ($this->parent->modules as $name => $module) { $uploadFields = array(); $setStatement = ""; foreach ($module->fields as $fname => $field) { # for each field ... if ($field[CONS_XML_TIPO] == CONS_TIPO_UPLOAD) { # which is an upload $uploadFields[] = $fname; $setStatement = $fname . "='n',"; // should expect files in the format [field]_[ids]_[thumbids].jpg // some thumbnails will be inside the t/ folder, same file style } } if (count($uploadFields) > 0) { $setStatement = substr($setStatement, 0, strlen($setStatement) - 1); $sql = "UPDATE " . $module->dbname . " SET {$setStatement}"; $ok = $this->parent->dbo->simpleQuery($sql); $existingFiles = listFiles(CONS_FMANAGER . $name, '@^(.*)$@', false, false, true); $report[] = "-Module {$name} has uploads: " . count($existingFiles) . " files found at " . CONS_FMANAGER . $name . "/. " . ($ok ? "Database markers reset" : "Unable to reset markers") . " ..."; foreach ($existingFiles as $file) { $filesChecked++; if (strpos($file, "/") !== false) { $filename = explode("/", $file); $filename = array_pop($filename); } else { $filename = $file; } foreach ($uploadFields as $field) { # FIELD _KEYS Tb# EXT if (preg_match("/" . $field . "_(.*)_[0-9]\\..+/", $filename, $regs)) { $keys = $regs[1]; if (!in_array($keys, $keystore[$name])) { $hadError2 = true; $orphans++; if (!$quick) { @unlink(CONS_FMANAGER . $name . "/" . $file); $report[] = "--Orphan file: {$file} (<strong>file deleted</strong>)"; } else { $report[] = "--Orphan file: {$file} (<strong>not deleted because this is a quick run</strong>)"; } } else { $keys = explode("_", $keys); $keys2 = array(); foreach ($module->keys as $key) { $keys2[] = "{$key}=" . array_shift($keys); } $keys = implode(" AND ", $keys2); $sql = "UPDATE " . $module->dbname . " SET {$field}='y' WHERE {$keys}"; if ($this->parent->dbo->simpleQuery($sql)) { $notorphans++; } } } } } } } if ($hadError2) { $report[] = "<strong>*** (ERR) Orphan files detected in {$orphans} of {$filesChecked} files. {$notorphans} files marked as existent on DB ***</strong>"; } else { $report[] = "<strong>No Orphan files in {$filesChecked} files. {$notorphans} files marked as existent on DB </strong>"; } # 5 # Checks useless files that might have been uploaded, like thumbs.db and _notes (stupid dreamweaver) $hadError3 = false; $orphans = 0; $existingFiles = listFiles(CONS_PATH_PAGES . $_SESSION['CODE'], '@^(.*)$@', false, false, true); $report[] = "Client has " . count($existingFiles) . " files:"; foreach ($existingFiles as $file) { // Thumbs.db, _notes (folder) $l = strlen($file); if (substr($file, $l - 6) == "_notes") { recursive_del(CONS_PATH_PAGES . $_SESSION['CODE'] . "/{$file}"); $report[] = " _notes folder: {$file} (<strong>folder deleted</strong>)"; } else { if (substr($file, $l - 8) == "humbs.db") { unlink(CONS_PATH_PAGES . $_SESSION['CODE'] . "/{$file}"); $report[] = " Thumbs.db: {$file} (<strong>file deleted</strong>)"; } } } if ($orphans > 0) { $hadError3 = true; $report[] = "<strong>-Useless files found: {$orphans} files</strong>"; } else { $report[] = "<strong>-No useless files</strong>"; } # - # End if (!$quick) { $report[] = "<strong>Integrity Check complete at " . date("H:i:s d/m/Y") . " with " . $this->parent->dbo->dbc . " DB queries run taking " . $this->parent->dbo->dbt . "ms</strong>"; echo "<pre>" . implode("<br/>", $report) . "</pre>"; } if ($die) { $this->parent->close(true); die; } return $hadError3 || $hadError2 || $hadError; }
<?php if (isset($_REQUEST['haveinfo'])) { $this->dbo->simpleQuery("TRUNCATE dbp"); $this->dbo->simpleQuery("TRUNCATE dba"); $this->dbo->simpleQuery("TRUNCATE dbb"); $this->dbo->simpleQuery("TRUNCATE dbmk"); $this->dbo->simpleQuery("TRUNCATE dbl"); $this->dbo->simpleQuery("TRUNCATE session_manager"); $this->dbo->simpleQuery("TRUNCATE bb_forum"); $this->dbo->simpleQuery("TRUNCATE bb_thread"); $this->dbo->simpleQuery("TRUNCATE bb_post"); $this->dbo->simpleQuery("TRUNCATE app_content"); $this->dbo->simpleQuery("TRUNCATE sys_seo"); $this->dbo->simpleQuery("TRUNCATE sys_undo"); $this->dbo->simpleQuery("DROP TABLE auth_users,auth_groups"); $this->dimconfig['presciastage'] = 'start'; $this->saveConfig(); // purge uploaded files $folder = CONS_PATH_PAGES . $_SESSION['CODE'] . "/files/presciator/"; recursive_del($folder, true); $folder = CONS_PATH_PAGES . $_SESSION['CODE'] . "/files/_undodata/"; recursive_del($folder, true); // purge logs $listFiles = listFiles(CONS_PATH_LOGS, "/^([^a]).*(\\.log)\$/i", false, false, true); foreach ($listFiles as $file) { @unlink(CONS_PATH_LOGS . $file); } $this->action = "index"; $this->headerControl->internalFoward("/index.html"); }
// cron notifies foreach ($this->onCron as $scriptName) { $this->loadedPlugins[$scriptName]->onCron(false); if ($this->nearTimeLimit()) { $this->errorControl->raise(112, 'onCron-stage'); $this->safety = true; # aborts cron as of now return; } } if (strpos(CONS_MASTERDOMAINS, $_SESSION['DOMAIN']) !== false) { $this->cacheControl->logCacheThrottle(); } if (!$this->nearTimeLimit() && isset($this->dimconfig['_recurseDelOverflow']) && $this->dimconfig['_recurseDelOverflow'] == 1) { # clean up object cache, unable to complete on daily clean up $allok = recursive_del(CONS_PATH_CACHE . $_SESSION['CODE'] . "/", false, 'cache', 250); if (!$allok) { $this->dimconfig['_recurseDelOverflow'] = 1; } else { $this->dimconfig['_recurseDelOverflow'] = 0; } } if (CONS_CRONDBBACKUP && !$this->nearTimeLimit() && ($this->dimconfig['_scheduledCronDay'] == 0 || date("d") == $this->dimconfig['_scheduledCronDay']) && $this->dimconfig['_scheduledCronDayHour'] == date("H")) { // special optimization and backup $this->errorControl->raise(113); $mods = array(); foreach ($this->modules as $name => $module) { if ($module->dbname != "" && !in_array($module->dbname, $mods)) { $mods[] = $module->dbname; } }
function loadMetadata() { if (!$this->debugmode) { return parent::loadMetadata(); } $this->errorControl->raise(1000); $this->log = array(); // we don't want the above "log" to cause an abort (yes, this function uses the log size to confirm an error - lame but extremelly effective) $this->allModulesLoaded = true; # initial clean up and check if (!is_dir(CONS_PATH_TEMP)) { safe_mkdir(CONS_PATH_TEMP); } if (!is_dir(CONS_PATH_CACHE)) { safe_mkdir(CONS_PATH_CACHE); } if (!is_dir(CONS_PATH_DINCONFIG)) { safe_mkdir(CONS_PATH_DINCONFIG); } if (!is_dir(CONS_PATH_CACHE . "locale/")) { safe_mkdir(CONS_PATH_CACHE . "locale/"); } if (!is_dir(CONS_PATH_LOGS)) { safe_mkdir(CONS_PATH_LOGS); } if (!is_dir(CONS_PATH_LOGS . $_SESSION['CODE'] . "/")) { safe_mkdir(CONS_PATH_LOGS . $_SESSION['CODE'] . "/"); } if (!is_dir(CONS_PATH_DINCONFIG . $_SESSION['CODE'] . "/")) { safe_mkdir(CONS_PATH_DINCONFIG . $_SESSION['CODE'] . "/"); } if (!is_dir(CONS_PATH_CACHE . $_SESSION['CODE'] . "/")) { safe_mkdir(CONS_PATH_CACHE . $_SESSION['CODE'] . "/"); } if (!is_dir(CONS_PATH_CACHE . $_SESSION['CODE'] . "/meta/")) { safe_mkdir(CONS_PATH_CACHE . $_SESSION['CODE'] . "/meta/"); } if (!is_dir(CONS_PATH_CACHE . $_SESSION['CODE'] . "/meta/locale")) { safe_mkdir(CONS_PATH_CACHE . $_SESSION['CODE'] . "/meta/locale/"); } if (!is_dir(CONS_PATH_PAGES . $_SESSION['CODE'] . "/")) { safe_mkdir(CONS_PATH_PAGES . $_SESSION['CODE'] . "/"); } if (!is_dir(CONS_PATH_PAGES . $_SESSION['CODE'] . "/actions/")) { safe_mkdir(CONS_PATH_PAGES . $_SESSION['CODE'] . "/actions"); } if (!is_dir(CONS_PATH_PAGES . $_SESSION['CODE'] . "/content/")) { safe_mkdir(CONS_PATH_PAGES . $_SESSION['CODE'] . "/content"); } if (!is_dir(CONS_PATH_PAGES . $_SESSION['CODE'] . "/_config/locale/")) { safe_mkdir(CONS_PATH_PAGES . $_SESSION['CODE'] . "/_config/locale"); } if (!is_dir(CONS_PATH_PAGES . $_SESSION['CODE'] . "/files/")) { safe_mkdir(CONS_PATH_PAGES . $_SESSION['CODE'] . "/files"); } if (!is_dir(CONS_PATH_PAGES . $_SESSION['CODE'] . "/template/")) { safe_mkdir(CONS_PATH_PAGES . $_SESSION['CODE'] . "/template"); copy(CONS_PATH_SETTINGS . "defaults/basefile.html", CONS_PATH_PAGES . $_SESSION['CODE'] . "/template/basefile.html"); copy(CONS_PATH_SETTINGS . "defaults/index.html", CONS_PATH_PAGES . $_SESSION['CODE'] . "/template/index.html"); } if (!is_dir(CONS_PATH_PAGES . $_SESSION['CODE'] . "/mail/")) { safe_mkdir(CONS_PATH_PAGES . $_SESSION['CODE'] . "/mail"); } # Dimconfig if (is_file(CONS_PATH_DINCONFIG . $_SESSION['CODE'] . "/din.dat")) { $this->dimconfig = unserialize(cReadFile(CONS_PATH_DINCONFIG . $_SESSION['CODE'] . "/din.dat")); } if ($this->dimconfig === false) { $this->dimconfig = array(); } # Error on load $this->checkConfig(); # clear the meta cache if (!$this->offlineMode) { $files = listFiles(CONS_PATH_CACHE . $_SESSION['CODE'] . "/meta/"); foreach ($files as $file) { if (is_file(CONS_PATH_CACHE . $_SESSION['CODE'] . "/meta/" . $file)) { @unlink(CONS_PATH_CACHE . $_SESSION['CODE'] . "/meta/" . $file); } } if (!$this->checkinstall()) { $this->errorControl->raise(118, array_unshift($this->log)); } if (isset($_REQUEST['nocache'])) { recursive_del(CONS_PATH_CACHE . $_SESSION['CODE'] . "/pages/", true); recursive_del(CONS_PATH_CACHE . $_SESSION['CODE'] . "/", false, 'cache'); } } # If no database, we are done if ($this->dbless) { return count($this->log) == 0; } # Search all necessary model files $parseXMLparams = array(C_XML_RAW => true, C_XML_AUTOPARSE => true, C_XML_REMOVECOMMENTS => true); $xml = new xmlHandler(); $model = is_file(CONS_PATH_SETTINGS . "default.xml") ? cReadFile(CONS_PATH_SETTINGS . "default.xml") . "\n" : ''; foreach ($this->loadedPlugins as $scriptName => $scriptObj) { if (is_file(CONS_PATH_SYSTEM . "plugins/" . $scriptName . "/meta.xml")) { $model .= cReadFile(CONS_PATH_SYSTEM . "plugins/" . $scriptName . "/meta.xml") . "\n"; } } unset($scriptName); unset($scriptObj); if (is_file(CONS_PATH_PAGES . $_SESSION['CODE'] . "/_config/meta.xml")) { $model .= cReadFile(CONS_PATH_PAGES . $_SESSION['CODE'] . "/_config/meta.xml") . "\n"; } $model = $xml->parseXML($model, $parseXMLparams, true); unset($xml); if ($model === false) { $this->errorControl->raise(119); } # browses the XML and loads modules $model =& $model->getbranch(0); $total = $model->total(); $relation = array(); # foreign keys are only created later $lastLoad = ""; for ($c = 0; $c < $total; $c++) { # for each module ... $thisbranch =& $model->getbranch($c); $total_campos = $thisbranch->total(); # creates the module as from XML settings $module = strtolower($thisbranch->data[0]); $param =& $thisbranch->data[1]; $dbname = strtolower(isset($param['dbname']) ? $param['dbname'] : ''); foreach ($this->modules as $name => $otherModule) { if ($otherModule->dbname == $dbname && $dbname != "" && $module != $otherModule->name) { $this->errorControl->raise(120, $otherModule->name, $name, $dbname); } } if ($module == '') { $this->errorControl->raise(107, $dbname, "XML error", "Module after {$lastLoad} is corrupt"); } $this->loadModule($module, $dbname); #MODULE CREATE $lastLoad = $module; # loads standard data from this object --------------------------------------------------------------------- # read parameters for the MODULE foreach ($this->moduleOptions as $mo) { $this->modules[$module]->options[$mo[0]] = $mo[3] != '' ? array() : ''; } if (is_array($param)) { foreach ($param as $pkey => $pcontent) { $pkey = strtolower($pkey); switch ($pkey) { case "key": case "keys": # will use default auto_increment "id" if none specified. If you specify more than one, none will be auto_increment and the system will use auto-numbering $this->modules[$module]->keys = explode(",", $pcontent); break; case "title": $this->modules[$module]->title = strtolower($pcontent); break; case "volatile": # this module can be deleted as a stand-alone volatile item $this->modules[$module]->options[CONS_MODULE_VOLATILE] = strtolower($pcontent) == "true"; break; case "parent": $this->modules[$module]->options[CONS_MODULE_PARENT] = strtolower($pcontent); // field which denotes parenthood break; case "plugins": case "plugin": $this->modules[$module]->plugins = explode(",", strtolower($pcontent)); break; case "order": $this->modules[$module]->order = trim(strtolower($pcontent)); break; case "permissionoverride": if (strlen($pcontent) >= 9) { $this->modules[$module]->permissionOverride = substr(strtolower($pcontent), 0, 9); } break; case "linker": $this->modules[$module]->linker = true; break; case "systemmodule": $this->modules[$module]->options[CONS_MODULE_SYSTEM] = true; break; case "autoclean": $this->modules[$module]->options[CONS_MODULE_AUTOCLEAN] = $pcontent; break; case "meta": $this->modules[$module]->options[CONS_MODULE_META] = $pcontent; break; case "disallowmultiple": if (strtolower($pcontent) == "true") { $this->modules[$module]->options[CONS_MODULE_DISALLOWMULTIPLE] = true; } else { unset($this->modules[$module]->options[CONS_MODULE_DISALLOWMULTIPLE]); } break; case "noundo": if (strtolower($pcontent) == "true") { $this->modules[$module]->options[CONS_MODULE_NOUNDO] = true; } else { unset($this->modules[$module]->options[CONS_MODULE_NOUNDO]); } default: if ($pkey != "name" && $pkey != "dbname") { $isMO = false; foreach ($this->moduleOptions as $mo) { if ($mo[1] == $pkey) { $isMO = true; if ($mo[2]) { $pcontent = strtolower($pcontent); } if ($mo[3] != '') { $pcontent = explode($mo[3], $pcontent); } $this->modules[$module]->options[$mo[0]] = $pcontent; break; } } if (!$isMO) { $this->modules[$module]->options[$pkey] = $pcontent; } } break; } } #foreach unset($pkey); unset($pcontent); } if ($this->modules[$module]->options[CONS_MODULE_PARENT] != '' && strpos($this->modules[$module]->order, $this->modules[$module]->options[CONS_MODULE_PARENT]) === false) { # in tree mode, the field that defines parenthood must be in the order clause, the first if possible $this->modules[$module]->order = $this->modules[$module]->options[CONS_MODULE_PARENT] . "+" . ($this->modules[$module]->order != '' ? "," . $this->modules[$module]->order : ''); } # -- ok on reading parameters $campos = array(); $mandatory = 0; # browse FIELDS --------------------------------------------------------------------------------- for ($campo = 0; $campo < $total_campos; $campo++) { $thiscampo =& $thisbranch->getbranch($campo); ## processParameters ######################################### $campos = $this->processParameters($thiscampo, $campos, $module); ############################################################## $nomecampo = strtolower($thiscampo->data[0]); if ($campos[$nomecampo][CONS_XML_TIPO] == CONS_TIPO_LINK) { array_push($relation, array($module, $nomecampo, $campos[$nomecampo][CONS_XML_MODULE])); // if this is a non-mandatory link to myself, called "id_parent", and I don't have parent ... well .. obviously this is it if ($campos[$nomecampo][CONS_XML_MODULE] == $module && !isset($campos[$nomecampo][CONS_XML_MANDATORY]) && $nomecampo == "id_parent" && $this->modules[$module]->options[CONS_MODULE_PARENT] == '') { $this->modules[$module]->options[CONS_MODULE_PARENT] = $nomecampo; } } else { if ($campos[$nomecampo][CONS_XML_TIPO] == CONS_TIPO_SERIALIZED) { // browse fields looking for links foreach ($campos[$nomecampo][CONS_XML_SERIALIZEDMODEL] as $exname => &$exfield) { if ($exfield[CONS_XML_TIPO] == CONS_TIPO_LINK) { array_push($relation, array($module, $nomecampo . ":" . $exname, $exfield[CONS_XML_MODULE])); } } } } # checks if this field can be NULL or NOT depending on options and mandatory setting if (isset($campos[$nomecampo][CONS_XML_SQL]) && $campos[$nomecampo][CONS_XML_SQL] != "") { # relation will not be set if (isset($campos[$nomecampo][CONS_XML_MANDATORY]) || $campos[$nomecampo][CONS_XML_TIPO] == CONS_TIPO_OPTIONS || isset($campos[$nomecampo][CONS_XML_DEFAULT])) { $campos[$nomecampo][CONS_XML_SQL] .= " NOT NULL"; $mandatory++; } else { $campos[$nomecampo][CONS_XML_SQL] .= " NULL"; } if (isset($campos[$nomecampo][CONS_XML_DEFAULT])) { $campos[$nomecampo][CONS_XML_SQL] .= " DEFAULT '" . $campos[$nomecampo][CONS_XML_DEFAULT] . "'"; } } } # this module has a database (it's possible to have modules without a database) if ($this->modules[$module]->dbname != "") { # checks standard key "id" if no key specified if (in_array("id", $this->modules[$module]->keys) && !isset($this->modules[$module]->fields['id']) && !isset($campos['id'])) { if ($this->modules[$module]->linker) { $this->modules[$module]->keys = array(); $keys = 0; foreach ($campos as $fieldname => $fieldobj) { if (isset($fieldobj[CONS_XML_MODULE])) { $keys++; $this->modules[$module]->keys[] = $fieldname; if ($keys == 2) { break; } } } unset($fieldname); unset($fieldobj); } else { $campos['id'][CONS_XML_SQL] = "INT (11) UNSIGNED NOT NULL" . (count($this->modules[$module]->keys) <= 1 ? " AUTO_INCREMENT" : ""); $campos['id'][CONS_XML_TIPO] = CONS_TIPO_INT; if (count($this->modules[$module]->keys) > 1) { $campos['id'][CONS_XML_RESTRICT] = 99; } } } # -- keys (this is done to prevent repeated keys) $chave = $this->modules[$module]->keys; $this->modules[$module]->keys = array(); foreach ($chave as $x => $di) { if (!in_array($di, $this->modules[$module]->keys) && $di != "") { array_push($this->modules[$module]->keys, $di); } } unset($x); unset($di); # if this is a re-definition, will TOTALLY overright the fields (you can redefine fields from the default.xml on the meta.xml) $this->modules[$module]->fields = array_merge($this->modules[$module]->fields, $campos); # -- makes sure all keys are mandatory and present foreach ($this->modules[$module]->keys as $x => $chave) { if (!isset($this->modules[$module]->fields[$chave])) { array_push($this->log, "Key not defined, considering INT 11, please fix the XML: {$module}.{$chave}"); $this->modules[$module]->fields[$chave] = array("CONS_XML_SQL" => "INT (11) UNSIGNED NOT NULL", "CONS_XML_TIPO" => CONS_TIPO_INT); } $this->modules[$module]->fields[$chave][CONS_XML_MANDATORY] = true; // vc keys without case specified, force ucase if ($this->modules[$module]->fields[$chave][CONS_XML_TIPO] == CONS_TIPO_VC && !isset($this->modules[$module]->fields[$chave][CONS_XML_SPECIAL])) { $this->modules[$module]->fields[$chave][CONS_XML_SPECIAL] = "ucase"; } } unset($x); unset($chave); } } # -- foreach module $total_relacoes = count($relation); # check our relationship counts and build proper fields or support tables ------------- for ($c = 0; $c < $total_relacoes; $c++) { $rel = $relation[$c]; # relation: MODULE => FIELD => MODULE or MODULE => SFIELD:FIELD => MODULE for serialized fields if (!isset($this->modules[$rel[0]]) || !isset($this->modules[$rel[2]])) { array_push($this->log, "Error (pass 1) trying to build foreign keys from '" . $rel[0] . "' to '" . $rel[2] . "' at " . $rel[1] . ": one of the modules do not exist, ignoring relation"); } else { $sfield = ""; if (strpos($rel[1], ":") !== false) { #serialized field $field = explode(":", $field); $sfield = $field[0]; $field = $field[1]; } else { $field = $rel[1]; } if (substr($field, 0, 3) != "id_") { array_push($this->log, "All relations to another modules MUST start with id_ on " . $rel[0] . "' to '" . $rel[2] . "' at " . $rel[1] . ": should be id_" . $field . " ?"); } if ($sfield == '') { $this->modules[$rel[2]]->volatile = false; } # keeps volatile if linked from serialized (a.k.a. serialized links are not safe, because they are meant to be dinamic) foreach ($this->modules[$rel[2]]->keys as $x => $chave) { # will create required keys for foreign table, except any one in common with this table if ($chave == "id" || !isset($this->modules[$rel[0]]->fields[$chave])) { # only standard id exists (always link it), or it's not a standard key ... still have to test if it's not a key to this table # basically, this will create the second+ keys on multikey relations if (!($this->modules[$rel[2]]->fields[$chave][CONS_XML_TIPO] == CONS_TIPO_LINK && $this->modules[$rel[2]]->fields[$chave][CONS_XML_MODULE] == $rel[0])) { # ok not a key to this table (the FOREING key is not this table, pay attention! this will still be true for id_parent) if ($sfield == "") { # normal if ($chave == "id") { # uses the name that came in the XML model if (!isset($this->modules[$rel[0]]->fields[$field])) { $this->modules[$rel[0]]->fields[$field] = array(); } $this->modules[$rel[0]]->fields[$field][CONS_XML_SQL] = str_replace("AUTO_INCREMENT", "", $this->modules[$rel[2]]->fields[$chave][CONS_XML_SQL]); $this->modules[$rel[0]]->fields[$field][CONS_XML_TIPO] = CONS_TIPO_LINK; $this->modules[$rel[0]]->fields[$field][CONS_XML_LINKTYPE] = $this->modules[$rel[2]]->fields[$chave][CONS_XML_TIPO] != CONS_TIPO_LINK ? $this->modules[$rel[2]]->fields[$chave][CONS_XML_TIPO] : CONS_TIPO_INT; $this->modules[$rel[0]]->fields[$field][CONS_XML_MODULE] = $rel[2]; # the creation system might have added this already, that's why testing before resetting the array if (isset($this->modules[$rel[0]]->fields[$field][CONS_XML_JOIN]) && $this->modules[$rel[0]]->fields[$field][CONS_XML_JOIN] == "inner" || isset($this->modules[$rel[0]]->fields[$field][CONS_XML_MANDATORY])) { // is set join to INNER or is explicitly mandatory, make sure both are set $this->modules[$rel[0]]->fields[$field][CONS_XML_MANDATORY] = true; if ($x == 0) { $this->modules[$rel[0]]->fields[$field][CONS_XML_JOIN] = "inner"; } } else { // no join mode set (defaults to left), set to left, and no explicit mandatory tag if ($x == 0) { $this->modules[$rel[0]]->fields[$field][CONS_XML_JOIN] = "left"; } $this->modules[$rel[0]]->fields[$field][CONS_XML_SQL] = str_replace("NOT NULL", "NULL", $this->modules[$rel[0]]->fields[$field][CONS_XML_SQL]); } } else { if ($x == 0) { $nome = $field; # first key keeps the original name $this->modules[$rel[0]]->fields[$field][CONS_XML_LINKTYPE] = $this->modules[$rel[2]]->fields[$chave][CONS_XML_TIPO] != CONS_TIPO_LINK ? $this->modules[$rel[2]]->fields[$chave][CONS_XML_TIPO] : CONS_TIPO_INT; } else { $nome = $field . "_" . str_replace("id_", "", $chave); } # creates a composition with the model name and the foreign name $this->modules[$rel[0]]->fields[$nome][CONS_XML_SQL] = str_replace("AUTO_INCREMENT", "", $this->modules[$rel[2]]->fields[$chave][CONS_XML_SQL]); $this->modules[$rel[0]]->fields[$nome][CONS_XML_TIPO] = $x == 0 ? CONS_TIPO_LINK : $this->modules[$rel[2]]->fields[$chave][CONS_XML_TIPO]; $this->modules[$rel[0]]->fields[$nome][CONS_XML_MODULE] = isset($this->modules[$rel[2]]->fields[$chave][CONS_XML_MODULE]) ? $this->modules[$rel[2]]->fields[$chave][CONS_XML_MODULE] : $rel[2]; if (isset($this->modules[$rel[0]]->fields[$field][CONS_XML_JOIN]) && $this->modules[$rel[0]]->fields[$field][CONS_XML_JOIN] == "inner" || isset($this->modules[$rel[0]]->fields[$nome][CONS_XML_MANDATORY])) { $this->modules[$rel[0]]->fields[$nome][CONS_XML_MANDATORY] = true; if ($x == 0) { $this->modules[$rel[0]]->fields[$nome][CONS_XML_JOIN] = "inner"; } } else { if ($x == 0) { $this->modules[$rel[0]]->fields[$nome][CONS_XML_JOIN] = "left"; } unset($this->modules[$rel[0]]->fields[$nome][CONS_XML_MANDATORY]); $this->modules[$rel[0]]->fields[$nome][CONS_XML_SQL] = str_replace("NOT NULL", "NULL", $this->modules[$rel[0]]->fields[$nome][CONS_XML_SQL]); } } } else { # serialized if ($chave == "id") { # uses the name that came in the XML model if (!isset($this->modules[$rel[0]]->fields[$sfield][CONS_XML_SERIALIZEDMODEL][$field])) { $this->modules[$rel[0]]->fields[$sfield][CONS_XML_SERIALIZEDMODEL][$field] = array(); } $this->modules[$rel[0]]->fields[$sfield][CONS_XML_SERIALIZEDMODEL][$field][CONS_XML_SQL] = str_replace("AUTO_INCREMENT", "", $this->modules[$rel[2]]->fields[$chave][CONS_XML_SQL]); $this->modules[$rel[0]]->fields[$sfield][CONS_XML_SERIALIZEDMODEL][$field][CONS_XML_TIPO] = CONS_TIPO_LINK; $this->modules[$rel[0]]->fields[$sfield][CONS_XML_SERIALIZEDMODEL][$field][CONS_XML_LINKTYPE] = $this->modules[$rel[2]]->fields[$chave][CONS_XML_TIPO] != CONS_TIPO_LINK ? $this->modules[$rel[2]]->fields[$chave][CONS_XML_TIPO] : CONS_TIPO_INT; $this->modules[$rel[0]]->fields[$sfield][CONS_XML_SERIALIZEDMODEL][$field][CONS_XML_MODULE] = $rel[2]; # serialized links cannot be "inner" $this->modules[$rel[0]]->fields[$sfield][CONS_XML_SERIALIZEDMODEL][$field][CONS_XML_JOIN] = "left"; if (isset($this->modules[$rel[0]]->fields[$sfield][CONS_XML_SERIALIZEDMODEL][$field][CONS_XML_MANDATORY])) { $this->modules[$rel[0]]->fields[$sfield][CONS_XML_SERIALIZEDMODEL][$field][CONS_XML_MANDATORY] = true; } else { $this->modules[$rel[0]]->fields[$sfield][CONS_XML_SERIALIZEDMODEL][$field][CONS_XML_SQL] = str_replace("NOT NULL", "NULL", $this->modules[$rel[0]]->fields[$sfield][CONS_XML_SERIALIZEDMODEL][$field][CONS_XML_SQL]); } } else { if ($x == 0) { $nome = $field; # first key keeps the original name $this->modules[$rel[0]]->fields[$sfield][CONS_XML_SERIALIZEDMODEL][$field][CONS_XML_LINKTYPE] = $this->modules[$rel[2]]->fields[$chave][CONS_XML_TIPO] != CONS_TIPO_LINK ? $this->modules[$rel[2]]->fields[$chave][CONS_XML_TIPO] : CONS_TIPO_INT; } else { $nome = $field . "_" . str_replace("id_", "", $chave); } # creates a composition with the model name and the foreign name $this->modules[$rel[0]]->fields[$sfield][CONS_XML_SERIALIZEDMODEL][$nome][CONS_XML_SQL] = str_replace("AUTO_INCREMENT", "", $this->modules[$rel[2]]->fields[$chave][CONS_XML_SQL]); $this->modules[$rel[0]]->fields[$sfield][CONS_XML_SERIALIZEDMODEL][$nome][CONS_XML_TIPO] = $x == 0 ? CONS_TIPO_LINK : $this->modules[$rel[2]]->fields[$chave][CONS_XML_TIPO]; $this->modules[$rel[0]]->fields[$sfield][CONS_XML_SERIALIZEDMODEL][$nome][CONS_XML_MODULE] = isset($this->modules[$rel[2]]->fields[$chave][CONS_XML_MODULE]) ? $this->modules[$rel[2]]->fields[$chave][CONS_XML_MODULE] : $rel[2]; # serialized links cannot be "inner" $this->modules[$rel[0]]->fields[$sfield][CONS_XML_SERIALIZEDMODEL][$nome][CONS_XML_JOIN] = "left"; if (isset($this->modules[$rel[0]]->fields[$sfield][CONS_XML_SERIALIZEDMODEL][$nome][CONS_XML_MANDATORY])) { $this->modules[$rel[0]]->fields[$sfield][CONS_XML_SERIALIZEDMODEL][$nome][CONS_XML_MANDATORY] = true; } else { $this->modules[$rel[0]]->fields[$sfield][CONS_XML_SERIALIZEDMODEL][$nome][CONS_XML_SQL] = str_replace("NOT NULL", "NULL", $this->modules[$rel[0]]->fields[$sfield][CONS_XML_SERIALIZEDMODEL][$nome][CONS_XML_SQL]); } } } # sfield? } } # secondary (multikey)? } # foreach unset($x); unset($chave); if (!isset($this->modules[$rel[0]]->fields[$field][CONS_XML_SQL])) { array_push($this->log, "Error (pass 2) trying to build foreing keys from " . $rel[0] . " to " . $rel[2] . " at " . $field . ": ignoring relation"); } } } # foreach for relations // now some automatic settings since all modules are loaded, and consistency check on build, partOf, etc --------------------- $cacheLinkNum = array(); // module => modules which link to this foreach ($this->modules as $mname => &$module) { $links = 0; $fieldsRequiredToLinks = 0; foreach ($module->fields as $name => $field) { // check for linker modules if ($field[CONS_XML_TIPO] == CONS_TIPO_LINK && $field[CONS_XML_MODULE] != $mname) { // links to OTHER link not myself $links++; # do not count PARENTS as links $fieldsRequiredToLinks += count($this->modules[$field[CONS_XML_MODULE]]->keys); # a module can have more than one key, thus to know if this module is a linker module, we need to check if ALL THIS HAVE are the keys for 2 modules // vc links that have no case specified, force to upper if ($field[CONS_XML_TIPO] == CONS_TIPO_LINK && $field[CONS_XML_LINKTYPE] == CONS_TIPO_VC && !isset($field[CONS_XML_SPECIAL])) { $this->modules[$mname]->fields[$name][CONS_XML_SPECIAL] = "ucase"; } } if (isset($field[CONS_XML_FILTEREDBY])) { foreach ($field[CONS_XML_FILTEREDBY] as $fbname) { if (!isset($module->fields[$fbname])) { $this->log[] = "Error on filteredby for {$mname}.{$name}: {$fbname} does not exist"; } else { if (!isset($this->modules[$module->fields[$fbname][CONS_XML_MODULE]])) { $this->log[] = "Error on filteredby for {$mname}.{$name}: module defined in {$fbname} does not exist"; } } } } } if ($links == 2 && count($module->fields) == $fieldsRequiredToLinks || $this->modules[$mname]->linker) { # this is a linker module! $this->modules[$mname]->linker = true; } if ($this->modules[$mname]->title == "" && !$this->modules[$mname]->options[CONS_MODULE_SYSTEM] && !$this->modules[$mname]->linker) { $this->modules[$mname]->title = $this->modules[$mname]->keys[0]; // first key } } # here we finished the automatic settings # load plugins that are defined by METADATA foreach ($this->modules as $name => &$module) { foreach ($module->plugins as $sname) { if (!isset($this->loadedPlugins[$sname])) { $this->addPlugin($sname, $name); } else { $this->loadedPlugins[$sname]->moduleRelation = $name; } } } foreach ($this->loadedPlugins as $sname => $obj) { if ($obj->name == '' || $obj->name != $sname) { $this->errorControl->raise(9, $obj->name, $sname); } } # DIE FREAKING THUMBS.DB, DIE! function dieFreakingThumbs($folder) { if ($folder[strlen($folder) - 1] != '/') { $folder .= "/"; } foreach (glob($folder . "*") as $file) { if (is_dir($file)) { dieFreakingThumbs($file); } else { $arf = explode(".", $file); if (array_pop($arf) == 'db') { @unlink($file); } } } } dieFreakingThumbs(CONS_PATH_PAGES . $_SESSION['CODE'] . "/"); $customxml = is_file(CONS_PATH_PAGES . $_SESSION["CODE"] . "/_config/custom.xml") ? cReadFile(CONS_PATH_PAGES . $_SESSION["CODE"] . "/_config/custom.xml") : ''; # All plugins are loaded, check their manifest and customs foreach ($this->loadedPlugins as $sname => $plugin) { if (is_file(CONS_PATH_SYSTEM . "plugins/{$sname}/payloadmanifest.php")) { $copyFiles = (include CONS_PATH_SYSTEM . "plugins/{$sname}/payloadmanifest.php"); foreach ($copyFiles as $from => $to) { if ($from[strlen($from) - 1] == "/" && is_dir($from) && (!is_dir($to) || !CONS_ONSERVER && isset($_REQUEST['nocache']))) { // FOLDER if (!function_exists('recursive_copy')) { include_once CONS_PATH_INCLUDE . "recursive_copy.php"; } recursive_copy($from, $to); } else { if (is_file($from) && (!is_file($to) || !CONS_ONSERVER && isset($_REQUEST['nocache']))) { // FILE $path = explode("/", $to); array_pop($path); // bye file $path = implode("/", $path); makeDirs($path); copy($from, $to); } } } } if (is_file(CONS_PATH_SYSTEM . "plugins/{$sname}/custom.xml")) { $customxml .= cReadFile(CONS_PATH_SYSTEM . "plugins/{$sname}/custom.xml"); } } # Read custom metadata for dimconfig if ($customxml != '') { $parseXMLparams = array(C_XML_RAW => true, C_XML_AUTOPARSE => true, C_XML_REMOVECOMMENTS => true); $xml = new xmlHandler(); $customxml = $xml->parseXML($customxml, $parseXMLparams, true); if ($customxml === false) { $this->errorControl->raise(180); } unset($xml); $customxml =& $customxml->getbranch(0); $total = $customxml->total(); $dimconfigMD = array(); // MetaData ------------------------------------- for ($c = 0; $c < $total; $c++) { # for each module ... $thisbranch =& $customxml->getbranch($c); $configname = strtolower($thisbranch->data[0]); if (!isset($this->dimconfig[$configname])) { $this->dimconfig[$configname] = ''; } $dimconfigMD = $this->processParameters($thisbranch, $dimconfigMD, ''); } foreach ($dimconfigMD as $name => $field) { if ($field[CONS_XML_TIPO] == CONS_TIPO_UPLOAD && (!isset($field['location']) || $field['location'][0] == '/')) { $this->errorControl->raise(181, $name, 'dimconfig'); } if ($field[CONS_XML_TIPO] != CONS_TIPO_ENUM) { unset($dimconfigMD[$name][CONS_XML_SQL]); } } cWriteFile(CONS_PATH_CACHE . $_SESSION['CODE'] . "/meta/_dimconfig.dat", serialize($dimconfigMD)); // this defines the type of each item on dimconfig } # Apply and raise metadata $this->applyMetaData(); # no log = no error return $sucess = count($this->log) == 0; }