/** * Return all non-excluded fields of a record as HTML table * * @return string */ public function show() { if (!strlen($this->intId)) { return ''; } $objRow = $this->Database->prepare("SELECT * FROM " . $this->strTable . " WHERE id=?")->limit(1)->execute($this->intId); if ($objRow->numRows < 1) { return ''; } $count = 1; $return = ''; $row = $objRow->row(); // Get the order fields $objDcaExtractor = \DcaExtractor::getInstance($this->strTable); $arrOrder = $objDcaExtractor->getOrderFields(); // Get all fields $fields = array_keys($row); $allowedFields = array('id', 'pid', 'sorting', 'tstamp'); if (is_array($GLOBALS['TL_DCA'][$this->strTable]['fields'])) { $allowedFields = array_unique(array_merge($allowedFields, array_keys($GLOBALS['TL_DCA'][$this->strTable]['fields']))); } // Use the field order of the DCA file $fields = array_intersect($allowedFields, $fields); // Show all allowed fields foreach ($fields as $i) { if (!in_array($i, $allowedFields) || $GLOBALS['TL_DCA'][$this->strTable]['fields'][$i]['inputType'] == 'password' || $GLOBALS['TL_DCA'][$this->strTable]['fields'][$i]['eval']['doNotShow'] || $GLOBALS['TL_DCA'][$this->strTable]['fields'][$i]['eval']['hideInput']) { continue; } // Special treatment for table tl_undo if ($this->strTable == 'tl_undo' && $i == 'data') { continue; } $value = deserialize($row[$i]); // Decrypt the value if ($GLOBALS['TL_DCA'][$this->strTable]['fields'][$i]['eval']['encrypt']) { $value = \Encryption::decrypt($value); } $class = $count++ % 2 == 0 ? ' class="tl_bg"' : ''; // Get the field value if (isset($GLOBALS['TL_DCA'][$this->strTable]['fields'][$i]['foreignKey'])) { $temp = array(); $chunks = explode('.', $GLOBALS['TL_DCA'][$this->strTable]['fields'][$i]['foreignKey'], 2); foreach ((array) $value as $v) { $objKey = $this->Database->prepare("SELECT " . $chunks[1] . " AS value FROM " . $chunks[0] . " WHERE id=?")->limit(1)->execute($v); if ($objKey->numRows) { $temp[] = $objKey->value; } } $row[$i] = implode(', ', $temp); } elseif ($GLOBALS['TL_DCA'][$this->strTable]['fields'][$i]['inputType'] == 'fileTree' || in_array($i, $arrOrder)) { if (is_array($value)) { foreach ($value as $kk => $vv) { $value[$kk] = $vv ? \StringUtil::binToUuid($vv) : ''; } $row[$i] = implode(', ', $value); } else { $row[$i] = $value ? \StringUtil::binToUuid($value) : ''; } } elseif (is_array($value)) { foreach ($value as $kk => $vv) { if (is_array($vv)) { $vals = array_values($vv); $value[$kk] = $vals[0] . ' (' . $vals[1] . ')'; } } $row[$i] = implode(', ', $value); } elseif ($GLOBALS['TL_DCA'][$this->strTable]['fields'][$i]['eval']['rgxp'] == 'date') { $row[$i] = $value ? \Date::parse(\Config::get('dateFormat'), $value) : '-'; } elseif ($GLOBALS['TL_DCA'][$this->strTable]['fields'][$i]['eval']['rgxp'] == 'time') { $row[$i] = $value ? \Date::parse(\Config::get('timeFormat'), $value) : '-'; } elseif ($GLOBALS['TL_DCA'][$this->strTable]['fields'][$i]['eval']['rgxp'] == 'datim' || in_array($GLOBALS['TL_DCA'][$this->strTable]['fields'][$i]['flag'], array(5, 6, 7, 8, 9, 10)) || $i == 'tstamp') { $row[$i] = $value ? \Date::parse(\Config::get('datimFormat'), $value) : '-'; } elseif ($GLOBALS['TL_DCA'][$this->strTable]['fields'][$i]['inputType'] == 'checkbox' && !$GLOBALS['TL_DCA'][$this->strTable]['fields'][$i]['eval']['multiple']) { $row[$i] = $value != '' ? $GLOBALS['TL_LANG']['MSC']['yes'] : $GLOBALS['TL_LANG']['MSC']['no']; } elseif ($GLOBALS['TL_DCA'][$this->strTable]['fields'][$i]['inputType'] == 'textarea' && ($GLOBALS['TL_DCA'][$this->strTable]['fields'][$i]['eval']['allowHtml'] || $GLOBALS['TL_DCA'][$this->strTable]['fields'][$i]['eval']['preserveTags'])) { $row[$i] = specialchars($value); } elseif (is_array($GLOBALS['TL_DCA'][$this->strTable]['fields'][$i]['reference'])) { $row[$i] = isset($GLOBALS['TL_DCA'][$this->strTable]['fields'][$i]['reference'][$row[$i]]) ? is_array($GLOBALS['TL_DCA'][$this->strTable]['fields'][$i]['reference'][$row[$i]]) ? $GLOBALS['TL_DCA'][$this->strTable]['fields'][$i]['reference'][$row[$i]][0] : $GLOBALS['TL_DCA'][$this->strTable]['fields'][$i]['reference'][$row[$i]] : $row[$i]; } elseif ($GLOBALS['TL_DCA'][$this->strTable]['fields'][$i]['eval']['isAssociative'] || array_is_assoc($GLOBALS['TL_DCA'][$this->strTable]['fields'][$i]['options'])) { $row[$i] = $GLOBALS['TL_DCA'][$this->strTable]['fields'][$i]['options'][$row[$i]]; } else { $row[$i] = $value; } // Label if (isset($GLOBALS['TL_DCA'][$this->strTable]['fields'][$i]['label'])) { $label = is_array($GLOBALS['TL_DCA'][$this->strTable]['fields'][$i]['label']) ? $GLOBALS['TL_DCA'][$this->strTable]['fields'][$i]['label'][0] : $GLOBALS['TL_DCA'][$this->strTable]['fields'][$i]['label']; } else { $label = is_array($GLOBALS['TL_LANG']['MSC'][$i]) ? $GLOBALS['TL_LANG']['MSC'][$i][0] : $GLOBALS['TL_LANG']['MSC'][$i]; } if ($label == '') { $label = $i; } $return .= ' <tr> <td' . $class . '><span class="tl_label">' . $label . ': </span></td> <td' . $class . '>' . $row[$i] . '</td> </tr>'; } // Special treatment for tl_undo if ($this->strTable == 'tl_undo') { $arrData = deserialize($objRow->data); foreach ($arrData as $strTable => $arrTableData) { \System::loadLanguageFile($strTable); $this->loadDataContainer($strTable); foreach ($arrTableData as $arrRow) { $count = 0; $return .= ' <tr> <td colspan="2" style="padding:0"><div style="margin-bottom:26px;line-height:24px;border-bottom:1px dotted #ccc"> </div></td> </tr>'; foreach ($arrRow as $i => $v) { if (is_array(deserialize($v))) { continue; } $class = $count++ % 2 == 0 ? ' class="tl_bg"' : ''; // Get the field label if (isset($GLOBALS['TL_DCA'][$strTable]['fields'][$i]['label'])) { $label = is_array($GLOBALS['TL_DCA'][$strTable]['fields'][$i]['label']) ? $GLOBALS['TL_DCA'][$strTable]['fields'][$i]['label'][0] : $GLOBALS['TL_DCA'][$strTable]['fields'][$i]['label']; } else { $label = is_array($GLOBALS['TL_LANG']['MSC'][$i]) ? $GLOBALS['TL_LANG']['MSC'][$i][0] : $GLOBALS['TL_LANG']['MSC'][$i]; } if (!strlen($label)) { $label = $i; } // Always encode special characters (thanks to Oliver Klee) $return .= ' <tr> <td' . $class . '><span class="tl_label">' . $label . ': </span></td> <td' . $class . '>' . specialchars($v) . '</td> </tr>'; } } } } // Return table return ' <div id="tl_buttons">' . (!\Input::get('popup') ? ' <a href="' . $this->getReferer(true) . '" class="header_back" title="' . specialchars($GLOBALS['TL_LANG']['MSC']['backBTTitle']) . '" accesskey="b" onclick="Backend.getScrollOffset()">' . $GLOBALS['TL_LANG']['MSC']['backBT'] . '</a>' : '') . ' </div> <table class="tl_show">' . $return . ' </table>'; }
/** * Implode a multi-dimensional array recursively * * @param mixed $var * @param boolean $binary * * @return string */ protected function implodeRecursive($var, $binary = false) { if (!is_array($var)) { return $binary ? \StringUtil::binToUuid($var) : $var; } elseif (!is_array(current($var))) { if ($binary) { $var = array_map(function ($v) { return $v ? \StringUtil::binToUuid($v) : ''; }, $var); } return implode(', ', $var); } else { $buffer = ''; foreach ($var as $k => $v) { $buffer .= $k . ": " . $this->implodeRecursive($v) . "\n"; } return trim($buffer); } }
/** * Get a UUID string from binary data. * * @param string $data The binary data. * * @return string The UUID string */ public static function binToUuid($data) { if (self::isStringUtilAvailable()) { return StringUtil::binToUuid($data); } return \Contao\String::binToUuid($data); }
/** * Save the current value * * @param mixed $varValue */ protected function save($varValue) { if (\Input::post('FORM_SUBMIT') != $this->strTable) { return; } $arrData = $GLOBALS['TL_DCA'][$this->strTable]['fields'][$this->strField]; // Make sure that checkbox values are boolean if ($arrData['inputType'] == 'checkbox' && !$arrData['eval']['multiple']) { $varValue = $varValue ? true : false; } if ($varValue != '') { // Convert binary UUIDs (see #6893) if ($arrData['inputType'] == 'fileTree') { $varValue = deserialize($varValue); if (!is_array($varValue)) { $varValue = \StringUtil::binToUuid($varValue); } else { $varValue = serialize(array_map('StringUtil::binToUuid', $varValue)); } } // Convert date formats into timestamps if ($varValue != '' && in_array($arrData['eval']['rgxp'], array('date', 'time', 'datim'))) { $objDate = new \Date($varValue, \Date::getFormatFromRgxp($arrData['eval']['rgxp'])); $varValue = $objDate->tstamp; } // Handle entities if ($arrData['inputType'] == 'text' || $arrData['inputType'] == 'textarea') { $varValue = deserialize($varValue); if (!is_array($varValue)) { $varValue = \StringUtil::restoreBasicEntities($varValue); } else { $varValue = serialize(array_map('StringUtil::restoreBasicEntities', $varValue)); } } } // Trigger the save_callback if (is_array($arrData['save_callback'])) { foreach ($arrData['save_callback'] as $callback) { if (is_array($callback)) { $this->import($callback[0]); $varValue = $this->{$callback}[0]->{$callback}[1]($varValue, $this); } elseif (is_callable($callback)) { $varValue = $callback($varValue, $this); } } } $strCurrent = $this->varValue; // Handle arrays and strings if (is_array($strCurrent)) { $strCurrent = serialize($strCurrent); } elseif (is_string($strCurrent)) { $strCurrent = html_entity_decode($this->varValue, ENT_QUOTES, \Config::get('characterSet')); } // Save the value if there was no error if ((strlen($varValue) || !$arrData['eval']['doNotSaveEmpty']) && $strCurrent != $varValue) { \Config::persist($this->strField, $varValue); $deserialize = deserialize($varValue); $prior = is_bool(\Config::get($this->strField)) ? \Config::get($this->strField) ? 'true' : 'false' : \Config::get($this->strField); // Add a log entry if (!is_array(deserialize($prior)) && !is_array($deserialize)) { if ($arrData['inputType'] == 'password' || $arrData['inputType'] == 'textStore') { $this->log('The global configuration variable "' . $this->strField . '" has been changed', __METHOD__, TL_CONFIGURATION); } else { $this->log('The global configuration variable "' . $this->strField . '" has been changed from "' . $prior . '" to "' . $varValue . '"', __METHOD__, TL_CONFIGURATION); } } // Set the new value so the input field can show it $this->varValue = $deserialize; \Config::set($this->strField, $deserialize); } }
/** * Run the controller and parse the template * * @return Response */ public function run() { if ($this->strFile == '') { die('No file given'); } // Make sure there are no attempts to hack the file system if (preg_match('@^\\.+@i', $this->strFile) || preg_match('@\\.+/@i', $this->strFile) || preg_match('@(://)+@i', $this->strFile)) { die('Invalid file name'); } // Limit preview to the files directory if (!preg_match('@^' . preg_quote(\Config::get('uploadPath'), '@') . '@i', $this->strFile)) { die('Invalid path'); } // Check whether the file exists if (!file_exists(TL_ROOT . '/' . $this->strFile)) { die('File not found'); } // Check whether the file is mounted (thanks to Marko Cupic) if (!$this->User->hasAccess($this->strFile, 'filemounts')) { die('Permission denied'); } // Open the download dialogue if (\Input::get('download')) { $objFile = new \File($this->strFile); $objFile->sendToBrowser(); } /** @var BackendTemplate|object $objTemplate */ $objTemplate = new \BackendTemplate('be_popup'); // Add the resource (see #6880) if (($objModel = \FilesModel::findByPath($this->strFile)) === null) { if (\Dbafs::shouldBeSynchronized($this->strFile)) { $objModel = \Dbafs::addResource($this->strFile); } } if ($objModel !== null) { $objTemplate->uuid = \StringUtil::binToUuid($objModel->uuid); // see #5211 } // Add the file info if (is_dir(TL_ROOT . '/' . $this->strFile)) { $objFile = new \Folder($this->strFile); $objTemplate->filesize = $this->getReadableSize($objFile->size) . ' (' . number_format($objFile->size, 0, $GLOBALS['TL_LANG']['MSC']['decimalSeparator'], $GLOBALS['TL_LANG']['MSC']['thousandsSeparator']) . ' Byte)'; } else { $objFile = new \File($this->strFile); // Image if ($objFile->isImage) { $objTemplate->isImage = true; $objTemplate->width = $objFile->width; $objTemplate->height = $objFile->height; $objTemplate->src = $this->urlEncode($this->strFile); } $objTemplate->href = ampersand(\Environment::get('request'), true) . '&download=1'; $objTemplate->filesize = $this->getReadableSize($objFile->filesize) . ' (' . number_format($objFile->filesize, 0, $GLOBALS['TL_LANG']['MSC']['decimalSeparator'], $GLOBALS['TL_LANG']['MSC']['thousandsSeparator']) . ' Byte)'; } $objTemplate->icon = $objFile->icon; $objTemplate->mime = $objFile->mime; $objTemplate->ctime = \Date::parse(\Config::get('datimFormat'), $objFile->ctime); $objTemplate->mtime = \Date::parse(\Config::get('datimFormat'), $objFile->mtime); $objTemplate->atime = \Date::parse(\Config::get('datimFormat'), $objFile->atime); $objTemplate->path = specialchars($this->strFile); $objTemplate->theme = \Backend::getTheme(); $objTemplate->base = \Environment::get('base'); $objTemplate->language = $GLOBALS['TL_LANGUAGE']; $objTemplate->title = specialchars($this->strFile); $objTemplate->charset = \Config::get('characterSet'); $objTemplate->label_uuid = $GLOBALS['TL_LANG']['MSC']['fileUuid']; $objTemplate->label_imagesize = $GLOBALS['TL_LANG']['MSC']['fileImageSize']; $objTemplate->label_filesize = $GLOBALS['TL_LANG']['MSC']['fileSize']; $objTemplate->label_ctime = $GLOBALS['TL_LANG']['MSC']['fileCreated']; $objTemplate->label_mtime = $GLOBALS['TL_LANG']['MSC']['fileModified']; $objTemplate->label_atime = $GLOBALS['TL_LANG']['MSC']['fileAccessed']; $objTemplate->label_path = $GLOBALS['TL_LANG']['MSC']['filePath']; $objTemplate->download = specialchars($GLOBALS['TL_LANG']['MSC']['fileDownload']); return $objTemplate->getResponse(); }