function fileDropBackslash($path) { if (substr($path, strlen($path)-1)=='/') $path = substr($path, 0, strlen($path)-1); return $path; } function addvideoarrow( $source_file_path, $watermark = "/images/html/play.png" ){ $opacity = 100; // % $quality = 5; // Compression level: from 0 (no compression) to 9; $site_id = $GLOBALS['site_id']; if (!$site_id) return ''; $name = basename ($source_file_path); $dir = dirname($source_file_path); $new_file_name = explode(".", $name); $new_file_name[count($new_file_name)-2] .= "_watermarked"; $new_file_name[count($new_file_name)-2] = md5($new_file_name[count($new_file_name)-2]); // not readable $new_file_name[count($new_file_name)-1] = "png"; // output will be png $new_file_name = implode(".", $new_file_name); $new_file_path = $dir."/".$new_file_name; $watermark = getFilePathFromLink($site_id, $watermark); $path_to_image = getFilePathFromLink($site_id, $source_file_path); $path_to_new_image = getFilePathFromLink($site_id, $new_file_path); list( $source_width, $source_height, $source_type ) = getimagesize( $path_to_image ); // original sizes list( $o_watermark_width, $o_watermark_height, $watermark_type ) = getimagesize( $watermark ); // original sizes if ( $source_type === NULL ){ return ""; } switch ( $source_type ){ case IMAGETYPE_JPEG: $source_gd_image = imagecreatefromjpeg( $path_to_image ); break; case IMAGETYPE_PNG: $source_gd_image = imagecreatefrompng( $path_to_image ); break; default: return ""; } switch ( $watermark_type ){ case IMAGETYPE_JPEG: $watermark_gd_image = imagecreatefromjpeg( $watermark ); break; case IMAGETYPE_PNG: $watermark_gd_image = imagecreatefrompng( $watermark ); break; default: return ""; } if($o_watermark_width > $source_width){ // if watermark is wider we need to resize watermark $ratio = $o_watermark_width / $source_width; $watermark_width = $o_watermark_width / $ratio; $watermark_height = $o_watermark_height / $ratio; } if($o_watermark_height > $source_height){ // if watermark is taller we need to resize watermark $ratio = $o_watermark_height / $source_height; $watermark_width = $o_watermark_width / $ratio; $watermark_height = $o_watermark_height / $ratio; } if($o_watermark_width / $source_width < 0.5){ // if watermark is too small $ratio = $o_watermark_width /($source_width * 0.5); $watermark_width = $o_watermark_width / $ratio; $watermark_height = $o_watermark_height / $ratio; } if($o_watermark_width / $source_width > 0.5){ // if watermark is too big $ratio = $o_watermark_width /($source_width * 0.5); $watermark_width = $o_watermark_width / $ratio; $watermark_height = $o_watermark_height / $ratio; } $watermark_width = ($watermark_width)? floor($watermark_width) : $o_watermark_width; $watermark_height = ($watermark_height)? floor($watermark_height) : $o_watermark_height; force_truecolor_image($watermark_gd_image); force_truecolor_image($source_gd_image); $waterm = imagecreatetruecolor($watermark_width, $watermark_height); imagealphablending($waterm, false); imagefill($waterm, 0, 0, imagecolortransparent($waterm, imagecolorallocatealpha($waterm, 0, 0, 0, 127))); // better do not try to understand this imagesavealpha($waterm, true); imagecopyresampled($waterm, $watermark_gd_image, 0, 0, 0, 0, $watermark_width, $watermark_height, $o_watermark_width, $o_watermark_height ); filter_opacity($waterm, $opacity); imagecopy($source_gd_image, $waterm, floor(($source_width-$watermark_width)/2), floor(($source_height-$watermark_height)/2), 0, 0, imagesx($waterm), imagesy($waterm)); imagepng( $source_gd_image, $path_to_new_image, $quality ); imagedestroy( $source_gd_image ); imagedestroy( $waterm ); imagedestroy( $watermark_gd_image ); return $new_file_path; } function fileAddBackslash($path) { if (substr($path, strlen($path)-1)!='/') $path = $path.'/'; return $path; } function fileDropStartBackslash($path) { if (substr($path, 0, 1)=='/') $path = substr($path, 1); return $path; } function fileValidName($fname) { return ereg_replace("[^a-z0-9._]", "", ereg_replace(" ", "_", ereg_replace("%20", "_", strtolower($fname)))); } function create_watermarked( $source_file_path, $watermark ){ $opacity = 15; // % $quality = 5; // Compression level: from 0 (no compression) to 9; $site_id = $GLOBALS['site_id']; if (!$site_id) return '1'; $name = basename ($source_file_path); $dir = dirname($source_file_path); $new_file_name = explode(".", $name); $new_file_name[count($new_file_name)-2] .= "_watermarked"; $new_file_name[count($new_file_name)-2] = md5($new_file_name[count($new_file_name)-2]); // not readable $new_file_name[count($new_file_name)-1] = "png"; // output will be png $new_file_name = implode(".", $new_file_name); $new_file_path = $dir."/".$new_file_name; $watermark = getFilePathFromLink($site_id, $watermark); $path_to_image = getFilePathFromLink($site_id, $source_file_path); $path_to_new_image = getFilePathFromLink($site_id, $new_file_path); list( $source_width, $source_height, $source_type ) = getimagesize( $path_to_image ); // original sizes list( $o_watermark_width, $o_watermark_height, $watermark_type ) = getimagesize( $watermark ); // original sizes if(is_file($path_to_new_image)){ return $new_file_path; } if ( $source_type === NULL ){ return '2';} switch ( $source_type ){ case IMAGETYPE_JPEG: $source_gd_image = imagecreatefromjpeg( $path_to_image ); break; case IMAGETYPE_PNG: $source_gd_image = imagecreatefrompng( $path_to_image ); break; default: return '3'; } switch ( $watermark_type ){ case IMAGETYPE_JPEG: $watermark_gd_image = imagecreatefromjpeg( $watermark ); break; case IMAGETYPE_PNG: $watermark_gd_image = imagecreatefrompng( $watermark ); break; default: return '4'; } $ratio = false; if($o_watermark_width > $source_width && $o_watermark_height > $source_height){ // if watermark is wider and taller we need to resize watermark $ratio = max(array($o_watermark_width / $source_width, $o_watermark_height / $source_height)); }elseif($o_watermark_height > $source_height){ // if watermark is taller we need to resize watermark $ratio = $o_watermark_height / $source_height; }elseif($o_watermark_height > $source_height){ // if watermark is wider we need to resize watermark $ratio = $o_watermark_width / $source_width; } if($ratio){ $watermark_width = $o_watermark_width / $ratio; $watermark_height = $o_watermark_height / $ratio; } if($o_watermark_width / $source_width < 0.5){ // if watermark is too small $ratio = $o_watermark_width /($source_width * 0.5); $watermark_width = $o_watermark_width / $ratio; $watermark_height = $o_watermark_height / $ratio; } $watermark_width = ($watermark_width)? floor($watermark_width) : $o_watermark_width; $watermark_height = ($watermark_height)? floor($watermark_height) : $o_watermark_height; force_truecolor_image($watermark_gd_image); force_truecolor_image($source_gd_image); $waterm = imagecreatetruecolor($watermark_width, $watermark_height); imagealphablending($waterm, false); imagefill($waterm, 0, 0, imagecolortransparent($waterm, imagecolorallocatealpha($waterm, 0, 0, 0, 127))); // better do not try to understand this imagesavealpha($waterm, true); imagecopyresampled($waterm, $watermark_gd_image, 0, 0, 0, 0, $watermark_width, $watermark_height, $o_watermark_width, $o_watermark_height ); filter_opacity($waterm, $opacity); // add watermark //imagealphablending($source_gd_image, false); imagesavealpha($source_gd_image, true); imagecopy($source_gd_image, $waterm, 0, $source_height-$watermark_height, 0, 0, imagesx($waterm), imagesy($waterm)); imagepng( $source_gd_image, $path_to_new_image, $quality ); imagedestroy( $source_gd_image ); imagedestroy( $waterm ); imagedestroy( $watermark_gd_image ); return $new_file_path; } function filter_opacity( &$img, $opacity ){ $opacity /= 100; //get image width and height $w = imagesx( $img ); $h = imagesy( $img ); //turn alpha blending off imagealphablending( $img, false ); //find the most opaque pixel in the image (the one with the smallest alpha value) $minalpha = 127; for( $x = 0; $x < $w; $x++ ) for( $y = 0; $y < $h; $y++ ) { $alpha = ( imagecolorat( $img, $x, $y ) >> 24 ) & 0xFF; if( $alpha < $minalpha ) { $minalpha = $alpha; } } //loop through image pixels and modify alpha for each for( $x = 0; $x < $w; $x++ ) { for( $y = 0; $y < $h; $y++ ) { //get current alpha value (represents the TANSPARENCY!) $colorxy = imagecolorat( $img, $x, $y ); $alpha = ( $colorxy >> 24 ) & 0xFF; //calculate new alpha if( $minalpha !== 127 ) { $alpha = 127 + 127 * $opacity * ( $alpha - 127 ) / ( 127 - $minalpha ); } else { $alpha += 127 * $opacity; } //get the color index with new alpha $alphacolorxy = imagecolorallocatealpha( $img, ( $colorxy >> 16 ) & 0xFF, ( $colorxy >> 8 ) & 0xFF, $colorxy & 0xFF, $alpha ); //set pixel with the new color + opacity if( !imagesetpixel( $img, $x, $y, $alphacolorxy ) ) { return false; } } } return true; } function DeleteFile($directory, $relpath='') { if ($_GET['file'] != "" ) { $files = explode(";",$_GET['file']); foreach ($files as $key=>$file) { $fname = fileAddBackslash($directory).$file; fileDelete($fname, true); Add_Log("Deleted file '$fname'", $GLOBALS['site_id']); //if($relpath) if(($relpath)and(($GLOBALS['index_htm_files'])or($GLOBALS['index_doc_files']))) { require_once ($GLOBALS['cfgDirRoot']."library/".'func.search.php'); IndexFileForSearch($GLOBALS['site_id'], fileDropStartBackslash(fileAddBackslash($relpath)).$file); sqlQuery(" DELETE FROM ".$GLOBALS['site_id']."_filesearch_object WHERE filename='".fileDropStartBackslash(fileAddBackslash($relpath)).$file."'"); sqlQuery(" DELETE FROM ".$GLOBALS['site_id']."_filesearch_link WHERE filename='".fileDropStartBackslash(fileAddBackslash($relpath)).$file."'"); sqlQuery(" DELETE FROM ".$GLOBALS['site_id']."_filesearch_keywordlink WHERE file_path ='".fileDropStartBackslash(fileAddBackslash($relpath)).$file."'"); } } } } function RenameFile($directory, $oldfile, $newfile) { if ($newfile != "" ) { $oldfname = fileAddBackslash($directory).$oldfile; $newfname = fileAddBackslash($directory).$newfile; rename($oldfname, $newfname); Add_Log("Renamed file '$oldfname' to '$newfname'", $GLOBALS['site_id']); } } function CopyFile($fromfile, $tofile) { if (!copy($fromfile, $tofile)) { //print ("error while copying file $fromfname\n"); //Add_Log("Erorr while copying file from '$fromfile' to '$tofile'", $GLOBALS['site_id']); } else Add_Log("Copy file from '$fromfile' to '$tofile'", $GLOBALS['site_id']); } function MoveFile($fromfile, $tofile) { if ($fromfile!=$tofile) if (!copy($fromfile, $tofile)) { //print ("error while copying file $fromfile\n"); //Add_Log("Erorr while moving file from '$fromfile' to '$tofile'", $GLOBALS['site_id']); } else { fileDelete($fromfile); Add_Log("Move file from '$fromfile' to '$tofile'", $GLOBALS['site_id']); } } function fileSizeStr($file){ $file_size = filesize($file); if($file_size >= 1073741824) { $file_size = round($file_size / 1073741824 * 100) / 100 . "g"; } elseif($file_size >= 1048576) { $file_size = round($file_size / 1048576 * 100) / 100 . "m"; } elseif($file_size >= 1024) { $file_size = round($file_size / 1024 * 100) / 100 . "k"; } else { $file_size = $file_size . "b"; } return $file_size; } function fileDelete($name, $recursive=false) { if(is_dir($name)) { if ($recursive) recursive_remove_directory($name); else rmdir($name); } else { unlink($name); } } function fileUp($path) { $path = fileDropBackslash($path); $pos = strrpos($path, '/'); if (!($pos === false)) $path = substr($path, 0, $pos); else $path = ''; return($path); } //get full file path in filesystem from relative url function getFilePathFromLink($site_id, $webpath) { static $dirs = Array(); if (!isset($dirs[$site_id])) $dirs[$site_id] = fileAddBackslash( sqlQueryValue("select dirroot from sites where site_id=".$site_id) ); return $dirs[$site_id] . trim($webpath, '/'); } //$file = elements no $_FILES masiiva //$path = relatiivais celjsh, uz kuru augshupielaadeet, piemeeram, upload/iesutitie/ function uploadSiteFile($site_id, $file, $path) { if(!$file['size']) return false; $file_name = basename($file['name']); $file_name = strtolower(str_replace(' ', '_', $file_name)); $domain = sqlQueryValue("select domain from sites where site_id=".$site_id); $uploaddir = sqlQueryValue("select dirroot from sites where site_id=".$site_id); $uploaddir .= $path; if (!file_exists($uploaddir)) { mkdir($uploaddir, 0755, true); } $target_path = $uploaddir . $file_name; $target_path = str_replace("//", "/", $target_path); while(file_exists($target_path)) { $timestamp = time(); $file_name = rand(1,999999)."_".$file_name; $target_path = $uploaddir.$file_name; } $webpath = 'http://'.$domain.'/' . $path . $file_name; $shortwebpath = '/' . $path . $file_name; $shortwebpath = str_replace("//", "/", $shortwebpath); $webpath = str_replace("//", "/", $webpath); if(move_uploaded_file($file['tmp_name'], $target_path)) { @chmod($target_path, 0755); $arr = array('fullurl' => $webpath, 'url' => $shortwebpath, 'filename' => $file_name, 'path' => $target_path); return $arr; } else { return false; } } //path = relatiivais celjsh (images/galleries/thumbs/) function forceDirectories($site_id, $path) { $uploaddir = getFilePathFromLink($site_id, '/'); $path = explode('/', $path); foreach($path as $dir) { if($dir) { $uploaddir .= $dir; if (!is_dir($uploaddir)) { mkdir($uploaddir); chmod($uploaddir, 0755); } $uploaddir .= '/'; } } } //filename = pilnais celjsh function fileDuplicate($site_id, $filename, $prefix = '', $destpath = '') { $file_name = $prefix . basename($filename); $domain = sqlQueryValue("select domain from sites where site_id=".$site_id); $uploaddir = sqlQueryValue("select dirroot from sites where site_id=".$site_id); if($destpath) { $uploaddir .= $destpath; $path = $destpath; }else { $uploaddir2 = dirname($filename) . '/'; if(substr($uploaddir2, 0, strlen($uploaddir)) == $uploaddir) { $path = substr($uploaddir2, strlen($uploaddir)); $uploaddir = $uploaddir2; }else { $path = false; } } $target_path = $uploaddir . $file_name; while(file_exists($target_path)) { $timestamp = time(); $file_name = rand(1,999999)."_".$file_name; $target_path = $uploaddir.$file_name; } copy($filename, $target_path); @chmod($target_path, 0755); $webpath = 'http://'.$domain.'/' . $path . $file_name; $shortwebpath = '/' . $path . $file_name; $arr = array('fullurl' => $webpath, 'url' => $shortwebpath, 'filename' => $file_name, 'path' => $target_path); return $arr; } //will resize image file located in $filename, overwriting it //$filename = full path in file system //resize mode // 0 - none // 1 - resize by width // 2 - resize by height // 3 - resize by width if too big // 4 - resize by height if too big // 5 - resize by width and height to fit // 6 - resize by width and height to fit if too big // 7 - crop to fit in width and height exactly function resizeImage($filename, $width, $height, $resizemode) { $type = substr($filename, strrpos($filename, '.') + 1); if($resizemode > 0 && $resizemode < 11) { resizeKeepAspectUploadedImage($filename, $type, $width, $height, $filename, $resizemode); }else { resizeCropUploadedImage($filename, $type, $width, $height, $filename); } return true; } function resizeCropUploadedImage($srcfile, $type, $w, $h, $new_name, $resizemode) { $uploadfile = $srcfile; $type = strtolower($type); if ($type == "gif") $abc = imagecreatefromGIF($uploadfile); //UPLOADED PIC FILE else if ($type == "jpg" || $type == "jpeg") $abc = imagecreatefromjpeg($uploadfile); //UPLOADED PIC FILE else if ($type == "png") $abc = imagecreatefrompng($uploadfile); //UPLOADED PIC FILE else return false; if (!$abc) { $abc = @imagecreatefromjpeg($uploadfile); if (!$abc) $abc = @imagecreatefrompng($uploadfile); if (!$abc) { $abc = @imagecreatefromgif($uploadfile); } if (!$abc) return false; } $thumbwidth = $w; $thumbheight = $h; //calc srcx, srcy, srcw and srch if($thumbheight / $thumbwidth < ImageSY($abc) / ImageSX($abc)) { $srcw = ImageSX($abc); $srch = $thumbheight * (ImageSX($abc) / $thumbwidth); }else { $srcw = $thumbwidth * (ImageSY($abc) / $thumbheight); $srch = ImageSY($abc); } $srcx = round((ImageSX($abc) - $srcw) / 2); switch ($resizemode) { case 7: $srcy = round((ImageSY($abc) - $srch) / 2); break; case 8: $srcy = 0; break; case 9: $srcy = ImageSY($abc) - $srch; break; } $def = @imagecreatetruecolor($thumbwidth, $thumbheight) or die("Cannot Initialize new GD image stream"); if ($type == 'png') { imagealphablending($def, false); imagesavealpha($def, true); } imagecopyresampled($def, $abc, 0, 0, $srcx, $srcy, $thumbwidth, $thumbheight, $srcw, $srch); ImageDestroy($abc); if ($type == 'gif') imagegif($def, $new_name); else if ($type == 'png') imagepng($def, $new_name, 9); else imagejpeg($def, $new_name, 90); //new file from $def ImageDestroy($def); } function resizeKeepAspectUploadedImage($srcfile, $type, $w, $h, $new_name, $resizemode) { $uploadfile = $srcfile; $type = strtolower($type); if ($type == "gif") $abc = imagecreatefromGIF($uploadfile); //UPLOADED PIC FILE else if ($type == "jpg" || $type == "jpeg") $abc = imagecreatefromjpeg($uploadfile); //UPLOADED PIC FILE else if ($type == "png") $abc = imagecreatefrompng($uploadfile); //UPLOADED PIC FILE $is_png = false; if (!$abc) { $abc = @imagecreatefromjpeg($uploadfile); if (!$abc) { $abc = @imagecreatefrompng($uploadfile); $is_png = true; } else if (!$abc) { $abc = @imagecreatefromgif($uploadfile); } if (!$abc) return false; } $thumbwidth = $w; $thumbheight = $h; //check if resizing is even required if(($resizemode != 3 || ImageSX($abc) > $w) && ($resizemode != 4 || ImageSY($abc) > $h) && ($resizemode != 6 || $resizemode != 10 || ImageSX($abc) > $w || ImageSY($abc) > $h)) { //calculate required thumbwidth and thumbheight if($resizemode == 1 || $resizemode == 3) { //resize by width $thumbheight = round(ImageSY($abc) * ($thumbwidth/ImageSX($abc))); }else if($resizemode == 2 || $resizemode == 4) { //resize by height $thumbwidth = round(ImageSX($abc) * ($thumbheight/ImageSY($abc))); }else if($resizemode == 5 || $resizemode == 6) { //resize by width and height $new_w = round(ImageSX($abc) * ($thumbheight/ImageSY($abc))); if($new_w <= $thumbwidth) { $thumbwidth = $new_w; }else { $thumbheight = round(ImageSY($abc) * ($thumbwidth/ImageSX($abc))); } } $def = @imagecreatetruecolor($thumbwidth, $thumbheight) or die("Cannot Initialize new GD image stream"); if ($is_png || $type == 'png') { imagealphablending($def, false); imagesavealpha($def, true); } imagecopyresampled($def, $abc, 0, 0, 0, 0, $thumbwidth, $thumbheight, ImageSX($abc), ImageSY($abc)); ImageDestroy($abc); if ($type == 'gif') imagegif($def, $new_name); else if ($is_png || $type == 'png') imagepng($def, $new_name, 9); else imagejpeg($def, $new_name, 90); //new file from $def ImageDestroy($def); return true; }else { //no resize required ImageDestroy($abc); return false; } } function getThumbURL($src_url, $width, $height, $resizemode, $site_id=0, $thumb_dir='th') { if (!$src_url || !$width || !$height) return ''; if (!$resizemode) return $src_url; if (!$site_id) { $site_id = $GLOBALS['site_id']; if (!$site_id) return ''; } $thumb_dir = fileDropBackslash($thumb_dir); $src_path = fileDropBackslash(getFilePathFromLink($site_id, $src_url)); if(!file_exists($src_path)){ return false; } $dir = dirname($src_path); $th_conf = $thumb_dir.'/'.$width.'x'.$height.'_'.$resizemode; $thumb_path = getFilePathFromLink($site_id, dirname($src_url)); $th_dir = fileAddBackslash($thumb_path).$th_conf; $basename = basename($src_url); $th_path = $th_dir.'/'.$basename; $th_url_path = fileAddBackslash(dirname($src_url)).$th_conf; $th_url = $th_url_path.'/'.$basename; $src_time = file_exists($src_path) ? filemtime($src_path) : false; $th_time = file_exists($th_path) ? filemtime($th_path) : false; if (file_exists($src_path) && file_exists($th_path) && $src_time && $src_time == $th_time) return $th_url; forceDirectories($site_id, $th_url_path); $type = substr($basename, strrpos($basename, '.') + 1); if(in_array($resizemode, array(7, 8, 9))) { resizeCropUploadedImage($src_path, $type, $width, $height, $th_path, $resizemode); }else { if (!resizeKeepAspectUploadedImage($src_path, $type, $width, $height, $th_path, $resizemode)) copy($src_path, $th_path); } touch($th_path, $src_time); return $th_url; } function deleteThumbnails($image_url, $site_id=0, $thumb_dir='th') { if (!$site_id) { $site_id = $GLOBALS['site_id']; if (!$site_id) return ''; } $path = getFilePathFromLink($site_id, $image_url); $dir = dirname($path); $filename = basename($path); foreach (glob($dir.'/'.$thumb_dir.'/*x*_*') as $dir) { foreach (glob($dir.'/'.$filename) as $f) { @unlink($f); } @rmdir($dir); } } function getFileExtension($file){ preg_match("/(\.)([a-z0-9]{3,999})$/", $file, $matches); return $matches[0]; } function getFormFile($key, $site_id=0, $uploaddir='upload/') { if (!isset($_POST[$key.'_file_select_mode']) || !isset($_FILES[$key])) return ''; if (!$site_id) $site_id = $GLOBALS['site_id']; if ($_POST[$key.'_file_select_mode'] == 'upload') { if ($uploaddir) forceDirectories($site_id, $uploaddir); $f = uploadSiteFile($site_id, $_FILES[$key], $uploaddir); $url = $f['url']; } else $url = $_POST[$key.'_link']; return $url; } function recursive_remove_directory($directory, $empty=FALSE) { // if the path has a slash at the end we remove it here if(substr($directory,-1) == '/') { $directory = substr($directory,0,-1); } // if the path is not valid or is not a directory ... if(!file_exists($directory) || !is_dir($directory)) { // ... we return false and exit the function return FALSE; // ... if the path is not readable }elseif(!is_readable($directory)) { // ... we return false and exit the function return FALSE; // ... else if the path is readable }else{ // we open the directory $handle = opendir($directory); // and scan through the items inside while (FALSE !== ($item = readdir($handle))) { // if the filepointer is not the current directory // or the parent directory if($item != '.' && $item != '..') { // we build the new path to delete $path = $directory.'/'.$item; // if the new path is a directory if(is_dir($path)) { // we call this function with the new path recursive_remove_directory($path); // if the new path is a file }else{ // we remove the file unlink($path); } } } // close the directory closedir($handle); // if the option to empty is not set to true if($empty == FALSE) { // try to delete the now empty directory if(!rmdir($directory)) { // return false if not possible return FALSE; } } // return success return TRUE; } } function force_truecolor_image($img) { $w = imagesx($img); $h = imagesy($img); if (!imageistruecolor($img)) { $truecolor = imagecreatetruecolor($w, $h); imagealphablending($img, false); imagesavealpha($img, true); imagecopy($truecolor, $img, 0, 0, 0, 0, $w, $h); imagedestroy($img); $img = $truecolor; } return $img; } function watermark_image($img, $watermark, $wf, $hf, $alpha=15) { $w_width = round(imagesx($img) * $wf); $w_height = round(imagesy($watermark) * ($w_width/imagesx($watermark)) ); $max_h = imagesy($img) * $hf ; if ($w_height > $max_h) { $h = $max_h; //round(imagesy($img) * 0.3); $w_width = round($w_width * ($h/$w_height) ); $w_height = $h; } $waterm = imagecreatetruecolor($w_width, $w_height); $x = (imagesx($img) - imagesx($waterm)) * 0.96; $y = (imagesy($img) - imagesy($waterm)) * 0.96; // imagealphablending($waterm, false); imagealphablending($waterm, false); $color = imagecolortransparent($waterm, imagecolorallocatealpha($waterm, 0, 0, 0, 127)); imagefill($waterm, 0, 0, $color); imagesavealpha($waterm, true); imagecopyresampled($waterm, $watermark, 0,0,0,0, $w_width, $w_height, imagesx($watermark), imagesy($watermark) ); imagecopy($img, $waterm, $x, $y, 0,0, imagesx($waterm), imagesy($waterm)); } function watermark_file($f, $outfile, $watermark, $wf, $hf, $alpha=15) { $ext = strtolower(pathinfo($f, PATHINFO_EXTENSION)); getimagesize($f, $info); if ($info || $ext == 'jpeg' || $ext == 'jpg') $img = @imagecreatefromjpeg($f); else if ($ext == 'png') $img = @imagecreatefrompng($f); else if ($ext == 'gif') $img = @imagecreatefromgif($f); if (!$img) { $img = @imagecreatefromjpeg($f); if (!$img) $img = @imagecreatefrompng($f); if (!$img) $img = @imagecreatefromgif($f); if (!$img) return false; } $img = force_truecolor_image($img); watermark_image($img, $watermark, $wf, $hf, $alpha); // imagecopymerge($img, $waterm, $x, $y, 0,0, imagesx($waterm), imagesy($waterm), $alpha); if ($info || $ext == 'jpeg' || $ext == 'jpg') imagejpeg($img, $outfile, 90); else if ($ext == 'png') imagepng($img, $outfile); else if ($ext == 'gif') imagegif($img, $outfile); return true; } ?> //Functions for processing components, parsing and extracting components from HTML code function OutputComponentPlain($name, $type, $page_id) { $filename = $GLOBALS['cfgDirRoot'] . "components/class.$type.php"; if(file_exists($filename)) { $GLOBALS['component_name'] = $name; $GLOBALS['page_id'] = $page_id; ob_start(); include_once($filename); $obj = new $type($name); if(!$obj->getProperty('visible')) $obj->Output(); $cont = ob_get_contents(); $ret .= $cont; ob_end_clean(); return $cont; } } function executeComponent(&$component, $type, $name){ if($component !== false){ $GLOBALS['component_name'] = $name; $GLOBALS['profiler_component'] = $name; $component->Execute(); $GLOBALS['profiler_component'] = ''; } } if(!function_exists('initializeComponent')) { function initializeComponent($type, $name) { $filename = getComponentFilePath($type); if(file_exists($filename)) { $GLOBALS['component_name'] = $name; $GLOBALS['profiler_component'] = $name; profiler_add('Init component ' . $type . ' ' . $name, 3); include_once($filename); $obj = new $type($name); addDefaultProperties($obj); profiler_add('Init component ' . $type . ' ' . $name, 4); $GLOBALS['profiler_component'] = ''; return $obj; }else { return false; } } } function createComponentInstance($name, $type, $page_id=0, $devmode=false) { $filename = getComponentFilePath($type); if (!file_exists($filename)) return null; include_once($filename); if (!class_exists($type)) return null; $obj = new $type($name); if ($page_id) $obj->initForPage($page_id, $devmode); return $obj; } function getDynamicComponentInfo($id, $site_id=0) { if (!$site_id) $site_id = $GLOBALS['site_id']; return sqlQueryRow('SELECT * FROM '.$site_id.'_dynamic_components WHERE id='.(int)$id); } function createDynamicComponentInstance($id, $page_id, $devmode=false) { $cmp = getDynamicComponentInfo($id); if (!$cmp) return null; $name = str_replace('_', '', $cmp['type']); $obj = createComponentInstance($name, $cmp['type'], $page_id, $devmode); if ($obj) { $obj->component_id = $id; $obj->dynamic_component_info = $cmp; } return $obj; } function componentGetDynamicComponents($name, $type, $page_id, $ind) { $components = array(); $obj = createComponentInstance($name, $type, $page_id, true); if ($obj) { $cmp_ids = $obj->getDynamicComponentsIDs($ind); $types = array(); foreach ($cmp_ids as $id) { $cmp = getDynamicComponentInfo($id); if (!isset($types[$cmp['type']])) { $types[$cmp['type']] = 1; $components[] = array( 'type' => $cmp['type'], 'name' => str_replace('_', '', $cmp['type']), 'options' => '', 'ind' => $ind, 'tag' => '' ); } } } return $components; } //Functions returns array of all components in $body function componentArray($body, $page_id, $ind = 0){ $r = Array(); $rd = array(); preg_match_all ( '/{%component:([a-zA-Z0-9_]+):([a-zA-Z0-9]+)(:[a-zA-Z0-9% \\.\\,\\\"\\\'\\#\\!-]+)?%}/s', $body, $matches, PREG_SET_ORDER); foreach($matches as $key => $regs){ $all = $regs[0]; $type = $regs[1]; $name = $regs[2]; $opts = $regs[3]; $r[] = Array("type" => $type, "name" => $name, "options" => $opts, "ind" => $ind, "tag" => $all); } return $r; } function getComponentParams($s) { //function extracts parameters from string //parameters are in form //:paramname1 "paramval" paramname2 "param""val" $isval = false; $name = ''; $value = ''; $a = Array(); for($f = 1; $f < strlen($s); $f++) { $c = $s{$f}; if($isval) { if($c == '"') { if($s{$f+1} == '"') { $f++; $value .= $c; }else { $isval = false; $name = trim($name); $a[$name] = $value; $name = ''; $value = ''; } }else { $value .= $c; } }else { if($c == '"') { $isval = true; }else { $name .= $c; } } } return($a); } function addDefaultProperties(&$obj) { //Add options visible/hidden to all components if(!$obj->properties["visible"]) { $obj->properties["visible"] = Array( "label" => "Visibility:", "type" => "list", "value" => "0", "lookup" => Array("0:Visible", "1:Hidden") ); } } function getPropertiesTable($type) { if(file_exists($GLOBALS['cfgDirRoot'] . 'components/class.' . $type . '.php')) { //Obtain the array of properties for the component include_once($GLOBALS['cfgDirRoot'] . 'components/class.' . $type . '.php'); $obj = new $type($name); addDefaultProperties($obj); return $obj->properties; } return Array(); } function getComponentFilePath($type) { $path = ''; $file = 'class.' . $type . '.php'; if (strpos($type, '_') !== false) { $a = explode('_', $type); unset($a[count($a)-1]); $path = implode('/', $a).'/'; } return $GLOBALS['cfgDirRoot'] . 'components/'.$path.$file; } //function has been rebuilt to work with pagesdev table function displayPropertiesTable($type, $name, $site_id, $page_id, &$form_data, $hide = false, $filterproperties = '') { $file = getComponentFilePath($type); if(file_exists($file)) { //Obtain the array of properties for the component include_once($file); $obj = new $type($name); $obj->InitFormData(); addDefaultProperties($obj); $properties = $obj->properties; $template_id = 0; $language_id = 0; if ($wap) { //if not template use wapcontentsdev table if ($page_id!=-1) { //Obtain the array of current values of properties $data = sqlQueryData("SELECT propertyname, propertyvalue FROM " . $site_id . "_wapcontentsdev WHERE wappagedev=$page_id AND componentname='$name'"); } //else use wapcontents table else { //Obtain the array of current values of properties $data = sqlQueryData("SELECT propertyname, propertyvalue FROM " . $site_id . "_wapcontents WHERE wappage=$page_id AND componentname='$name'"); } } else { if ($page_id>0) { //Obtain the array of current values of properties for page $data = sqlQueryData("SELECT propertyname, propertyvalue FROM " . $site_id . "_contentsdev WHERE pagedev=$page_id AND componentname='$name'"); list($template_id, $language_id) = sqlQueryRow('SELECT template, language FROM ' . $site_id . '_pages WHERE page_id = ' . $page_id); } else { //Obtain the array of current values of properties for view $data = sqlQueryData("SELECT propertyname, propertyvalue FROM " . $site_id . "_contents WHERE page=$page_id AND componentname='$name'"); list($template_id) = sqlQueryRow('SELECT template_id FROM ' . $site_id . '_views WHERE view_id = ' . Abs($page_id)); $language_id = $_SESSION['currentlanguagenum']; } } $properties['name']['value'] = $name; //All values are default before we start foreach(array_keys($properties) as $property) { $properties[$property]['default'] = true; } //Find which values are not default, set them accordingly if($data) { foreach($data as $row) { if(in_array($row['propertyname'], array_keys($properties))) { $properties[$row['propertyname']]['value'] = $row['propertyvalue']; $properties[$row['propertyname']]['default'] = false; } } } $form_data['type_' . $name] = Array('value' => $type, 'type' => 'hidden'); //Set final values and default values of properties $properties_keys = array_keys($properties); foreach($properties_keys as $property) { $uselanguageview = true; if($page_id != -1) { //if editing properties of page components if ($wap) { if($page_id > 0) { $copypage = sqlQueryValue("SELECT copypage FROM " . $site_id . "_wappagesdev WHERE wappagedev_id=$page_id"); } } else { if($page_id > 0) { $copypage = sqlQueryValue("SELECT copypage FROM " . $site_id . "_pagesdev WHERE pagedev_id=$page_id"); }else { $copypage = sqlQueryValue("SELECT -parent FROM " . $site_id . "_views WHERE view_id=" . Abs($page_id)); } } $defaultProperty = null; $OldDefaultProperty = $properties[$property]['value']; if($copypage || $uselanguageview) { if ($wap) { //allow copypages to work in multiple levels while(($copypage)and($defaultProperty == null)) { $defaultProperty = sqlQueryValue("SELECT propertyvalue FROM " . $site_id . "_wapcontentsdev WHERE wappagedev=$copypage AND componentname='" . $name . "' AND propertyname='" . $property . "'"); } } else { //allow copypages to work in multiple levels while(($copypage)and($defaultProperty == null)) { $defaultProperty = sqlQueryValue("SELECT propertyvalue FROM " . $site_id . "_contents WHERE page=$copypage AND componentname='" . $name . "' AND propertyname='" . $property . "'"); if($defaultProperty == null) { $copypage = sqlQueryValue("SELECT -parent FROM " . $site_id . "_views WHERE view_id=" . Abs($copypage)); } } if($defaultProperty == null) { if($template_id > 0 && $language_id > 0 && $uselanguageview) { $copypage = sqlQueryValue('SELECT -view_id FROM ' . $site_id . '_views WHERE template_id = ' . $template_id . ' AND language_id = ' . $language_id); if($copypage != $page_id && $copypage) { $defaultProperty = sqlQueryValue("SELECT propertyvalue FROM " . $site_id . "_contents WHERE page=$copypage AND componentname='" . $name . "' AND propertyname='" . $property . "'"); $uselanguageview = false; }else { $copypage = 0; } } } } } if ($wap) { if($defaultProperty==null) { $defaultProperty = sqlQueryValue("SELECT propertyvalue FROM " . $site_id . "_wapcontents WHERE wappage=-1 AND componentname='" . $name . "' AND propertyname='" . $property . "'"); } } else { if($defaultProperty==null) { $defaultProperty = sqlQueryValue("SELECT propertyvalue FROM " . $site_id . "_contents WHERE page=-1 AND componentname='" . $name . "' AND propertyname='" . $property . "'"); } } $properties[$property]['defval'] = parseForJScript($defaultProperty,true); if($properties[$property]['default']) { $properties[$property]['value'] = $defaultProperty; } if($properties[$property]['value'] == null) $properties[$property]['value'] = $OldDefaultProperty; }else { //If editing properties of template components $properties[$property]['defval'] = parseForJScript($properties[$property]['value'],true); } //$properties[$property]['label'] = $property . ": "; if($property == 'name') { $properties[$property]['type'] = 'title'; $properties[$property]['label'] = $name . ", " . $type; } //Do not display some components in graphical mode if((!$hide)or(!$properties[$property]['hide'])) { if(!$filterproperties) { $form_data["component_" . $name . "_" . $property] = $properties[$property]; }else { $fp = explode(':', $filterproperties); if(in_array($property, $fp)) { $form_data["component_" . $name . "_" . $property] = $properties[$property]; } } } } } } function getProperty($property, $component_name, $type, $page, $site, $copypage=false, $dev=0){ static $cache = array(); if ($dev){ $pageData = sqlQueryRow("SELECT propertyvalue FROM " . $site . "_contentsdev WHERE propertyname='" . $property . "' AND componentname='$component_name' AND pagedev=$page"); }else{ if(empty($cache)){ $data = DB::GetTable("SELECT * FROM " . $site . "_contents"); foreach($data as $row){ $cache[$row["propertyname"]][$row['componentname']][$row['page']] = $row['propertyvalue']; } } //$pageData = sqlQueryRow("SELECT propertyvalue FROM " . $site . "_contents WHERE propertyname='" . $property . "' AND componentname='$component_name' AND page=$page"); $pageData = $cache[$property][$component_name][$page]; } if(($pageData==null)and($page!=-1)){ $data = null; if($copypage){ while(($copypage)and($data == null)){ if($cache[$property][$component_name][$copypage]){ $data = $cache[$property][$component_name][$copypage]; }else{ $data = sqlQueryValue("SELECT propertyvalue FROM " . $site . "_contents WHERE propertyname='" . $property . "' AND componentname='$component_name' AND page=$copypage"); } if($data == null){ $copypage = sqlQueryValue("SELECT -parent FROM " . $site . "_views WHERE view_id=" . Abs($copypage)); } } } if($data==null){ if($cache[$property][$component_name][-1]){ $data = $cache[$property][$component_name][-1]; }else{ $data = sqlQueryValue("SELECT propertyvalue FROM " . $site . "_contents WHERE propertyname='" . $property . "' AND componentname='$component_name' AND page=-1"); } } }else{ $data = is_array($pageData) ? $pageData['propertyvalue'] : $pageData; } if($data==null){ if($type){ $properties = getPropertiesTable($type); $data = $properties[$property]['value']; } } return $data; } function setProperty($property, $value, $component_name, $page, $site, $dev) { if ($dev) { sqlQuery("DELETE FROM " . $site . "_contentsdev WHERE propertyname='" . $property . "' AND componentname='$component_name' AND pagedev=$page"); sqlQuery("INSERT INTO " . $site . "_contentsdev (pagedev, componentname, propertyname, propertyvalue) VALUES ('$page', '$component_name', '$property', '$value')"); } else { sqlQuery("DELETE FROM " . $site . "_contents WHERE propertyname='" . $property . "' AND componentname='$component_name' AND page=$page"); sqlQuery("INSERT INTO " . $site . "_contents (page, componentname, propertyname, propertyvalue) VALUES ('$page', '$component_name', '$property', '$value')"); } } function getPropertyMassive($property, $component_name, $type, $page, $site, $copypage, $dev=0) { if(isset($GLOBALS['cachedproperty'][$property][$component_name])) { return $GLOBALS['cachedproperty'][$property][$component_name]; } else { if ($dev) $pageData = sqlQueryData("SELECT propertyvalue, componentname FROM " . $site . "_contentsdev WHERE propertyname='" . $property . "' AND pagedev=$page"); else $pageData = sqlQueryData("SELECT propertyvalue, componentname FROM " . $site . "_contents WHERE propertyname='" . $property . "' AND page=$page"); foreach($pageData as $row) { $GLOBALS['cachedproperty'][$property][$row['componentname']] = $row['propertyvalue']; } if($page!=-1) { $data = null; if($copypage) { while(($copypage)) { //if ($dev) // $data = sqlQueryValue("SELECT propertyvalue FROM " . $site . "_contentsdev WHERE propertyname='" . $property . "' AND componentname='$component_name' AND pagedev=$copypage"); //else $data = sqlQueryData("SELECT propertyvalue, componentname FROM " . $site . "_contents WHERE propertyname='" . $property . "' AND page=$copypage"); foreach($data as $row) { if(!isset($GLOBALS['cachedproperty'][$property][$row['componentname']])) $GLOBALS['cachedproperty'][$property][$row['componentname']] = $row['propertyvalue']; } $copypage = sqlQueryValue("SELECT -parent FROM " . $site . "_views WHERE view_id=" . Abs($copypage)); } } //process language default $lang_id = $GLOBALS['language_id']; $template_id = $GLOBALS['template_id']; if($template_id && $lang_id) { if(!isset($GLOBALS['cachedlangview' . $template_id . '_' . $lang_id])) { $copypage = sqlQueryValue('SELECT -view_id FROM ' . $site . '_views WHERE template_id = ' . $template_id . ' AND language_id = ' . $lang_id); $GLOBALS['cachedlangview' . $template_id . '_' . $lang_id] = $copypage; }else { $copypage = $GLOBALS['cachedlangview' . $template_id . '_' . $lang_id]; } if($copypage) { $data = sqlQueryData("SELECT propertyvalue, componentname FROM " . $site . "_contents WHERE propertyname='" . $property . "' AND page=$copypage"); foreach($data as $row) { if(!isset($GLOBALS['cachedproperty'][$property][$row['componentname']])) $GLOBALS['cachedproperty'][$property][$row['componentname']] = $row['propertyvalue']; } } } $data = sqlQueryData("SELECT propertyvalue, componentname FROM " . $site . "_contents WHERE propertyname='" . $property . "' AND page=-1"); foreach($data as $row) { if(!isset($GLOBALS['cachedproperty'][$property][$row['componentname']])) $GLOBALS['cachedproperty'][$property][$row['componentname']] = $row['propertyvalue']; } } $data = $GLOBALS['cachedproperty'][$property][$component_name]; return $data; } } function setWapProperty($property, $value, $component_name, $page, $site, $dev) { if ($dev) { sqlQuery("DELETE FROM " . $site . "_wapcontentsdev WHERE propertyname='" . $property . "' AND componentname='$component_name' AND wappagedev=$page"); sqlQuery("INSERT INTO " . $site . "_wapcontentsdev (wappagedev, componentname, propertyname, propertyvalue) VALUES ('$page', '$component_name', '$property', '$value')"); } else { sqlQuery("DELETE FROM " . $site . "_wapcontents WHERE propertyname='" . $property . "' AND componentname='$component_name' AND wappage=$page"); sqlQuery("INSERT INTO " . $site . "_wapcontents (wappage, componentname, propertyname, propertyvalue) VALUES ('$page', '$component_name', '$property', '$value')"); } } function createComponentCombobox($site_id, $page_id, $selname, $template_editor=0) { if ($template_editor) { $id = $page_id; list($data, $copybody) = sqlQueryRow("SELECT body, copybody FROM " . $site_id . "_templates WHERE template_id=$id"); while($copybody) list($data, $copybody) = sqlQueryRow("SELECT body, copybody FROM " . $site_id . "_templates WHERE template_id=$copybody"); $data = attachSubTemplates($data, $site_id); $r = componentArray($data, 0); $html = "\n".''; } else { list($template,$copypage) = sqlQueryRow("SELECT template,copypage FROM ". $site_id . "_pagesdev WHERE pagedev_id=$page_id"); if($template) { list($data, $copybody) = sqlQueryRow("SELECT body, copybody FROM " . $site_id . "_templates WHERE template_id=$template"); while($copybody) list($data, $copybody) = sqlQueryRow("SELECT body, copybody FROM " . $site_id . "_templates WHERE template_id=$copybody"); $data = attachSubTemplates($data, $site_id); } $r = componentArray($data, $page_id); $id = sqlQueryValue("SELECT page_id FROM ".$site_id."_pagesdev WHERE pagedev_id=".$page_id); $html = "\n".''; } foreach($r as $row) { if (!$template_editor) { //get page_id of the original page from pages table $id = sqlQueryValue("SELECT page_id FROM ".$site_id."_pagesdev WHERE pagedev_id=$page_id"); if(HasComponentPermissionPage($site_id, $id, $row['name'])) { $hidden = getProperty("visible",$row['name'],$row['type'],$page_id,$site_id,$copypage); $opts = getComponentParams($row['options']); if($hidden) { $opt = "color:#999999;"; } else { $opt = "color:#000000"; } $html .= "\n".''.str_repeat(" ", $row['ind']).'('.$row['type'] .') ' . iif($opts['fullname'], $opts['fullname'], $row['name']) .''; } } else { if(HasComponentPermission($site_id, $page_id, $row['name'])) { $hidden = getProperty("visible",$row['name'],$row['type'],-1,$site_id,$copypage); $opts = getComponentParams($row['options']); if($hidden) { $opt = "color:#999999;"; } else { $opt = "color:#000000"; } $html .= "\n".''.str_repeat(" ", $row['ind']).'('.$row['type'] .') ' . iif($opts['fullname'], $opts['fullname'], $row['name']) .''; } } } $html .= ''; return $html; } function borderDiv($name, $contentEditable=true) { if ($contentEditable==false) $a = " contenteditable=false"; else $a = ""; return ''; } function outputGraphicalComponent(&$hascontent, $type, $name, $page_id, $noDiv, $paramstr = '', $dontprocessinnercomponents = false, &$toolbarfunc, $skippermissioncheck = false, $pagedev_id, $canloaddynamically = false) { global $site_id; $filename = getComponentFilePath($type); $hascontent = false; if(file_exists($filename)) { $GLOBALS['design_view']=true; profiler_add('Design component ' . $type . ' ' . $name, 5); include_once($filename); $obj = new $type($name); $obj->dev = true; $obj->visualedit = true; $obj->componentParamStr = $paramstr; $params = getComponentParams($paramstr); $obj->RefineParams($params); $obj->componentParams = $params; //get copypage for page_id $copypage = sqlQueryValue("SELECT copypage FROM ".$site_id."_pagesdev WHERE pagedev_id=$pagedev_id"); $hastoolbar = $obj->toolbar($script, $toolbars, $btnids, $onclick); if($hastoolbar) { $scripts = "\n".'SelectComponent(document.getElementById("div_'.$name.'"),\''.$name.'\',\''.$type.'\',1);ClearAllToolbars(1);'; $c = 0; if(is_array($toolbars)){ foreach($toolbars as $t) { $c++; $scripts .= "\n".'SetToolbarHTML(' . $c . ',\''.parseForJScript($t,true).'\', 1);'; } } if(is_array($btnids)){ foreach($btnids as $btnid) { if (preg_match("/CMB$/",$btnid)) { $scripts .= "\n".'window.parent.window.document.all["'.$btnid.'"].onchange = window.'.$btnid.'_onchange;'; } else { $scripts .= "\n".'window.parent.window.document.all["'.$btnid.'"].onclick = window.'.$btnid.'_onclick;'; } } } $scripts .= $onclick; $toolbarfunc = $script . "\n" . $scripts; } if($noDiv) { $ret = ''; }else { if(!$skippermissioncheck) { //get permissions from original page if(!HasComponentPermissionPage($site_id, $page_id, $name)) { $params['novisualedit'] = true; } } $visualhidden = $params['novisualvisible']; if((!$params['novisualedit'])and(!$visualhidden)) { $hidden = getPropertyMassive('visible', $name, $type, $pagedev_id, $site_id, $copypage, $dev=1); if($hidden) { $background = ''; $hiddenstyle = ' display: none;'; }else { $background = ''; $hiddenstyle = ' display: inline;'; if($params['outborder'] && !$params['forceinline']) $hiddenstyle = ' display: block;'; } if($params['outborder'] && !$params['noborder']) { $borderstyle = 'border: 1px dashed #808080;'; }else { $borderstyle = ''; } $domain = $GLOBALS['domain']; $class = iif($params['class'], '', 'graphicaleditdiv'); $ret = 'CanLoadDesignDynamically())){ $ret .= ''; } $ret .= iif($params['spanclass'], '', ''); } } if(!$visualhidden) { $GLOBALS['component_name'] = $name; $GLOBALS['page_id'] = $page_id; $GLOBALS['pagedev_id'] = $pagedev_id; if(!$params['novisualedit']) $GLOBALS['design_view'] = true; ob_start(); if($params['novisualedit']) { if(!$obj->getProperty('visible')){ $obj->Output(); } }else { if(!$hidden) { if($canloaddynamically && $obj->CanLoadDesignDynamically()) echo ' '; else { $obj->Design(); } } } $cont = ob_get_contents(); ob_end_clean(); //unset($GLOBALS['pagedev_id']); /*if(!$dontprocessinnercomponents) { //process inner components as well $r = componentArray($cont, $page_id); foreach($r as $c) { $cont = str_replace($c['tag'], outputGraphicalComponent($hascontent, $c['type'], $c['name'], $page_id, false, $c['options']), $cont, $toolbarfunc); } }*/ $ret .= $cont; $hascontent = ((strlen($cont))and(!$hidden)); $GLOBALS['design_view'] = false; } profiler_add('Design component ' . $type . ' ' . $name, 6); }else { $ret .= '' . $name . ' ' . $type ; $hascontent = (!$hidden); } if((!$noDiv)and(!$params['novisualedit'])and(!$visualhidden)) { $ret .= iif($params['spanclass'], '', ''); $ret .= ''; } return $ret; } //-------------------------------------- function outputTemplateGraphicalComponent(&$hascontent, $type, $name, $template_id, $noDiv, $paramstr = '', $dontprocessinnercomponents = false, &$toolbarfunc, $skippermissioncheck = false) { global $site_id; $filename = $GLOBALS['cfgDirRoot'] . "components/class.$type.php"; $hascontent = false; if(file_exists($filename)) { $GLOBALS['design_view']=true; include_once($filename); $obj = new $type($name); $obj->visualedit = true; $params = Array(); if($noDiv) { $ret = ''; }else { $params = getComponentParams($paramstr); if(!$skippermissioncheck) { /* if(!HasComponentPermissionPage($site_id, $page_id, $name)) { $params['novisualedit'] = true; } */ } $visualhidden = $params['novisualvisible']; if((!$params['novisualedit'])and(!$visualhidden)) { $hidden = getProperty('visible', $name, $type, -1, $site_id, $copypage); if($hidden) { $background = ''; $hiddenstyle = ' display: none;'; }else { $background = ''; $hiddenstyle = ' display: inline;'; } $domain = $GLOBALS['domain']; $ret = ''; }*/ // $notable = getProperty('notable', $name, $type, $page_id, $site_id); $notable = true; if(!$notable) $ret .= ''; $ret .= iif($params['spanclass'], '', ''); } } if(!$visualhidden) { $GLOBALS['component_name'] = $name; $GLOBALS['page_id'] = -1; if(!$params['novisualedit']) $GLOBALS['design_view'] = true; ob_start(); /*if($params['novisualedit']) { if(!$obj->getProperty('visible')) $obj->Output(); }else*/ $obj->DesignTemplateEx(); $cont = ob_get_contents(); ob_end_clean(); /* if(!$dontprocessinnercomponents) { //process inner components as well $r = componentArray($cont, $page_id); foreach($r as $c) { $cont = str_replace($c['tag'], outputTemplateGraphicalComponent($hascontent, $c['type'], $c['name'], $page_id, false, $c['options']), $cont, $toolbarfunc); } } */ $ret .= $cont; $hascontent = ((strlen($cont))and(!$hidden)); $GLOBALS['design_view'] = false; } }else { $ret .= '' . $name . ' ' . $type ; $hascontent = (!$hidden); } if((!$noDiv)and(!$params['novisualedit'])and(!$visualhidden)) { $ret .= iif($params['spanclass'], '', ''); if(!$notable) $ret .= ''; $ret .= ''; } return $ret; } //-------------------------------------- function EditCollection($collection) { $category_id = $collection->collection_id; $site_id = $collection->site_id; if(isset($_GET['editpage']) && intval($_GET['editpage']) > 0) { $_SESSION[$collection->name . '_coledit_active_page'] = intval($_GET['editpage']) - 1; $forced_page = true; }else { $forced_page = false; } if($_GET['ordercolumn']) { $ordercol = $_GET['ordercolumn']; if($_GET['desc']) $ordercol .= ' DESC'; }else { $ordercol = ''; } $recordposition = ''; $data = $collection->GetEditData(intval($_SESSION[$collection->name . '_coledit_active_page']), $count, $recordposition, $ordercol); //if active page is outside data range, re-request data if($_SESSION[$collection->name . '_coledit_active_page'] > floor($count / $collection->GetEditPageSize())) { $_SESSION[$collection->name . '_coledit_active_page'] = 0; $data = $collection->GetEditData(intval($_SESSION[$collection->name . '_coledit_active_page']), $count, $recordposition, $ordercol); } $cols = $collection->GetDisplayColumns(); foreach ($cols as $key=>$col) { if ($col['timestamp']) { $date_cols[] = $key; } } //legacy stuff, please never use date_cols if ($date_cols) { foreach ($data as $key=>$row) { foreach ($date_cols as $date_col) $data[$key][$date_col] = date("Y-m-d H:i:s", $row[$date_col]); } } require("class.datagrid.php"); //make normal columns sortable foreach($cols as $key => $col) { if(!isset($col['sortable'])) { $cols[$key]['sortable'] = true; if($_GET['ordercolumn'] == $key) { $cols[$key]['sorted'] = true; } } } $Table = new DataGrid(); $Table->cols = $cols; $Table->data = $data; $Table->footer = false; $Table->rowformat = " id=\"tablerow{%item_id%}\" onClick=\"javascript:HighLightTR(this, {%item_id%},1);\" oncontextmenu=\"javascript:HighLightTR(this, {%item_id%},1); showMenu(this, event); return false;\""; $Table->sortlinkformat = preg_replace('/&ordercolumn=[a-zA-Z0-9_]*/s', '', $_SERVER["REQUEST_URI"]) . '&ordercolumn=%s'; $Table->sortlinkformat = preg_replace('/&desc=[a-zA-Z0-9_]*/s', '', $Table->sortlinkformat); if($count > 0) { $Table->pagecount = ceil($count / $collection->GetEditPageSize()); $Table->pagelen = 1; $Table->linkformat = preg_replace('/&editpage=[0-9]*/s', '', $_SERVER["REQUEST_URI"]) . '&editpage=%d'; $Table->pagenum = min($Table->pagecount, $_SESSION[$collection->name . '_coledit_active_page'] + 1); } echo $Table->output(); echo ''; if($_GET['selrow']) { echo ''; } } function listPageComponents($site_id, $page_id){ list($pagedev_id, $title, $copypage) = sqlQueryRow('SELECT pagedev_id, title, copypage FROM ' . $site_id . '_pagesdev WHERE page_id = ' . $page_id . ' ORDER BY lastmod DESC LIMIT 1'); if($pagedev_id){ $template = sqlQueryValue("SELECT template FROM ". $site_id . "_pagesdev WHERE pagedev_id=$pagedev_id"); } if($template){ list($data, $copybody) = sqlQueryRow("SELECT body, copybody FROM " . $site_id . "_templates WHERE template_id=".$template); while($copybody){ list($data, $copybody) = sqlQueryRow("SELECT body, copybody FROM " . $site_id . "_templates WHERE template_id=".$copybody); } } $data = attachSubTemplates($data, $site_id); return componentArray($data, $pagedev_id); } /* DB functions */ function var_dump_ret($mixed = null) { ob_start(); var_dump($mixed); $content = ob_get_contents(); ob_end_clean(); return $content; } function db_error($desc, $die=false) { if ($GLOBALS['SqlErrorShow']) { echo "\n"; echo "Database Error\n"; echo "Description: $desc\n"; echo "MySQL Error: ", mysql_error(), "\n"; if ($die) echo "Status: This script cannot continue, terminating.\n"; echo "".print_r(debug_backtrace(), true).""; } if ($GLOBALS['SqlErrorMail'] && mysql_error() != 'No database selected' && $desc != 'Can\'t select database' && strpos($desc, 'Can\'t connect to localhost') === false && mysql_error() != 'Too many connections' && mysql_error() != 'MySQL server has gone away') { if(!isset($GLOBALS['SqlErrorMailSentTimes'])) $GLOBALS['SqlErrorMailSentTimes'] = 0; $GLOBALS['SqlErrorMailSentTimes']++; if($GLOBALS['SqlErrorMailSentTimes'] <= 4) { mail($GLOBALS['SqlErrorMail'], "MySQL error", "User: " . $_SESSION['session_user'] . "\nError: " . mysql_error() . "\nLink: http://" . $_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'] . "\nDescription: $desc" . "\nStack: ". var_dump_ret(debug_backtrace())); } //echo $GLOBALS['SqlErrorMail']; die; } if ($die) die(); } function db_connect($dbhost, $dbname, $dbuser, $dbpass, $dbport=false) { if ($dbport){ if (! $dbh = mysql_connect($dbhost.':'.$dbport, $dbuser, $dbpass)) { db_error('Can\'t connect to '.$dbhost.':'.$dbport.' as '.$dbuser); } } else{ if (! $dbh = mysql_connect($dbhost, $dbuser, $dbpass)) { db_error("Can't connect to $dbhost as $dbuser"); } } if (! mysql_select_db($dbname)) { db_error("Can't select database $dbnam"); return false; } $row = mysql_fetch_assoc(mysql_query('SHOW TABLE STATUS LIKE "sites"')); if ($row['Collation'] != 'latin1_swedish_ci') mysql_query('SET NAMES utf8'); return $dbh; } function db_disconnect($link) { mysql_close($link); } function log_slow_query($query, $time){ file_put_contents(SLOW_QUERY_FILE, "Query(MySQL): " . $query . PHP_EOL . "Exec time: ".$time."" . PHP_EOL . "---------------" . PHP_EOL, FILE_APPEND); } function log_query($query, $time){ file_put_contents(QUERY_FILE, "Query(".$GLOBALS['total_queries_executed'].".)((MySQL)): " . $query . PHP_EOL . "Exec time: ".$time . PHP_EOL . "---------------" . PHP_EOL, FILE_APPEND); } function db_query($query, $link) { $GLOBALS['total_queries_executed']++; $start = microtime(true); if(LOG_SLOW_QUERIES || LOG_QUERIES){ $start = microtime(true); } DB::Query($query); if(LOG_SLOW_QUERIES || LOG_QUERIES){ $end = microtime(true); $dif = $end - $start; $GLOBALS['total_query_time'] += $dif; if(LOG_SLOW_QUERIES){ if($dif > SLOW_QUERY_TIME_LIMIT){ log_slow_query($query, $dif); } } if(LOG_QUERIES){ // all log_query($query, $dif); } } if (! $qid) { db_error("Can't execute query: $query"); } return $qid; } function db_fetch_object($qid) { return mysql_fetch_object($qid); } function db_fetch_array($qid) { return mysql_fetch_array($qid); } function db_fetch_array_assoc($qid) { return mysql_fetch_assoc($qid); } function db_insert_id($link) { return mysql_insert_id($link); } function db_num_rows() { return mysql_num_rows(); } function db_escape($s) { return mysql_real_escape_string($s); } /* SQL functions */ function sqlLastID() { return db_insert_id($GLOBALS['DBH']); } function sqlQueryData($query, $params = array(), $fetch = PDO::FETCH_BOTH) { $result = DB::GetTable($query, $params, $fetch); return $result; } function sqlQueryDataAssoc($query, $params = array()) { $result = DB::GetTable($query, $params); return $result; } function sqlQueryColumn($query, $params = array()) { $result = DB::GetColumn($query, $params); return $result; } function sqlQueryRow($query, $params = array(), $fetch = PDO::FETCH_BOTH) { $result = DB::GetRow($query, $params, $fetch); return $result; } function sqlQueryRowAssoc($query, $params = array()) { $result = DB::GetRow($query, $params); return $result; } function sqlQueryValue($query, $params = array()) { $result = DB::GetValue($query, $params); return $result; } function sqlQuery($query, $params = array()) { return DB::Query($query, $params); } function sqlQueryDataAndID($query, &$qid) { $result = false; $i = 0; if ($qid = db_query($query, $GLOBALS['DBH'])) while ($r = db_fetch_array($qid)) $result[$i++] = $r; return $result; } // Login and session handling related library // Aivars Irmejs function valid_login($username, $password, $ip, $ignoreenabledrow=false){ if ($_SESSION['admin_logged_in']){ $row = sqlQueryRow('SELECT * FROM users WHERE username="Admin"'); $_SESSION['userdata'] = $row; $GLOBALS["currentUserID"] = $row['user_id']; $GLOBALS["currentUserSiteID"] = $row['site_id']; $GLOBALS['loginfailmessage'] = ''; return true; } if($username){ $user = DB::GetRow("SELECT * FROM users WHERE username = :username", array(":username" => $username)); if(!$user){ $GLOBALS['loginfailmessage'] = 'Invalid username or password'; return false; } if(!valid_password($password, $user['password'])){ $GLOBALS['loginfailmessage'] = 'Incorrect username or password'; return false; } if($user['addresses'] && $ip){ $IPs = explode("\n", $user['addresses']); $IIPs = Array(); foreach($IPs as $key => $IPadd){ $IIPs[] = trim($IPadd); } $IPs = $IIPs; if(!in_array($ip, $IPs)){ $GLOBALS['loginfailmessage'] = 'Logging in from this IP is not allowed for user ' . $username; return false; } } $_SESSION['userdata'] = $user; $GLOBALS["currentUserID"] = $user['user_id']; $GLOBALS["currentUserSiteID"] = $user['site_id']; if(($user["enabled"])or($ignoreenabledrow)){ $GLOBALS['loginfailmessage'] = ''; return true; }else{ $GLOBALS['loginfailmessage'] = 'User disabled'; return false; } }else{ $GLOBALS['loginfailmessage'] = 'No user specified'; return false; } } function encode_password($password){ $salt = generate_random_string(5); return $salt.hash("sha256", $salt.hash("sha256", $password)); } // pasw is being encoded like this: $password = $salt.sha256($salt.sha256($password)); // sha256($password) part comes from user browser, as it's encoded before sent over function valid_password($received_pasw, $pasw){ $salt = substr($pasw, 0, 5); $hash = substr($pasw, 5); return (hash("sha256", $salt.$received_pasw) == $hash) ? true : false; } function logged_in(){ if($_GET['forcelogin']){ return valid_login($_GET["user"], $_GET["pass"], $_SERVER['REMOTE_ADDR']); }else{ return valid_login($_SESSION["session_user"], $_SESSION["session_pass"], $_SERVER['REMOTE_ADDR']); } } function log_in($username, $password, $ip){ $minutes = 5; $attempts = 5; // 5 unsuccessful login attempts and last one was less than 5 min ago if($_SESSION['unsuccessful_login_attempts'] >= $attempts && time() - $_SESSION['last_unsuccessful_login_attempt'] < $minutes * 60){ $GLOBALS['loginfailmessage'] = 'Login form is disabled for '.$minutes.' minutes after '.$attempts.' unsuccessful login attempts'; return false; } if(valid_login($username, $password, $ip)){ $_SESSION['unsuccessful_login_attempts'] = 0; login_successful($username, $password); return true; }else{ login_failed($username); // if we had 5 unsuccessful login attempts we should start counting from 0 $_SESSION['unsuccessful_login_attempts'] = ($_SESSION['unsuccessful_login_attempts'] >= $attempts) ? 0 : $_SESSION['unsuccessful_login_attempts']; $_SESSION['unsuccessful_login_attempts']++; $_SESSION['last_unsuccessful_login_attempt'] = time(); return false; } } function login_successful($username, $password, $msg='') { $row = DB::GetRow('SELECT * FROM users WHERE username=:username', array(":username" => $username)); $GLOBALS["currentUserID"] = $row['user_id']; session_start(); $_SESSION['session_user'] = $username; $_SESSION['session_pass'] = $password; add_log('Logged in: ' . $username.($msg ? '( '.$msg.' )' : ''), 0); } function login_failed($username, $msg='') { session_start(); $_SESSION["session_user"] = ''; $_SESSION["session_pass"] = ''; add_log('Login failed: ' . $username.($msg ? '( '.$msg.' )' : ''), 0); } function log_out() { session_destroy(); } ?> function CheckPermissionByID($userID, $perm_num, $data, $data2) { $adddata = ''; if($data) $adddata .= " AND data='$data'"; if($data2) $adddata .= " AND data2='$data2'"; $val = sqlQueryValue("SELECT perm_id FROM permissions WHERE perm_num=$perm_num AND isuser=1 AND id=$userID" . $adddata); if($val != null) return true; //User has the permission $groups = sqlQueryColumn("SELECT group_id FROM users_groups WHERE user_id=$userID"); if($groups != null) { $groups = join(" OR id=", $groups); $val = sqlQueryValue("SELECT perm_id FROM permissions WHERE perm_num=$perm_num AND isuser=0 AND (id=$groups)" . $adddata); if($val != null) { return true; //User's group has the permission } } return false; } function CheckPermission($perm_num, $data = '', $data2 = '') { return CheckPermissionByID($GLOBALS['currentUserID'], $perm_num, $data, $data2); } function HasComponentPermission($site_id, $template_id, $component_name) { $userID = $GLOBALS['currentUserID']; $row = sqlQueryRow("SELECT * FROM permissions WHERE perm_num=14 AND isuser=1 AND id=$userID AND data=$site_id AND data2=$template_id"); $extradata = $row['extradata']; $groups = sqlQueryColumn("SELECT group_id FROM users_groups WHERE user_id=$userID"); if($groups != null) { foreach($groups as $g) { $row = sqlQueryRow("SELECT * FROM permissions WHERE perm_num=14 AND isuser=0 AND id=$g AND data=$site_id AND data2=$template_id"); if($row['extradata']) { if($extradata) { $extradata .= ','; } $extradata .= $row['extradata']; } } } if(!$extradata) { return true; }else { $allowed = explode(',', $extradata); return in_array($component_name, $allowed); } } function HasComponentPermission2($site_id, $page_id, $component_name) { $userID = $GLOBALS['currentUserID']; $row = sqlQueryRow("SELECT * FROM permissions WHERE perm_num=16 AND isuser=1 AND id=$userID AND data=$site_id AND data2=$page_id"); $extradata = $row['extradata']; $groups = sqlQueryColumn("SELECT group_id FROM users_groups WHERE user_id=$userID"); if($groups != null) { foreach($groups as $g) { $row = sqlQueryRow("SELECT * FROM permissions WHERE perm_num=16 AND isuser=0 AND id=$g AND data=$site_id AND data2=$page_id"); if($row['extradata']) { if($extradata) { $extradata .= ','; } $extradata .= $row['extradata']; } } } if(!$extradata) { return true; }else { $allowed = explode(',', $extradata); return in_array($component_name, $allowed); } } function HasComponentPermissionPage($site_id, $page_id, $component_name) { $template_id = sqlQueryValue("SELECT template FROM " . $site_id . "_pages WHERE page_id='$page_id'"); return (HasComponentPermission($site_id, $template_id, $component_name) && HasComponentPermission2($site_id, $page_id, $component_name)); } //Check if user has any of the permissions specified in the parameter array function CheckGlobalPermissions($a) { foreach($a as $num) { if(CheckPermission($num)) return true; } return false; } function CheckSitePermissions($a, $siteID) { global $site_id; foreach($a as $num) { if((CheckPermission($num, $siteID))and($site_id == $siteID)) return true; } return false; } function AddGroupPermission($groupID, $permNum, $data, $data2) { sqlQuery("INSERT INTO permissions (perm_num, isuser, id, data, data2) VALUES ($permNum, 0, $groupID, $data, $data2)"); } function EchoBoo() { echo ' function boooooo() { FillFromArray(); FillPagesFromArray(5); //fill checked components if possible try { for(f=0;f0?','.$GLOBALS['site_id']:'').'); ChangeExtraData(doAdd, PermID, ExtraData); } try { // parentframes("usergroups.Select_1").onchange = boooooo; } catch (e) {} /*]]>*/ '; } function OutputPermProc($perm_type, $site_id, $data, $data2) { switch($perm_type) { /* case 2: $pages = sqlQueryValue("SELECT page_id FROM " . $data . "_pages WHERE parent=" . $data2); if($pages) { return ' Apply to subpages'; } break; */ case (2 || 3 || 4 || 5): $specified_comp = 14; $n = 1; if ($perm_type==2) { $specified_comp = 16; $n = 2; /* $pages = sqlQueryValue("SELECT page_id FROM " . $data . "_pages WHERE parent=" . $data2); if($pages) { echo ' Apply to subpages'; } */ } if ($perm_type==4) { $specified_comp = 22; $n = 2; } if ($perm_type==5) { $specified_comp = 26; $n = 2; } echo ' '; //print_R($a); //echo ' '; $s .= ''; return $s; break; default: break; } } function BeforeDeletePermission($num, $isuser, $id, $data, $data2) { switch($num) { case 11: case 13: //page permissions //check if "subpage" is checked and act accordingly if($_POST['subpages']) { //data = site_id, data2 = page_id //obtain all subpages for this page $pages = sqlQueryColumn("SELECT page_id FROM " . $data . "_pages WHERE parent=" . $data2); foreach($pages as $page) { BeforeDeletePermission($num, $isuser, $id, $data, $page); sqlQuery("DELETE FROM permissions WHERE perm_num=$num AND isuser=" . IIF($isuser,1,0) . " AND id=$id AND data=$data AND data2=$page"); } } break; default: break; } } function AfterAddPermission($perm_id, $num, $isuser, $id, $data, $data2) { switch($num) { case 11: case 13: if($_POST['subpages']) { $pages = sqlQueryColumn("SELECT page_id FROM " . $data . "_pages WHERE parent=" . $data2); foreach($pages as $page) { sqlQuery("INSERT INTO permissions (perm_num, isuser, id, data, data2) VALUES ($num, ".IIF($isuser,1,0).", $id, $data, $page)"); $where = 'WHERE perm_num="' . $num . '"'; if($isuser) $where .= ' AND isuser=1'; else $where .= ' AND isuser=0'; if($data2) $where .= ' AND data2=\'' . $page . '\''; if($data) $where .= ' AND data=\'' . $data . '\''; $where .= ' AND id="' . $id . '"'; $p = sqlQueryValue("SELECT perm_id FROM permissions " . $where); AfterAddPermission($p, $num, $isuser, $id, $data, $page); } } break; case 22: case 16: case 14: case 26: //go through all permchanges, create extradata from it if($isuser) $u = 'u'; else $u = 'g'; $u .= $id; $components = Array(); $commands = split(';', $_POST['permchanges']); foreach($commands as $command) { if($command) { $s = split(':', $command); if($s[3] == $u) { if($s[0] == '*') $components[$s[4]] = true; if($s[0] == '/') unset($components[$s[4]]); } } } $s = ''; foreach($components as $component => $val) { if($s) $s .= ','; $s .= $component; } sqlQuery("UPDATE permissions SET extradata='$s' WHERE perm_id=$perm_id"); //echo "UPDATE permissions SET extradata='$s' WHERE perm_id=$perm_id"; break; default: break; } } function MakeGlobalPermVars() { if((!isset($_SESSION['user_site_permissions']))and($_GET['site_id'])and($GLOBALS['currentUserID'])) { include($GLOBALS['cfgDirRoot'] . "backend/modules/permissions.texts.php"); foreach($permissions_list as $key => $p) { if($p['type'] == 1) { $_SESSION['user_site_permissions'][$key] = CheckPermission($key, $_GET['site_id']); } } } $GLOBALS['user_site_permissions_modifysite'] = $_SESSION['user_site_permissions'][6]; $GLOBALS['user_site_permissions_managepages'] = $_SESSION['user_site_permissions'][8]; $GLOBALS['user_site_permissions_managetemplates'] = $_SESSION['user_site_permissions'][9]; $GLOBALS['user_site_permissions_managewappages'] = $_SESSION['user_site_permissions'][19]; $GLOBALS['user_site_permissions_managewaptemplates'] = $_SESSION['user_site_permissions'][23]; $GLOBALS['user_site_permissions_managefiles'] = $_SESSION['user_site_permissions'][7]; $GLOBALS['user_site_permissions_manageusers'] = $_SESSION['user_site_permissions'][10]; $GLOBALS['user_site_permissions_managecollections'] = $_SESSION['user_site_permissions'][17]; $GLOBALS['user_site_permissions_managelists'] = $_SESSION['user_site_permissions'][66]; $GLOBALS['user_site_permissions_managedocuments'] = $_SESSION['user_site_permissions'][28]; $GLOBALS['user_site_permissions_admin'] = $_SESSION['user_site_permissions'][18]; $GLOBALS['user_site_permissions_stats'] = $_SESSION['user_site_permissions'][34]; } ?> function FormatForSearch($s) { while (preg_match("/\<\!\-\-(.*)?\-\-\>/Usi", $s, $regs)) { $s = str_replace($regs[0], '', $s); //echo htmlentities($regs[0]); } while (preg_match("/\(.*)?\<\/title\>/Usi", $s, $regs)) { $s = str_replace($regs[0], '', $s); // echo htmlentities($regs[0]); } while (preg_match("/\(.*)?\<\/head\>/Usi", $s, $regs)) { $s = str_replace($regs[0], '', $s); // echo htmlentities($regs[0]); } while (preg_match("/\
Description: $desc\n"; echo "MySQL Error: ", mysql_error(), "\n"; if ($die) echo "Status: This script cannot continue, terminating.\n"; echo "
".print_r(debug_backtrace(), true)."
$query
Apply to subpages