PageRenderTime 47ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/htdocs/wp-content/plugins/nextgen-gallery/nggallery.php

https://github.com/Fishgate/privatecollectionswp
PHP | 648 lines | 458 code | 78 blank | 112 comment | 55 complexity | d31278debe50d78f834a091902869b2d MD5 | raw file
  1. <?php
  2. if(preg_match('#' . basename(__FILE__) . '#', $_SERVER['PHP_SELF'])) { die('You are not allowed to call this page directly.'); }
  3. /**
  4. * Plugin Name: NextGEN Gallery by Photocrati
  5. * Description: The most popular gallery plugin for WordPress and one of the most popular plugins of all time with over 9 million downloads.
  6. * Version: 2.0.66.27
  7. * Author: Photocrati Media
  8. * Plugin URI: http://www.nextgen-gallery.com
  9. * Author URI: http://www.photocrati.com
  10. * License: GPLv2
  11. */
  12. if (!class_exists('E_Clean_Exit')) { class E_Clean_Exit extends RuntimeException {} }
  13. if (!class_exists('E_NggErrorException')) { class E_NggErrorException extends RuntimeException {} }
  14. // This is a temporary function to replace the use of WP's esc_url which strips spaces away from URLs
  15. // TODO: Move this to a better place
  16. if (!function_exists('nextgen_esc_url')) {
  17. function nextgen_esc_url( $url, $protocols = null, $_context = 'display' ) {
  18. $original_url = $url;
  19. if ( '' == $url )
  20. return $url;
  21. $url = preg_replace('|[^a-z0-9 \\-~+_.?#=!&;,/:%@$\|*\'()\\x80-\\xff]|i', '', $url);
  22. $strip = array('%0d', '%0a', '%0D', '%0A');
  23. $url = _deep_replace($strip, $url);
  24. $url = str_replace(';//', '://', $url);
  25. /* If the URL doesn't appear to contain a scheme, we
  26. * presume it needs http:// appended (unless a relative
  27. * link starting with /, # or ? or a php file).
  28. */
  29. if ( strpos($url, ':') === false && ! in_array( $url[0], array( '/', '#', '?' ) ) &&
  30. ! preg_match('/^[a-z0-9-]+?\.php/i', $url) )
  31. $url = 'http://' . $url;
  32. // Replace ampersands and single quotes only when displaying.
  33. if ( 'display' == $_context ) {
  34. $url = wp_kses_normalize_entities( $url );
  35. $url = str_replace( '&amp;', '&#038;', $url );
  36. $url = str_replace( "'", '&#039;', $url );
  37. $url = str_replace( '%', '%25', $url );
  38. $url = str_replace( ' ', '%20', $url );
  39. }
  40. if ( '/' === $url[0] ) {
  41. $good_protocol_url = $url;
  42. } else {
  43. if ( ! is_array( $protocols ) )
  44. $protocols = wp_allowed_protocols();
  45. $good_protocol_url = wp_kses_bad_protocol( $url, $protocols );
  46. if ( strtolower( $good_protocol_url ) != strtolower( $url ) )
  47. return '';
  48. }
  49. return apply_filters('clean_url', $good_protocol_url, $original_url, $_context);
  50. }
  51. }
  52. /**
  53. * NextGEN Gallery is built on top of the Photocrati Pope Framework:
  54. * https://bitbucket.org/photocrati/pope-framework
  55. *
  56. * Pope constructs applications by assembling modules.
  57. *
  58. * The Bootstrapper. This class performs the following:
  59. * 1) Loads the Pope Framework
  60. * 2) Adds a path to the C_Component_Registry instance to search for products
  61. * 3) Loads all found Products. A Product is a collection of modules with some
  62. * additional meta data. A Product is responsible for loading any modules it
  63. * requires.
  64. * 4) Once all Products (and their associated modules) have been loaded (or in
  65. * otherwords, "included"), the modules are initialized.
  66. */
  67. class C_NextGEN_Bootstrap
  68. {
  69. var $_registry = NULL;
  70. var $_settings_option_name = 'ngg_options';
  71. var $_pope_loaded = FALSE;
  72. static $debug = FALSE;
  73. static function shutdown($exception=NULL)
  74. {
  75. if (is_null($exception)) {
  76. throw new E_Clean_Exit;
  77. }
  78. elseif (!($exception instanceof E_Clean_Exit)) {
  79. ob_end_clean();
  80. self::print_exception($exception);
  81. }
  82. }
  83. static function print_exception($exception)
  84. {
  85. $klass = get_class($exception);
  86. echo "<h1>{$klass} thrown</h1>";
  87. echo "<p>{$exception->getMessage()}</p>";
  88. if (self::$debug OR (defined('NGG_DEBUG') AND NGG_DEBUG == TRUE)) {
  89. echo "<h3>Where:</h3>";
  90. echo "<p>On line <strong>{$exception->getLine()}</strong> of <strong>{$exception->getFile()}</strong></p>";
  91. echo "<h3>Trace:</h3>";
  92. echo "<pre>{$exception->getTraceAsString()}</pre>";
  93. if (method_exists($exception, 'getPrevious')) {
  94. if (($previous = $exception->getPrevious())) {
  95. self::print_exception($previous);
  96. }
  97. }
  98. }
  99. }
  100. static function get_backtrace($objects=FALSE, $remove_dynamic_calls=TRUE)
  101. {
  102. $trace = debug_backtrace($objects);
  103. if ($remove_dynamic_calls) {
  104. $skip_methods = array(
  105. '_exec_cached_method',
  106. '__call',
  107. 'get_method_property',
  108. 'set_method_property',
  109. 'call_method'
  110. );
  111. foreach ($trace as $key => &$value) {
  112. if (isset($value['class']) && isset($value['function'])) {
  113. if ($value['class'] == 'ReflectionMethod' && $value['function'] == 'invokeArgs')
  114. unset($trace[$key]);
  115. else if ($value['class'] == 'ExtensibleObject' && in_array($value['function'], $skip_methods))
  116. unset($trace[$key]);
  117. }
  118. }
  119. }
  120. return $trace;
  121. }
  122. function __construct()
  123. {
  124. // Boostrap
  125. set_exception_handler(__CLASS__.'::shutdown');
  126. $this->_define_constants();
  127. $this->_load_non_pope();
  128. $this->_register_hooks();
  129. $this->_load_pope();
  130. }
  131. function _load_non_pope()
  132. {
  133. // Load caching component
  134. include_once('non_pope/class.photocrati_cache.php');
  135. C_Photocrati_Cache::get_instance();
  136. C_Photocrati_Cache::get_instance('displayed_galleries');
  137. C_Photocrati_Cache::get_instance('displayed_gallery_rendering');
  138. C_Photocrati_Cache::$enabled = PHOTOCRATI_CACHE;
  139. if (isset($_REQUEST['ngg_flush'])) {
  140. C_Photocrati_Cache::flush('all');
  141. die("Flushed all caches");
  142. }
  143. elseif (isset($_REQUEST['ngg_force_update'])) {
  144. C_Photocrati_Cache::$do_not_lookup = TRUE;
  145. C_Photocrati_Cache::$force_update = TRUE;
  146. $_SERVER['QUERY_STRING'] = str_replace('ngg_force_update=1', '', $_SERVER['QUERY_STRING']);
  147. }
  148. elseif (isset($_REQUEST['ngg_flush_expired'])) {
  149. C_Photocrati_Cache::flush('all', TRUE);
  150. die("Flushed all expired items from the cache");
  151. }
  152. // Load Settings Manager
  153. include_once('non_pope/class.photocrati_settings_manager.php');
  154. include_once('non_pope/class.nextgen_settings.php');
  155. C_Photocrati_Global_Settings_Manager::$option_name = $this->_settings_option_name;
  156. C_Photocrati_Settings_Manager::$option_name = $this->_settings_option_name;
  157. // Load the installer
  158. include_once('non_pope/class.photocrati_installer.php');
  159. // Load the resource manager
  160. include_once('non_pope/class.photocrati_resource_manager.php');
  161. C_Photocrati_Resource_Manager::init();
  162. // Load the style manager
  163. include_once('non_pope/class.nextgen_style_manager.php');
  164. // Load the shortcode manager
  165. include_once('non_pope/class.nextgen_shortcode_manager.php');
  166. }
  167. /**
  168. * Loads the Pope Framework
  169. */
  170. function _load_pope()
  171. {
  172. // No need to initialize pope again
  173. if ($this->_pope_loaded) return;
  174. // Pope requires a a higher limit
  175. $tmp = ini_get('xdebug.max_nesting_level');
  176. if ($tmp && (int)$tmp <= 300) @ini_set('xdebug.max_nesting_level', 300);
  177. // Include pope framework
  178. require_once(implode(
  179. DIRECTORY_SEPARATOR, array(NGG_PLUGIN_DIR, 'pope','lib','autoload.php')
  180. ));
  181. // Get the component registry
  182. $this->_registry = C_Component_Registry::get_instance();
  183. // Add the default Pope factory utility, C_Component_Factory
  184. $this->_registry->add_utility('I_Component_Factory', 'C_Component_Factory');
  185. // Load embedded products. Each product is expected to load any
  186. // modules required
  187. $this->_registry->add_module_path(NGG_PRODUCT_DIR, true, false);
  188. $this->_registry->load_all_products();
  189. // Give third-party plugins that opportunity to include their own products
  190. // and modules
  191. do_action('load_nextgen_gallery_modules', $this->_registry);
  192. // Initializes all loaded modules
  193. $this->_registry->initialize_all_modules();
  194. $this->_pope_loaded = TRUE;
  195. }
  196. /**
  197. * Registers hooks for the WordPress framework necessary for instantiating
  198. * the plugin
  199. */
  200. function _register_hooks()
  201. {
  202. // Register the activation routines
  203. add_action('activate_'.NGG_PLUGIN_BASENAME, array(get_class(), 'activate'));
  204. // Register the deactivation routines
  205. add_action('deactivate_'.NGG_PLUGIN_BASENAME, array(get_class(), 'deactivate'));
  206. // Register our test suite
  207. add_filter('simpletest_suites', array(&$this, 'add_testsuite'));
  208. // Ensure that settings manager is saved as an array
  209. add_filter('pre_update_option_'.$this->_settings_option_name, array(&$this, 'persist_settings'));
  210. add_filter('pre_update_site_option_'.$this->_settings_option_name, array(&$this, 'persist_settings'));
  211. // This plugin uses jQuery extensively
  212. if (NGG_FIX_JQUERY) {
  213. add_action('wp_enqueue_scripts', array(&$this, 'fix_jquery'));
  214. add_action('wp_print_scripts', array(&$this, 'fix_jquery'));
  215. }
  216. // If the selected stylesheet is using an unsafe path, then notify the user
  217. add_action('all_admin_notices', array(&$this, 'display_stylesheet_notice'));
  218. // Delete displayed gallery transients periodically
  219. add_filter('cron_schedules', array(&$this, 'add_ngg_schedule'));
  220. add_action('ngg_delete_expired_transients', array(&$this, 'delete_expired_transients'));
  221. add_action('wp', array(&$this, 'schedule_cron_jobs'));
  222. // Update modules
  223. add_action('init', array(&$this, 'update'), PHP_INT_MAX-1);
  224. // Start the plugin!
  225. add_action('init', array(&$this, 'route'), 11);
  226. }
  227. function schedule_cron_jobs()
  228. {
  229. if (!wp_next_scheduled('ngg_delete_expired_transients')) {
  230. wp_schedule_event(time(), 'ngg_custom', 'ngg_delete_expired_transients');
  231. }
  232. }
  233. /**
  234. * Defines a new cron schedule
  235. * @param $schedules
  236. * @return mixed
  237. */
  238. function add_ngg_schedule($schedules)
  239. {
  240. $schedules['ngg_custom'] = array(
  241. 'interval' => NGG_CRON_SCHEDULE,
  242. 'display' => sprintf(__('Every %d seconds', 'nggallery'), NGG_CRON_SCHEDULE)
  243. );
  244. return $schedules;
  245. }
  246. /**
  247. * Flush all expires transients created by the plugin
  248. */
  249. function delete_expired_transients()
  250. {
  251. C_Photocrati_Cache::flush('all', TRUE);
  252. }
  253. /**
  254. * Ensure that C_Photocrati_Settings_Manager gets persisted as an array
  255. * @param $settings
  256. * @return array
  257. */
  258. function persist_settings($settings)
  259. {
  260. if (is_object($settings) && $settings instanceof C_Photocrati_Settings_Manager_Base) {
  261. $settings = $settings->to_array();
  262. }
  263. return $settings;
  264. }
  265. /**
  266. * Ensures that the version of JQuery used is expected for NextGEN Gallery
  267. */
  268. function fix_jquery()
  269. {
  270. global $wp_scripts;
  271. // Determine which version of jQuery to include
  272. $src = '/wp-includes/js/jquery/jquery.js';
  273. // Ensure that jQuery is always set to the default
  274. if (isset($wp_scripts->registered['jquery'])) {
  275. $jquery = $wp_scripts->registered['jquery'];
  276. // There's an exception to the rule. We'll allow the same
  277. // version of jQuery as included with WP to be fetched from
  278. // Google AJAX libraries, as we have a systematic means of verifying
  279. // that won't cause any troubles
  280. $version = preg_quote($jquery->ver, '#');
  281. if (!preg_match("#ajax\\.googleapis\\.com/ajax/libs/jquery/{$version}/jquery\\.min\\.js#", $jquery->src)) {
  282. $jquery->src = FALSE;
  283. if (array_search('jquery-core', $jquery->deps) === FALSE) {
  284. $jquery->deps[] = 'jquery-core';
  285. }
  286. if (array_search('jquery-migrate', $jquery->deps) === FALSE) {
  287. $jquery->deps[] = 'jquery-migrate';
  288. }
  289. }
  290. }
  291. // Ensure that jquery-core is used, as WP intended
  292. if (isset($wp_scripts->registered['jquery-core'])) {
  293. $wp_scripts->registered['jquery-core']->src = $src;
  294. }
  295. wp_enqueue_script('jquery');
  296. }
  297. /**
  298. * Displays a notice to the user that the current stylesheet location is unsafe
  299. */
  300. function display_stylesheet_notice()
  301. {
  302. if (C_NextGen_Style_Manager::get_instance()->is_directory_unsafe()) {
  303. $styles = C_NextGen_Style_Manager::get_instance();
  304. $filename = $styles->get_selected_stylesheet();
  305. $abspath = $styles->find_selected_stylesheet_abspath();
  306. $newpath = $styles->new_dir;
  307. echo "<div class='updated error'>
  308. <h3>WARNING: NextGEN Gallery Stylesheet NOT Upgrade-safe</h3>
  309. <p>
  310. <strong>{$filename}</strong> is currently stored in <strong>{$abspath}</strong>, which isn't upgrade-safe. Please move the stylesheet to
  311. <strong>{$newpath}</strong> to ensure that your customizations persist after updates.
  312. </p></div>";
  313. }
  314. }
  315. /**
  316. * Updates all modules
  317. */
  318. function update()
  319. {
  320. if ((!(defined('DOING_AJAX') && DOING_AJAX)) && !isset($_REQUEST['doing_wp_cron'])) {
  321. $this->_load_pope();
  322. // Try updating all modules
  323. C_Photocrati_Installer::update();
  324. }
  325. }
  326. /**
  327. * Routes access points using the Pope Router
  328. * @return boolean
  329. */
  330. function route()
  331. {
  332. $this->_load_pope();
  333. $router = C_Router::get_instance();
  334. do_action_ref_array('ngg_routes', array(&$router));
  335. if (!$router->serve_request() && $router->has_parameter_segments()) {
  336. return $router->passthru();
  337. }
  338. }
  339. /**
  340. * Run the installer
  341. */
  342. static function activate($network=FALSE)
  343. {
  344. C_Photocrati_Installer::update();
  345. }
  346. /**
  347. * Run the uninstaller
  348. */
  349. static function deactivate()
  350. {
  351. C_Photocrati_Installer::uninstall(NGG_PLUGIN_BASENAME);
  352. }
  353. /**
  354. * Defines necessary plugins for the plugin to load correctly
  355. */
  356. function _define_constants()
  357. {
  358. // NextGEN by Photocrati Constants
  359. define('NGG_PLUGIN', basename($this->directory_path()));
  360. define('NGG_PLUGIN_BASENAME', plugin_basename(__FILE__));
  361. define('NGG_PLUGIN_DIR', $this->directory_path());
  362. define('NGG_PLUGIN_URL', $this->path_uri());
  363. define('NGG_TESTS_DIR', implode(DIRECTORY_SEPARATOR, array(rtrim(NGG_PLUGIN_DIR, "/\\"), 'tests')));
  364. define('NGG_PRODUCT_DIR', implode(DIRECTORY_SEPARATOR, array(rtrim(NGG_PLUGIN_DIR, "/\\"), 'products')));
  365. define('NGG_MODULE_DIR', implode(DIRECTORY_SEPARATOR, array(rtrim(NGG_PRODUCT_DIR, "/\\"), 'photocrati_nextgen', 'modules')));
  366. define('NGG_PRODUCT_URL', path_join(str_replace("\\", '/', NGG_PLUGIN_URL), 'products'));
  367. define('NGG_MODULE_URL', path_join(str_replace("\\", '/', NGG_PRODUCT_URL), 'photocrati_nextgen/modules'));
  368. define('NGG_PLUGIN_STARTED_AT', microtime());
  369. define('NGG_PLUGIN_VERSION', '2.0.66.27');
  370. if (!defined('NGG_HIDE_STRICT_ERRORS')) {
  371. define('NGG_HIDE_STRICT_ERRORS', TRUE);
  372. }
  373. // Should we display E_STRICT errors?
  374. if (NGG_HIDE_STRICT_ERRORS) {
  375. $level = error_reporting();
  376. if ($level != 0) error_reporting($level & ~E_STRICT);
  377. }
  378. // Should we display NGG debugging information?
  379. if (!defined('NGG_DEBUG')) {
  380. define('NGG_DEBUG', FALSE);
  381. }
  382. self::$debug = NGG_DEBUG;
  383. // User definable constants
  384. if (!defined('NGG_IMPORT_ROOT')) {
  385. $path = WP_CONTENT_DIR;
  386. define('NGG_IMPORT_ROOT', $path);
  387. }
  388. // Should the Photocrati cache be enabled
  389. if (!defined('PHOTOCRATI_CACHE')) {
  390. define('PHOTOCRATI_CACHE', TRUE);
  391. }
  392. if (!defined('PHOTOCRATI_CACHE_TTL')) {
  393. define('PHOTOCRATI_CACHE_TTL', 3600);
  394. }
  395. // Cron job
  396. if (!defined('NGG_CRON_SCHEDULE')) {
  397. define('NGG_CRON_SCHEDULE', 1800);
  398. }
  399. // Don't enforce interfaces
  400. if (!defined('EXTENSIBLE_OBJECT_ENFORCE_INTERFACES')) {
  401. define('EXTENSIBLE_OBJECT_ENFORCE_INTERFACES', FALSE);
  402. }
  403. // Fix jquery
  404. if (!defined('NGG_FIX_JQUERY')) {
  405. define('NGG_FIX_JQUERY', TRUE);
  406. }
  407. }
  408. /**
  409. * Defines the NextGEN Test Suite
  410. * @param array $suites
  411. * @return array
  412. */
  413. function add_testsuite($suites=array())
  414. {
  415. $tests_dir = NGG_TESTS_DIR;
  416. if (file_exists($tests_dir)) {
  417. // Include mock objects
  418. // TODO: These mock objects should be moved to the appropriate
  419. // test folder
  420. require_once(path_join($tests_dir, 'mocks.php'));
  421. // Define the NextGEN Test Suite
  422. $suites['nextgen'] = array(
  423. // path_join($tests_dir, 'mvc'),
  424. path_join($tests_dir, 'datamapper'),
  425. path_join($tests_dir, 'nextgen_data'),
  426. path_join($tests_dir, 'gallery_display')
  427. );
  428. }
  429. return $suites;
  430. }
  431. /**
  432. * Returns the path to a file within the plugin root folder
  433. * @param type $file_name
  434. * @return type
  435. */
  436. function file_path($file_name=NULL)
  437. {
  438. $path = dirname(__FILE__);
  439. if ($file_name != null)
  440. {
  441. $path .= '/' . $file_name;
  442. }
  443. return str_replace(array('/', '\\'), DIRECTORY_SEPARATOR, $path);
  444. }
  445. /**
  446. * Gets the directory path used by the plugin
  447. * @return string
  448. */
  449. function directory_path($dir=NULL)
  450. {
  451. return $this->file_path($dir);
  452. }
  453. /**
  454. * Determines the location of the plugin - within a theme or plugin
  455. * @return string
  456. */
  457. function get_plugin_location()
  458. {
  459. $path = dirname(__FILE__);
  460. $gallery_dir = strtolower($path);
  461. $gallery_dir = str_replace(array('/', '\\'), DIRECTORY_SEPARATOR, $gallery_dir);
  462. $theme_dir = strtolower(get_stylesheet_directory());
  463. $theme_dir = str_replace(array('/', '\\'), DIRECTORY_SEPARATOR, $theme_dir);
  464. $plugin_dir = strtolower(WP_PLUGIN_DIR);
  465. $plugin_dir = str_replace(array('/', '\\'), DIRECTORY_SEPARATOR, $plugin_dir);
  466. $common_dir_theme = substr($gallery_dir, 0, strlen($theme_dir));
  467. $common_dir_plugin = substr($gallery_dir, 0, strlen($plugin_dir));
  468. if ($common_dir_theme == $theme_dir)
  469. {
  470. return 'theme';
  471. }
  472. if ($common_dir_plugin == $plugin_dir)
  473. {
  474. return 'plugin';
  475. }
  476. $parent_dir = dirname($path);
  477. if (file_exists($parent_dir . DIRECTORY_SEPARATOR . 'style.css'))
  478. {
  479. return 'theme';
  480. }
  481. return 'plugin';
  482. }
  483. /**
  484. * Gets the URI for a particular path
  485. * @param string $path
  486. * @param boolean $url_encode
  487. * @return string
  488. */
  489. function path_uri($path = null, $url_encode = false)
  490. {
  491. $location = $this->get_plugin_location();
  492. $uri = null;
  493. $path = str_replace(array('/', '\\'), '/', $path);
  494. if ($url_encode)
  495. {
  496. $path_list = explode('/', $path);
  497. foreach ($path_list as $index => $path_item)
  498. {
  499. $path_list[$index] = urlencode($path_item);
  500. }
  501. $path = implode('/', $path_list);
  502. }
  503. if ($location == 'theme')
  504. {
  505. $theme_uri = get_stylesheet_directory_uri();
  506. $uri = $theme_uri . 'nextgen-gallery';
  507. if ($path != null)
  508. {
  509. $uri .= '/' . $path;
  510. }
  511. }
  512. else
  513. {
  514. // XXX Note, paths could not match but STILL being contained in the theme (i.e. WordPress returns the wrong path for the theme directory, either with wrong formatting or wrong encoding)
  515. $base = basename(dirname(__FILE__));
  516. if ($base != 'nextgen-gallery')
  517. {
  518. // XXX this is needed when using symlinks, if the user renames the plugin folder everything will break though
  519. $base = 'nextgen-gallery';
  520. }
  521. if ($path != null)
  522. {
  523. $base .= '/' . $path;
  524. }
  525. $uri = plugins_url($base);
  526. }
  527. return $uri;
  528. }
  529. /**
  530. * Returns the URI for a particular file
  531. * @param string $file_name
  532. * @return string
  533. */
  534. function file_uri($file_name = NULL)
  535. {
  536. return $this->path($file_name);
  537. }
  538. }
  539. new C_NextGEN_Bootstrap();