1<?php 2/** 3 * Coppermine Photo Gallery 4 * 5 * v1.0 originally written by Gregory Demar 6 * 7 * @copyright Copyright (c) 2003-2021 Coppermine Dev Team 8 * @license GNU General Public License version 3 or later; see LICENSE 9 * 10 * include/init.inc.php 11 * @since 1.6.12 12 */ 13 14define('COPPERMINE_VERSION', '1.6.12'); 15define('COPPERMINE_VERSION_STATUS', 'stable'); 16// Define path to jQuery for this version of Coppermine 17define('CPG_JQUERY_VERSION', 'js/jquery-1.12.4.js'); 18define('CPG_JQUERY_MIGRATE', 'js/jquery-migrate-1.4.1.js'); 19 20if (!defined('IN_COPPERMINE')) die('Not in Coppermine...'); 21 22function cpgGetMicroTime() 23{ 24 list($usec, $sec) = explode(' ', microtime()); 25 return ((float)$usec + (float)$sec); 26} 27$cpg_time_start = cpgGetMicroTime(); 28 29// Set a flag if register globals is on to show a warning to admin 30if (ini_get('register_globals') == '1' || strtolower(ini_get('register_globals')) == 'on') { 31 $register_globals_flag = true; 32} else { 33 $register_globals_flag = false; 34} 35 36require_once('include/inspekt.php'); 37 38// Set $strict to false to make the superglobals available 39$strict = TRUE; 40 41$superCage = Inspekt::makeSuperCage($strict); 42// Remove any variables introduced by register_globals, if enabled 43$keysToSkip = array('keysToSkip', 'register_globals_flag', 'superCage', 'cpg_time_start', 'key'); 44 45if ($register_globals_flag && is_array($GLOBALS)) { 46 foreach ($GLOBALS as $key => $value) { 47 if (!in_array($key, $keysToSkip) && isset($$key)) { 48 unset($$key); 49 } 50 } 51} 52 53// List of valid meta albums - needed for displaying 'no image to display' message 54$valid_meta_albums = array('lastcom', 'lastcomby', 'lastup', 'lastupby', 'topn', 'toprated', 'lasthits', 'random', 'search', 'lastalb', 'favpics', 'datebrowse'); 55 56// HTML tags replace pairs (used at some places for input validation) 57$HTML_SUBST = array('&' => '&', '"' => '"', '<' => '<', '>' => '>', '%26' => '&', '%22' => '"', '%3C' => '<', '%3E' => '>','%27' => ''', "'" => '''); 58 59// Store all reported errors in the $cpgdebugger 60require_once('include/debugger.inc.php'); 61 62// used for timing purposes 63$query_stats = array(); 64$queries = array(); 65 66// Initialise the $CONFIG array and some other variables 67$CONFIG = array(); 68 69$PHP_SELF = ''; 70 71$possibilities = array( 72 'REDIRECT_URL', 73 'PHP_SELF', 74 'SCRIPT_URL', 75 'SCRIPT_NAME', 76 'SCRIPT_FILENAME' 77); 78 79foreach ($possibilities as $test) { 80 if ( ($matches = $superCage->server->getMatched($test, '/([^\/]+\.php)$/')) ) { 81 $CPG_PHP_SELF = $matches[1]; 82 break; 83 } 84} 85/** 86 * TODO: $REFERER has a potential for exploitation as the QUERY_STRING is being fetched with getRaw() 87 * A probable solution is to parse the query string into its individual key and values and check 88 * them against a regex, recombine and use only if all the values are safe else set referer to index.php 89 */ 90$REFERER = urlencode($CPG_PHP_SELF . (($superCage->server->keyExists('QUERY_STRING') && $superCage->server->getRaw('QUERY_STRING')) ? '?' . $superCage->server->getRaw('QUERY_STRING') : '')); 91$ALBUM_SET = ''; 92$META_ALBUM_SET = ''; 93$FORBIDDEN_SET = ''; 94$FORBIDDEN_SET_DATA = array(); 95$CURRENT_CAT_NAME = ''; 96$CAT_LIST = ''; 97$LINEBREAK = "\r\n"; // For compatibility both on Windows as well as *nix 98 99// Define some constants 100define('USER_GAL_CAT', 1); 101define('FIRST_USER_CAT', 10000); 102define('TEMPLATE_FILE', 'template.html'); 103// Constants used by the cpg_die function 104define('INFORMATION', 1); 105define('ERROR', 2); 106define('CRITICAL_ERROR', 3); 107 108// Include config and functions files 109if (file_exists('include/config.inc.php')) { 110 ob_start(); 111 require_once 'include/config.inc.php'; 112 ob_clean(); 113} else { 114 // error handling: if the config file doesn't exist go to install 115 die('<html> 116 <head> 117 <title>Coppermine not installed yet</title> 118 <meta http-equiv="refresh" content="10;url=install.php" /> 119 <style type="text/css"> 120 <!-- 121 body { font-size: 12px; background: #FFFFFF; margin: 20%; color: black; font-family: verdana, arial, helvetica, sans-serif;} 122 --> 123 </style> 124 </head> 125 <body> 126 <img src="images/coppermine-logo.png" alt="Coppermine Photo Gallery - Your Online Photo Gallery" /><br /> 127 Coppermine Photo Gallery seems not to be installed correctly, or you are running coppermine for the first time. You\'ll be redirected to the installer. If your browser doesn\'t support redirect, click <a href="install.php">here</a>. 128 </body> 129</html>'); 130} 131 132$mb_utf8_regex = '[\xE1-\xEF][\x80-\xBF][\x80-\xBF]|\xE0[\xA0-\xBF][\x80-\xBF]|[\xC2-\xDF][\x80-\xBF]'; 133 134require 'include/functions.inc.php'; 135 136// Include logger functions 137include_once('include/logger.inc.php'); 138 139// see http://php.net/mbstring for details 140if (function_exists('mb_internal_encoding')) { 141 mb_internal_encoding('UTF-8'); 142} 143 144$CONFIG['TABLE_PICTURES'] = $CONFIG['TABLE_PREFIX'].'pictures'; 145$CONFIG['TABLE_ALBUMS'] = $CONFIG['TABLE_PREFIX'].'albums'; 146$CONFIG['TABLE_COMMENTS'] = $CONFIG['TABLE_PREFIX'].'comments'; 147$CONFIG['TABLE_CATEGORIES'] = $CONFIG['TABLE_PREFIX'].'categories'; 148$CONFIG['TABLE_CONFIG'] = $CONFIG['TABLE_PREFIX'].'config'; 149$CONFIG['TABLE_USERGROUPS'] = $CONFIG['TABLE_PREFIX'].'usergroups'; 150$CONFIG['TABLE_VOTES'] = $CONFIG['TABLE_PREFIX'].'votes'; 151$CONFIG['TABLE_USERS'] = $CONFIG['TABLE_PREFIX'].'users'; 152$CONFIG['TABLE_BANNED'] = $CONFIG['TABLE_PREFIX'].'banned'; 153$CONFIG['TABLE_EXIF'] = $CONFIG['TABLE_PREFIX'].'exif'; 154$CONFIG['TABLE_FILETYPES'] = $CONFIG['TABLE_PREFIX'].'filetypes'; 155$CONFIG['TABLE_ECARDS'] = $CONFIG['TABLE_PREFIX'].'ecards'; 156$CONFIG['TABLE_FAVPICS'] = $CONFIG['TABLE_PREFIX'].'favpics'; 157$CONFIG['TABLE_BRIDGE'] = $CONFIG['TABLE_PREFIX'].'bridge'; 158$CONFIG['TABLE_VOTE_STATS'] = $CONFIG['TABLE_PREFIX'].'vote_stats'; 159$CONFIG['TABLE_HIT_STATS'] = $CONFIG['TABLE_PREFIX'].'hit_stats'; 160$CONFIG['TABLE_TEMP_MESSAGES'] = $CONFIG['TABLE_PREFIX'].'temp_messages'; 161$CONFIG['TABLE_CATMAP'] = $CONFIG['TABLE_PREFIX'].'categorymap'; 162$CONFIG['TABLE_LANGUAGE'] = $CONFIG['TABLE_PREFIX'].'languages'; 163$CONFIG['TABLE_DICT'] = $CONFIG['TABLE_PREFIX'].'dict'; 164 165// Connect to database 166list($db_ext, $db_sub) = explode(':', $CONFIG['dbtype'].':'); 167$db_ext = $db_ext ?: 'mysqli'; 168require 'include/database/'.$db_ext.'/dbase.inc.php'; 169$CPGDB = new CPG_Dbase($CONFIG); 170 171if (!$CPGDB->isConnected()) { 172 log_write("Unable to connect to database: " . $CPGDB->getError(), CPG_DATABASE_LOG); 173 die('<strong>Coppermine critical error</strong>:<br />Unable to connect to database !<br /><br />'.$CPGDB->db_type.' said: <strong>' . $CPGDB->getError() . '</strong>'); 174} 175 176// Retrieve DB stored configuration 177$result = cpg_db_query("SELECT name, value FROM {$CONFIG['TABLE_CONFIG']}"); 178if (!$result) cpg_db_error('When read CONFIG from database '); 179while ( ($row = $result->fetchAssoc()) ) { 180 $CONFIG[$row['name']] = $row['value']; 181} // while 182$result->free(); 183 184// Check if Coppermine is allowed to store cookies (cookie consent is required and user has agreed to store cookies) 185define('CPG_COOKIES_ALLOWED', ($CONFIG['cookies_need_consent'] && !$superCage->cookie->keyExists($CONFIG['cookie_name'].'_cookies_allowed') ? false : true)); 186 187// A space cannot be stored in the config table since the value field is VARCHAR, so %20 is used instead. 188if ($CONFIG['keyword_separator'] == '%20') { 189 $CONFIG['keyword_separator'] = ' '; 190} 191 192if ($CONFIG['log_mode']) { 193 spring_cleaning('logs', (!empty($CONFIG['log_retention']) ? $CONFIG['log_retention'] : CPG_DAY * 2)); 194} 195 196// Record User's IP address 197$raw_ip = $superCage->server->testIp('REMOTE_ADDR') ? $superCage->server->getEscaped('REMOTE_ADDR') : '0.0.0.0'; 198 199if ($superCage->server->testIp('HTTP_CLIENT_IP')) { 200 $hdr_ip = $superCage->server->getEscaped('HTTP_CLIENT_IP'); 201} else { 202 if ($superCage->server->testIp('HTTP_X_FORWARDED_FOR')) { 203 $hdr_ip = $superCage->server->getEscaped('X_FORWARDED_FOR'); 204 } else { 205 $hdr_ip = $raw_ip; 206 } 207} 208 209// Reference 'site_url' to 'ecards_more_pic_target' 210$CONFIG['site_url'] =& $CONFIG['ecards_more_pic_target']; 211 212// Set the site_url in js_vars so that it can be used in js 213set_js_var('site_url', rtrim($CONFIG['site_url'], '/')); 214 215// Set a constant for the default language and theme (in the gallery config), since it might get replaced during runtime 216define('DEFAULT_LANGUAGE', $CONFIG['lang']); 217define('DEFAULT_THEME', $CONFIG['theme']); 218 219// Check for GD GIF Create support 220if ($CONFIG['thumb_method'] == 'im' || $CONFIG['thumb_method'] == 'imx' || function_exists('imagecreatefromgif')) { 221 $CONFIG['GIF_support'] = 1; 222} else { 223 $CONFIG['GIF_support'] = 0; 224} 225 226// Include plugin API 227require('include/plugin_api.inc.php'); 228if ($CONFIG['enable_plugins'] == 1) { 229 CPGPluginAPI::load(); 230} 231 232// Set UDB_INTEGRATION if enabled in admin 233if ($CONFIG['bridge_enable'] == 1 && !defined('BRIDGEMGR_PHP')) { 234 $BRIDGE = cpg_get_bridge_db_values(); 235} else { 236 $BRIDGE['short_name'] = 'coppermine'; 237 $BRIDGE['recovery_logon_failures'] = 0; 238 $BRIDGE['use_post_based_groups'] = false; 239} 240 241define('UDB_INTEGRATION', $BRIDGE['short_name']); 242 243require_once 'bridge/' . UDB_INTEGRATION . '.inc.php'; 244 245// Start output buffering 246ob_start('cpg_filter_page_html'); 247 248// Parse cookie stored user profile 249user_get_profile(); 250 251// Authenticate 252$cpg_udb->authenticate(); 253 254// Test if admin mode 255$USER['am'] = isset($USER['am']) ? (int)$USER['am'] : 0; 256define('GALLERY_ADMIN_MODE', USER_IS_ADMIN && $USER['am']); 257define('USER_ADMIN_MODE', USER_ID && USER_CAN_CREATE_ALBUMS && !GALLERY_ADMIN_MODE); 258 259// Set error logging level 260// Maze's new error report system 261if (!USER_IS_ADMIN) { 262 if (!$CONFIG['debug_mode']) { 263 $cpgdebugger->stop(); // useless to run debugger because there's no output 264 } 265 error_reporting(0); // hide all errors for visitors 266} 267 268$USER_DATA['allowed_albums'] = array(); 269 270if (!GALLERY_ADMIN_MODE) { 271 $result = cpg_db_query("SELECT aid FROM {$CONFIG['TABLE_ALBUMS']} WHERE moderator_group IN ".USER_GROUP_SET); 272 if ($result->numRows()) { 273 while ( ($row = $result->fetchAssoc()) ) { 274 $USER_DATA['allowed_albums'][] = $row['aid']; 275 } 276 } 277 $result->free(); 278} 279 280// Set the debug flag to be used in js var 281if ($CONFIG['debug_mode'] == 1 || ($CONFIG['debug_mode'] == 2 && GALLERY_ADMIN_MODE)) { 282 set_js_var('debug', true); 283} else { 284 set_js_var('debug', false); 285} 286 287// ******************************************************** 288// * Theme processing - start 289// ******************************************************** 290 291$CONFIG['theme_config'] = DEFAULT_THEME; // Save the gallery-configured setting 292 293if ($matches = $superCage->get->getMatched('theme', '/^[A-Za-z0-9_-]+$/')) { 294 $USER['theme'] = $matches[0]; 295 $hasURLtheme = true; 296} 297if (isset($USER['theme']) && !strstr($USER['theme'], '/') && is_dir('themes/' . $USER['theme'])) { 298 $CONFIG['theme'] = strtr($USER['theme'], '$/\\:*?"\'<>|`', '____________'); 299} else { 300 unset($USER['theme']); 301} 302// If no URL override, give plugins the chance to specify a theme 303if (empty($hasURLtheme)) 304 $CONFIG['theme'] = CPGPluginAPI::filter('theme_name', $CONFIG['theme']); 305if (!file_exists('themes/'.$CONFIG['theme'].'/theme.php')) { 306 $CONFIG['theme'] = 'curve'; 307} 308$THEME_DIR = 'themes/'.$CONFIG['theme'].'/'; 309require('themes/'.$CONFIG['theme'].'/theme.php'); // Load configured theme first 310require('include/themes.inc.php'); // All Fallback Theme Templates and Functions 311 312// ******************************************************** 313// * Theme processing - end 314// ******************************************************** 315 316if (defined('THEME_HAS_MENU_ICONS')) { 317 $ICON_DIR = $THEME_DIR . 'images/icons/'; 318} else { 319 $ICON_DIR = 'images/icons/'; 320} 321 322set_js_var('icon_dir', $ICON_DIR); 323 324// ******************************************************** 325// * Language processing --- start 326// ******************************************************** 327 328require('lang/english.php'); // Load the default language file: 'english.php' 329$CONFIG['lang_config'] = DEFAULT_LANGUAGE; // Save the gallery-configured setting 330$CONFIG['default_lang'] = $CONFIG['lang']; // Save default language 331 332$enabled_languages_array = array(); 333 334$result = cpg_db_query("SELECT lang_id FROM {$CONFIG['TABLE_LANGUAGE']} WHERE enabled='YES'"); 335while ($row = $result->fetchAssoc()) { 336 $enabled_languages_array[] = $row['lang_id']; 337} 338$result->free(); 339 340// Process language selection if present in URI or in user profile or try 341// autodetection if default charset is utf-8 342if ($matches = $superCage->get->getMatched('lang', '/^[a-z0-9_-]+$/')) { 343 $USER['lang'] = $matches[0]; 344} 345 346// Set the user preference to the language submit by URL parameter or by auto-detection 347// Only set the preference if a corresponding file language file exists. 348if (isset($USER['lang']) && !strstr($USER['lang'], '/') && file_exists('lang/' . $USER['lang'] . '.php')) { 349 $CONFIG['lang'] = strtr($USER['lang'], '$/\\:*?"\'<>|`', '____________'); 350} elseif ($CONFIG['charset'] == 'utf-8' && $CONFIG['language_autodetect'] != 0) { 351 include('include/select_lang.inc.php'); 352 if (file_exists('lang/' . $USER['lang'] . '.php') == TRUE) { 353 if (in_array($USER['lang'], $enabled_languages_array)) { 354 $CONFIG['lang'] = $USER['lang']; 355 } 356 } 357} else { 358 unset($USER['lang']); 359} 360 361if (!file_exists("lang/{$CONFIG['lang']}.php")) { 362 $CONFIG['lang'] = 'english'; 363} 364 365// We finally load the chosen language file if it differs from English 366if ($CONFIG['lang'] != 'english') { 367 require('lang/' . $CONFIG['lang'] . '.php'); 368} 369set_js_var('lang_close', $lang_common['close']); 370if (defined('THEME_HAS_MENU_ICONS')) { 371 set_js_var('icon_close_path', $THEME_DIR . 'images/icons/close.png'); 372} else { 373 set_js_var('icon_close_path', 'images/icons/close.png'); 374} 375 376// ******************************************************** 377// * Language processing --- end 378// ******************************************************** 379 380// See if the fav cookie is set; else set it 381if ($superCage->cookie->keyExists($CONFIG['cookie_name'] . '_fav')) { 382 $FAVPICS = @unserialize(@base64_decode($superCage->cookie->getRaw($CONFIG['cookie_name'] . '_fav'))); 383 foreach ($FAVPICS as $key => $id ) { 384 $FAVPICS[$key] = (int)$id; //protect against sql injection attacks 385 } 386} else { 387 $FAVPICS = array(); 388} 389 390// If the person is logged in get favs from DB those in the DB have precedence 391if (USER_ID > 0) { 392 $result = cpg_db_query("SELECT user_favpics FROM {$CONFIG['TABLE_FAVPICS']} WHERE user_id = ".USER_ID); 393 394 $row = $result->fetchAssoc(true); 395 if (!empty($row['user_favpics'])) { 396 $FAVPICS = @unserialize(@base64_decode($row['user_favpics'])); 397 } else { 398 $FAVPICS = array(); 399 } 400} 401 402// Include the jquery javascript library. Jquery will be included on all pages. 403js_include(CPG_JQUERY_VERSION); 404js_include(CPG_JQUERY_MIGRATE); 405 406// Include the scripts.js javascript library that contains coppermine-specific 407// JavaScript that is being used on all pages. 408// Do not remove this line unless you really know what you're doing 409js_include('js/scripts.js'); 410 411// Include the JavaScript library that takes care of the help system. 412js_include('js/jquery.greybox.js'); 413 414// Include the elastic plugin for auto-expanding textareas if debug_mode is on 415js_include('js/jquery.elastic.js'); 416 417// If referer is set in URL and it contains 'http' or 'script' texts then set it to 'index.php' script 418/** 419 * Use $CPG_REFERER wherever $_GET['referer'] is used 420 */ 421if ( ($matches = $superCage->get->getMatched('referer', '/((\%3C)|<)[^\n]+((\%3E)|>)|(.*http.*)|(.*script.*)|(^[\W].*)/i')) ) { 422 $CPG_REFERER = 'index.php'; 423} else { 424 /** 425 * Using getRaw() since we are checking the referer in the above if condition. 426 */ 427 $CPG_REFERER = $superCage->get->getRaw('referer'); 428} 429 430/** 431 * CPGPluginAPI::action('page_start',null) 432 * 433 * Executes page_start action on all plugins 434 * 435 * @param null 436 * @return N/A 437 **/ 438 439CPGPluginAPI::action('page_start', null); 440 441// load the main template 442load_template(); 443$CONFIG['template_loaded'] = true; 444 445// Remove expired bans 446$now = date('Y-m-d H:i:s'); 447if ($CONFIG['purge_expired_bans'] == 1) { 448 cpg_db_query("DELETE FROM {$CONFIG['TABLE_BANNED']} WHERE expiry < '$now'"); 449} 450// Check if the user is banned 451$user_id = USER_ID; 452// Compose the query 453$query_string = "SELECT null FROM {$CONFIG['TABLE_BANNED']} WHERE ("; 454if (USER_ID) { 455 $query_string .= "user_id=$user_id OR "; 456} 457if ($raw_ip != $hdr_ip) { 458 $query_string .= "'$raw_ip' LIKE ip_addr OR '$hdr_ip' LIKE ip_addr "; 459} elseif ($raw_ip != '') { 460 $query_string .= "'$raw_ip' LIKE ip_addr "; 461} 462$query_string .= ") AND brute_force=0 LIMIT 1"; 463 464$result = cpg_db_query($query_string); 465unset($query_string); 466if ($result->numRows()) { 467 pageheader($lang_common['error']); 468 msg_box($lang_common['information'], $lang_errors['banned']); 469 pagefooter(); 470 exit; 471} 472$result->free(); 473 474// Retrieve the "private" album set 475if (!GALLERY_ADMIN_MODE && $CONFIG['allow_private_albums']) { 476 get_private_album_set(); 477} 478 479if (!USER_IS_ADMIN && $CONFIG['offline'] && $CPG_PHP_SELF != 'login.php' && $CPG_PHP_SELF != 'update.php') { 480 pageheader($lang_errors['offline_title']); 481 msg_box($lang_errors['offline_title'], $lang_errors['offline_text']); 482 pagefooter(); 483 exit; 484} 485//EOF