PageRenderTime 45ms CodeModel.GetById 9ms RepoModel.GetById 0ms app.codeStats 0ms

/wp-content/plugins/w3-total-cache/lib/W3/Plugin/Cdn.php

https://gitlab.com/juanito.abelo/nlmobile
PHP | 1022 lines | 599 code | 172 blank | 251 comment | 116 complexity | 61ab57fd3537bf92a1f2cf4a3ff6d0fc MD5 | raw file
  1. <?php
  2. /**
  3. * W3 Total Cache CDN Plugin
  4. */
  5. if (!defined('W3TC')) {
  6. die();
  7. }
  8. w3_require_once(W3TC_INC_DIR . '/functions/file.php');
  9. w3_require_once(W3TC_LIB_W3_DIR . '/Plugin.php');
  10. /**
  11. * Class W3_Plugin_Cdn
  12. */
  13. class W3_Plugin_Cdn extends W3_Plugin {
  14. /**
  15. * CDN reject reason
  16. *
  17. * @var string
  18. */
  19. var $cdn_reject_reason = '';
  20. var $replaced_urls;
  21. /**
  22. * Run plugin
  23. */
  24. function run() {
  25. add_filter('cron_schedules', array(
  26. &$this,
  27. 'cron_schedules'
  28. ));
  29. $cdn_engine = $this->_config->get_string('cdn.engine');
  30. if (!w3_is_cdn_mirror($cdn_engine)) {
  31. add_action('delete_attachment', array(
  32. &$this,
  33. 'delete_attachment'
  34. ));
  35. add_filter('update_attached_file', array(
  36. &$this,
  37. 'update_attached_file'
  38. ));
  39. add_filter('wp_update_attachment_metadata', array(
  40. &$this,
  41. 'update_attachment_metadata'
  42. ));
  43. add_action('w3_cdn_cron_queue_process', array(
  44. &$this,
  45. 'cron_queue_process'
  46. ));
  47. add_action('w3_cdn_cron_upload', array(
  48. &$this,
  49. 'cron_upload'
  50. ));
  51. add_action('switch_theme', array(
  52. &$this,
  53. 'switch_theme'
  54. ));
  55. add_filter('update_feedback', array(
  56. &$this,
  57. 'update_feedback'
  58. ));
  59. }
  60. if (is_admin()) {
  61. add_action('w3tc_saving_options-w3tc_cdn', array($this, 'change_canonical_header'),0,0);
  62. add_filter('w3tc_module_is_running-cdn', array($this, 'cdn_is_running'));
  63. }
  64. /**
  65. * Start rewrite engine
  66. */
  67. if ($this->can_cdn()) {
  68. w3tc_add_ob_callback('cdn', array($this,'ob_callback'));
  69. }
  70. if (is_admin() && w3_can_cdn_purge($cdn_engine)) {
  71. add_filter('media_row_actions', array(
  72. &$this,
  73. 'media_row_actions'
  74. ), 0, 2);
  75. }
  76. }
  77. /**
  78. * Instantiates worker with admin functionality on demand
  79. *
  80. * @return W3_Plugin_CdnAdmin
  81. */
  82. function get_admin() {
  83. return w3_instance('W3_Plugin_CdnAdmin');
  84. }
  85. /**
  86. * Instantiates worker with common functionality on demand
  87. *
  88. * @return W3_Plugin_CdnCommon
  89. */
  90. function _get_common() {
  91. return w3_instance('W3_Plugin_CdnCommon');
  92. }
  93. /**
  94. * Cron queue process event
  95. */
  96. function cron_queue_process() {
  97. $queue_limit = $this->_config->get_integer('cdn.queue.limit');
  98. return $this->get_admin()->queue_process($queue_limit);
  99. }
  100. /**
  101. * Cron upload event
  102. */
  103. function cron_upload() {
  104. $files = $this->get_files();
  105. $upload = array();
  106. $results = array();
  107. $w3_plugin_cdncommon = w3_instance('W3_Plugin_CdnCommon');
  108. foreach ($files as $file) {
  109. $local_path = $w3_plugin_cdncommon->docroot_filename_to_absolute_path($file);
  110. $remote_path = $w3_plugin_cdncommon->uri_to_cdn_uri($w3_plugin_cdncommon->docroot_filename_to_uri($file));
  111. $upload[] = $w3_plugin_cdncommon->build_file_descriptor($local_path, $remote_path);
  112. }
  113. $this->_get_common()->upload($upload, true, $results);
  114. }
  115. /**
  116. * Update attachment file
  117. *
  118. * Upload _wp_attached_file
  119. *
  120. * @param string $attached_file
  121. * @return string
  122. */
  123. function update_attached_file($attached_file) {
  124. $files = $this->_get_common()->get_files_for_upload($attached_file);
  125. $files = apply_filters('w3tc_cdn_update_attachment', $files);
  126. $results = array();
  127. $this->_get_common()->upload($files, true, $results);
  128. return $attached_file;
  129. }
  130. /**
  131. * On attachment delete action
  132. *
  133. * Delete _wp_attached_file, _wp_attachment_metadata, _wp_attachment_backup_sizes
  134. *
  135. * @param integer $attachment_id
  136. */
  137. function delete_attachment($attachment_id) {
  138. $files = $this->_get_common()->get_attachment_files($attachment_id);
  139. $files = apply_filters('w3tc_cdn_delete_attachment', $files);
  140. $results = array();
  141. $this->_get_common()->delete($files, true, $results);
  142. }
  143. /**
  144. * Update attachment metadata filter
  145. *
  146. * Upload _wp_attachment_metadata
  147. *
  148. * @param array $metadata
  149. * @return array
  150. */
  151. function update_attachment_metadata($metadata) {
  152. $files = $this->_get_common()->get_metadata_files($metadata);
  153. $files = apply_filters('w3tc_cdn_update_attachment_metadata', $files);
  154. $results = array();
  155. $this->_get_common()->upload($files, true, $results);
  156. return $metadata;
  157. }
  158. /**
  159. * Cron schedules filter
  160. *
  161. * @param array $schedules
  162. * @return array
  163. */
  164. function cron_schedules($schedules) {
  165. $queue_interval = $this->_config->get_integer('cdn.queue.interval');
  166. $autoupload_interval = $this->_config->get_integer('cdn.autoupload.interval');
  167. return array_merge($schedules, array(
  168. 'w3_cdn_cron_queue_process' => array(
  169. 'interval' => $queue_interval,
  170. 'display' => sprintf('[W3TC] CDN queue process (every %d seconds)', $queue_interval)
  171. ),
  172. 'w3_cdn_cron_upload' => array(
  173. 'interval' => $autoupload_interval,
  174. 'display' => sprintf('[W3TC] CDN auto upload (every %d seconds)', $autoupload_interval)
  175. )
  176. ));
  177. }
  178. /**
  179. * Switch theme action
  180. */
  181. function switch_theme() {
  182. $this->_config->set('notes.theme_changed', true);
  183. $this->_config->save();
  184. }
  185. /**
  186. * WP Upgrade action hack
  187. *
  188. * @param string $message
  189. */
  190. function update_feedback($message) {
  191. if ($message == __('Upgrading database')) {
  192. $this->_config->set('notes.wp_upgraded', true);
  193. $this->_config->save();
  194. }
  195. }
  196. /**
  197. * OB Callback
  198. *
  199. * @param string $buffer
  200. * @return string
  201. */
  202. function ob_callback(&$buffer) {
  203. if ($buffer != '' && w3_is_xml($buffer)) {
  204. if ($this->can_cdn2($buffer)) {
  205. $regexps = array();
  206. $site_path = w3_get_site_path();
  207. $domain_url_regexp = w3_get_domain_url_regexp();
  208. $site_domain_url_regexp = false;
  209. if ($domain_url_regexp != w3_get_url_regexp(w3_get_domain(w3_get_site_url())))
  210. $site_domain_url_regexp = w3_get_url_regexp(w3_get_domain(w3_get_site_url()));
  211. if ($this->_config->get_boolean('cdn.uploads.enable')) {
  212. w3_require_once(W3TC_INC_DIR . '/functions/http.php');
  213. $upload_info = w3_upload_info();
  214. if ($upload_info) {
  215. $baseurl = $upload_info['baseurl'];
  216. if (defined('DOMAIN_MAPPING') && DOMAIN_MAPPING) {
  217. $parsed = @parse_url($upload_info['baseurl']);
  218. $baseurl = home_url() . $parsed['path'];
  219. }
  220. $regexps = $this->make_uploads_regexes($domain_url_regexp, $baseurl, $upload_info, $regexps);
  221. if ($site_domain_url_regexp)
  222. $regexps = $this->make_uploads_regexes($site_domain_url_regexp, $baseurl, $upload_info, $regexps);
  223. }
  224. }
  225. if ($this->_config->get_boolean('cdn.includes.enable')) {
  226. $mask = $this->_config->get_string('cdn.includes.files');
  227. if ($mask != '') {
  228. $regexps[] = '~(["\'(])\s*((' . $domain_url_regexp . ')?(' . w3_preg_quote($site_path . WPINC) . '/(' . $this->get_regexp_by_mask($mask) . ')))~';
  229. if ($site_domain_url_regexp)
  230. $regexps[] = '~(["\'(])\s*((' . $site_domain_url_regexp . ')?(' . w3_preg_quote($site_path . WPINC) . '/(' . $this->get_regexp_by_mask($mask) . ')))~';
  231. }
  232. }
  233. if ($this->_config->get_boolean('cdn.theme.enable')) {
  234. $theme_dir = preg_replace('~' . $domain_url_regexp . '~i', '', get_theme_root_uri());
  235. $mask = $this->_config->get_string('cdn.theme.files');
  236. if ($mask != '') {
  237. $regexps[] = '~(["\'(])\s*((' . $domain_url_regexp . ')?(' . w3_preg_quote($theme_dir) . '/(' . $this->get_regexp_by_mask($mask) . ')))~';
  238. if ($site_domain_url_regexp) {
  239. $theme_dir2 = preg_replace('~' . $site_domain_url_regexp. '~i', '', get_theme_root_uri());
  240. $regexps[] = '~(["\'(])\s*((' . $site_domain_url_regexp . ')?(' . w3_preg_quote($theme_dir) . '/(' . $this->get_regexp_by_mask($mask) . ')))~';
  241. $regexps[] = '~(["\'(])\s*((' . $site_domain_url_regexp . ')?(' . w3_preg_quote($theme_dir2) . '/(' . $this->get_regexp_by_mask($mask) . ')))~';
  242. }
  243. }
  244. }
  245. if ($this->_config->get_boolean('cdn.custom.enable')) {
  246. $masks = $this->_config->get_array('cdn.custom.files');
  247. $masks = array_map(array($this, '_replace_folder_placeholders'), $masks);
  248. $masks = array_map('w3_parse_path', $masks);
  249. if (count($masks)) {
  250. $mask_regexps = array();
  251. foreach ($masks as $mask) {
  252. if ($mask != '') {
  253. $mask = w3_normalize_file($mask);
  254. $mask_regexps[] = $this->get_regexp_by_mask($mask);
  255. }
  256. }
  257. $regexps[] = '~(["\'(])\s*((' . $domain_url_regexp . ')?(' . w3_preg_quote($site_path) . '(' . implode('|', $mask_regexps) . ')))~i';
  258. if ($site_domain_url_regexp)
  259. $regexps[] = '~(["\'(])\s*((' . $site_domain_url_regexp . ')?(' . w3_preg_quote($site_path) . '(' . implode('|', $mask_regexps) . ')))~i';
  260. }
  261. }
  262. foreach ($regexps as $regexp) {
  263. $buffer = preg_replace_callback($regexp, array(
  264. &$this,
  265. 'link_replace_callback'
  266. ), $buffer);
  267. }
  268. if ($this->_config->get_boolean('cdn.minify.enable')) {
  269. if ($this->_config->get_boolean('minify.auto')) {
  270. $regexp = '~(["\'(])\s*' .
  271. $this->_minify_url_regexp('/[a-zA-Z0-9-_]+\.(css|js)') .
  272. '~U';
  273. if (w3_is_cdn_mirror($this->_config->get_string('cdn.engine')))
  274. $processor = 'link_replace_callback';
  275. else
  276. $processor = 'minify_auto_pushcdn_link_replace_callback';
  277. } else {
  278. $regexp = '~(["\'(])\s*' .
  279. $this->_minify_url_regexp('/[a-z0-9]+/.+\.include(-(footer|body))?(-nb)?\.[a-f0-9]+\.(css|js)') .
  280. '~U';
  281. $processor = 'link_replace_callback';
  282. }
  283. $buffer = preg_replace_callback($regexp, array(
  284. &$this,
  285. $processor),
  286. $buffer);
  287. }
  288. }
  289. if ($this->_config->get_boolean('cdn.debug')) {
  290. $buffer .= "\r\n\r\n" . $this->get_debug_info();
  291. }
  292. }
  293. return $buffer;
  294. }
  295. /**
  296. * Gets regexp for minified files
  297. *
  298. * @return string
  299. */
  300. function _minify_url_regexp($filename_mask) {
  301. $minify_base_url = w3_filename_to_url(w3_cache_blog_dir('minify'));
  302. $matches = null;
  303. if (!preg_match('~((https?://)?([^/]+))(.+)~i', $minify_base_url, $matches))
  304. return '';
  305. $protocol_domain_regexp = w3_get_url_regexp($matches[1]);
  306. $path_regexp = w3_preg_quote($matches[4]);
  307. $regexp =
  308. '(' .
  309. '(' . $protocol_domain_regexp . ')?' .
  310. '(' . $path_regexp . $filename_mask . ')' .
  311. ')';
  312. return $regexp;
  313. }
  314. /**
  315. * Returns array of files to upload
  316. *
  317. * @return array
  318. */
  319. function get_files() {
  320. $files = array();
  321. if ($this->_config->get_boolean('cdn.includes.enable')) {
  322. $files = array_merge($files, $this->get_files_includes());
  323. }
  324. if ($this->_config->get_boolean('cdn.theme.enable')) {
  325. $files = array_merge($files, $this->get_files_theme());
  326. }
  327. if ($this->_config->get_boolean('cdn.minify.enable')) {
  328. $files = array_merge($files, $this->get_files_minify());
  329. }
  330. if ($this->_config->get_boolean('cdn.custom.enable')) {
  331. $files = array_merge($files, $this->get_files_custom());
  332. }
  333. return $files;
  334. }
  335. /**
  336. * Exports includes to CDN
  337. *
  338. * @return array
  339. */
  340. function get_files_includes() {
  341. $includes_root = w3_path(ABSPATH . WPINC);
  342. $doc_root = w3_get_document_root();
  343. $includes_path = ltrim(str_replace($doc_root, '', $includes_root), '/');
  344. $files = $this->search_files($includes_root, $includes_path, $this->_config->get_string('cdn.includes.files'));
  345. return $files;
  346. }
  347. /**
  348. * Exports theme to CDN
  349. *
  350. * @return array
  351. */
  352. function get_files_theme() {
  353. /**
  354. * If mobile or referrer support enabled
  355. * we should upload whole themes directory
  356. */
  357. if ($this->_config->get_boolean('mobile.enabled') || $this->_config->get_boolean('referrer.enabled')) {
  358. $themes_root = get_theme_root();
  359. } else {
  360. $themes_root = get_stylesheet_directory();
  361. }
  362. $themes_root = w3_path($themes_root);
  363. $site_root = w3_get_document_root();
  364. $themes_path = ltrim(str_replace($site_root, '', $themes_root), '/');
  365. $files = $this->search_files($themes_root, $themes_path, $this->_config->get_string('cdn.theme.files'));
  366. return $files;
  367. }
  368. /**
  369. * Exports min files to CDN
  370. *
  371. * @return array
  372. */
  373. function get_files_minify() {
  374. $files = array();
  375. if ($this->_config->get_boolean('minify.rewrite') && (!$this->_config->get_boolean('minify.auto') || w3_is_cdn_mirror($this->_config->get_string('cdn.engine')))) {
  376. w3_require_once(W3TC_INC_DIR . '/functions/http.php');
  377. $minify = w3_instance('W3_Plugin_Minify');
  378. $document_root = w3_get_document_root();
  379. $minify_root = w3_cache_blog_dir('minify');
  380. $minify_path = ltrim(str_replace($document_root, '', $minify_root), '/');
  381. $urls = $minify->get_urls();
  382. if ($this->_config->get_string('minify.engine') == 'file') {
  383. foreach ($urls as $url) {
  384. w3_http_get($url);
  385. }
  386. $files = $this->search_files($minify_root, $minify_path, '*.css;*.js');
  387. } else {
  388. foreach ($urls as $url) {
  389. $file = w3_normalize_file_minify($url);
  390. $file = w3_translate_file($file);
  391. if (!w3_is_url($file)) {
  392. $file = $document_root . '/' . $file;
  393. $file = ltrim(str_replace($minify_root, '', $file), '/');
  394. $dir = dirname($file);
  395. if ($dir) {
  396. w3_mkdir($dir, 0777, $minify_root);
  397. }
  398. if (w3_download($url, $minify_root . '/' . $file) !== false) {
  399. $files[] = $minify_path . '/' . $file;
  400. }
  401. }
  402. }
  403. }
  404. }
  405. return $files;
  406. }
  407. /**
  408. * Exports custom files to CDN
  409. *
  410. * @return array
  411. */
  412. function get_files_custom() {
  413. $files = array();
  414. $document_root = w3_get_document_root();
  415. $custom_files = $this->_config->get_array('cdn.custom.files');
  416. $custom_files = array_map('w3_parse_path', $custom_files);
  417. $site_root = w3_get_site_root();
  418. $path = w3_get_site_path();
  419. $site_root_dir = str_replace($document_root, '', $site_root);
  420. if (strstr(WP_CONTENT_DIR, w3_get_site_root()) === false) {
  421. $site_root = w3_get_document_root();
  422. $path = '';
  423. }
  424. $content_path = trim(str_replace(WP_CONTENT_DIR, '', $site_root),'/\\');
  425. foreach ($custom_files as $custom_file) {
  426. if ($custom_file != '') {
  427. $custom_file = $this->_replace_folder_placeholders($custom_file);
  428. $custom_file = w3_normalize_file($custom_file);
  429. if (!w3_is_multisite()) {
  430. $dir = trim(dirname($custom_file), '/\\');
  431. $rel_path = trim(dirname($custom_file), '/\\');
  432. } else
  433. $rel_path = $dir = trim(dirname($custom_file), '/\\');
  434. if (strpos($dir, '<currentblog>') != false) {
  435. $rel_path = $dir = str_replace('<currentblog>', 'blogs.dir/' . w3_get_blog_id(), $dir);
  436. }
  437. if ($dir == '.') {
  438. $rel_path = $dir = '';
  439. }
  440. $mask = basename($custom_file);
  441. $files = array_merge($files, $this->search_files($document_root . '/' . $dir, $rel_path, $mask));
  442. }
  443. }
  444. return $files;
  445. }
  446. /**
  447. * Link replace callback
  448. *
  449. * @param array $matches
  450. * @return string
  451. */
  452. function link_replace_callback($matches) {
  453. list($match, $quote, $url, , , , $path) = $matches;
  454. $path = ltrim($path, '/');
  455. $r = $this->_link_replace_callback_checks($match, $quote, $url, $path);
  456. if (is_null($r)) {
  457. $r = $this->_link_replace_callback_ask_cdn($match, $quote, $url, $path);
  458. }
  459. return $r;
  460. }
  461. /**
  462. * Link replace callback for urls from minify module using auto mode and in cdn of push type
  463. *
  464. * @param array $matches
  465. * @return string
  466. */
  467. function minify_auto_pushcdn_link_replace_callback($matches) {
  468. static $dispatcher = null;
  469. list($match, $quote, $url, , , , $path) = $matches;
  470. $path = ltrim($path, '/');
  471. $r = $this->_link_replace_callback_checks($match, $quote, $url, $path);
  472. /**
  473. * Check if we can replace that URL (for auto mode it should be uploaded)
  474. */
  475. if (is_null($dispatcher)) {
  476. $dispatcher = w3_instance('W3_Dispatcher');
  477. }
  478. if (!$dispatcher->is_url_cdn_uploaded($url)) {
  479. /*
  480. * file not yet uploaded (rare case) - push to queue
  481. */
  482. $this->_get_common()->queue_upload_url($url);
  483. return $match;
  484. }
  485. if (is_null($r)) {
  486. $r = $this->_link_replace_callback_ask_cdn($match, $quote, $url, $path);
  487. }
  488. return $r;
  489. }
  490. /**
  491. * Link replace callback, basic checks step
  492. *
  493. * @param $match
  494. * @param $quote
  495. * @param $url
  496. * @param $path
  497. * @return null|string
  498. */
  499. function _link_replace_callback_checks($match, $quote, $url, $path) {
  500. /**
  501. * @var wpdb $wpdb
  502. */
  503. global $wpdb;
  504. static $queue = null, $reject_files = null;
  505. /**
  506. * Check if URL was already replaced
  507. */
  508. if (isset($this->replaced_urls[$url])) {
  509. return $quote . $this->replaced_urls[$url];
  510. }
  511. /**
  512. * Check URL for rejected files
  513. */
  514. if ($reject_files === null) {
  515. $reject_files = $this->_config->get_array('cdn.reject.files');
  516. }
  517. foreach ($reject_files as $reject_file) {
  518. if ($reject_file != '') {
  519. $reject_file = $this->_replace_folder_placeholders($reject_file);
  520. $reject_file = w3_normalize_file($reject_file);
  521. $reject_file_regexp = '~^(' . $this->get_regexp_by_mask($reject_file) . ')~i';
  522. if (preg_match($reject_file_regexp, $path)) {
  523. return $match;
  524. }
  525. }
  526. }
  527. /**
  528. * Don't replace URL for files that are in the CDN queue
  529. */
  530. if ($queue === null) {
  531. if (!w3_is_cdn_mirror($this->_config->get_string('cdn.engine'))) {
  532. $sql = $wpdb->prepare('SELECT remote_path FROM ' . $wpdb->prefix . W3TC_CDN_TABLE_QUEUE . ' WHERE remote_path = %s', $path);
  533. $queue = $wpdb->get_var($sql);
  534. } else {
  535. $queue = false;
  536. }
  537. }
  538. if ($queue) {
  539. return $match;
  540. }
  541. return null;
  542. }
  543. /**
  544. * Link replace callback, url replacement using cdn engine
  545. *
  546. * @param $match
  547. * @param $quote
  548. * @param $url
  549. * @param $path
  550. * @return null|string
  551. */
  552. function _link_replace_callback_ask_cdn($match, $quote, $url, $path) {
  553. /**
  554. * Do replacement
  555. */
  556. $cdn = $this->_get_common()->get_cdn();
  557. $remote_path = $this->_get_common()->uri_to_cdn_uri($path);
  558. $new_url = $cdn->format_url($remote_path);
  559. if ($new_url) {
  560. $new_url = apply_filters('w3tc_cdn_url', $new_url, $url);
  561. $this->replaced_urls[$url] = $new_url;
  562. return $quote . $new_url;
  563. }
  564. return $match;
  565. }
  566. /**
  567. * Search files
  568. *
  569. * @param string $search_dir
  570. * @param string $base_dir
  571. * @param string $mask
  572. * @param boolean $recursive
  573. * @return array
  574. */
  575. function search_files($search_dir, $base_dir, $mask = '*.*', $recursive = true) {
  576. static $stack = array();
  577. $files = array();
  578. $ignore = array(
  579. '.svn',
  580. '.git',
  581. '.DS_Store',
  582. 'CVS',
  583. 'Thumbs.db',
  584. 'desktop.ini'
  585. );
  586. $dir = @opendir($search_dir);
  587. if ($dir) {
  588. while (($entry = @readdir($dir)) !== false) {
  589. if ($entry != '.' && $entry != '..' && !in_array($entry, $ignore)) {
  590. $path = $search_dir . '/' . $entry;
  591. if (@is_dir($path) && $recursive) {
  592. array_push($stack, $entry);
  593. $files = array_merge($files, $this->search_files($path, $base_dir, $mask, $recursive));
  594. array_pop($stack);
  595. } else {
  596. $regexp = '~^(' . $this->get_regexp_by_mask($mask) . ')$~i';
  597. if (preg_match($regexp, $entry)) {
  598. $files[] = ($base_dir != '' ? $base_dir . '/' : '') . (($p = implode('/', $stack)) != '' ? $p . '/' : '') . $entry;
  599. }
  600. }
  601. }
  602. }
  603. @closedir($dir);
  604. }
  605. return $files;
  606. }
  607. /**
  608. * Returns regexp by mask
  609. *
  610. * @param string $mask
  611. * @return string
  612. */
  613. function get_regexp_by_mask($mask) {
  614. $mask = trim($mask);
  615. $mask = w3_preg_quote($mask);
  616. $mask = str_replace(array(
  617. '\*',
  618. '\?',
  619. ';'
  620. ), array(
  621. '@ASTERISK@',
  622. '@QUESTION@',
  623. '|'
  624. ), $mask);
  625. $regexp = str_replace(array(
  626. '@ASTERISK@',
  627. '@QUESTION@'
  628. ), array(
  629. '[^\\?\\*:\\|\'"<>]*',
  630. '[^\\?\\*:\\|\'"<>]'
  631. ), $mask);
  632. return $regexp;
  633. }
  634. /**
  635. * Returns debug info
  636. *
  637. * @return string
  638. */
  639. function get_debug_info() {
  640. $debug_info = "<!-- W3 Total Cache: CDN debug info:\r\n";
  641. $debug_info .= sprintf("%s%s\r\n", str_pad('Engine: ', 20), $this->_config->get_string('cdn.engine'));
  642. if ($this->cdn_reject_reason) {
  643. $debug_info .= sprintf("%s%s\r\n", str_pad('Reject reason: ', 20), $this->cdn_reject_reason);
  644. }
  645. if (count($this->replaced_urls)) {
  646. $debug_info .= "\r\nReplaced URLs:\r\n";
  647. foreach ($this->replaced_urls as $old_url => $new_url) {
  648. $debug_info .= sprintf("%s => %s\r\n", w3_escape_comment($old_url), w3_escape_comment($new_url));
  649. }
  650. }
  651. $debug_info .= '-->';
  652. return $debug_info;
  653. }
  654. /**
  655. * Check if we can do CDN logic
  656. * @return boolean
  657. */
  658. function can_cdn() {
  659. /**
  660. * Skip if admin
  661. */
  662. if (defined('WP_ADMIN')) {
  663. $this->cdn_reject_reason = 'wp-admin';
  664. return false;
  665. }
  666. /**
  667. * Check for WPMU's and WP's 3.0 short init
  668. */
  669. if (defined('SHORTINIT') && SHORTINIT) {
  670. $this->cdn_reject_reason = 'Short init';
  671. return false;
  672. }
  673. /**
  674. * Check User agent
  675. */
  676. if (!$this->check_ua()) {
  677. $this->cdn_reject_reason = 'user agent is rejected';
  678. return false;
  679. }
  680. /**
  681. * Check request URI
  682. */
  683. if (!$this->_check_request_uri()) {
  684. $this->cdn_reject_reason = 'request URI is rejected';
  685. return false;
  686. }
  687. /**
  688. * Do not replace urls if SSL and SSL support is do not replace
  689. */
  690. if (w3_is_https() && $this->_config->get_boolean('cdn.reject.ssl')) {
  691. $this->cdn_reject_reason = 'SSL is rejected';
  692. return false;
  693. }
  694. return true;
  695. }
  696. /**
  697. * Returns true if we can do CDN logic
  698. *
  699. * @param $buffer
  700. * @return string
  701. */
  702. function can_cdn2(&$buffer) {
  703. /**
  704. * Check for database error
  705. */
  706. if (w3_is_database_error($buffer)) {
  707. $this->cdn_reject_reason = 'Database Error occurred';
  708. return false;
  709. }
  710. /**
  711. * Check for DONOTCDN constant
  712. */
  713. if (defined('DONOTCDN') && DONOTCDN) {
  714. $this->cdn_reject_reason = 'DONOTCDN constant is defined';
  715. return false;
  716. }
  717. /**
  718. * Check logged users roles
  719. */
  720. if ($this->_config->get_boolean('cdn.reject.logged_roles') && !$this->_check_logged_in_role_allowed()) {
  721. $this->cdn_reject_reason = 'logged in role is rejected';
  722. return false;
  723. }
  724. return true;
  725. }
  726. /**
  727. * Checks User Agent
  728. *
  729. * @return boolean
  730. */
  731. function check_ua() {
  732. $uas = array_merge($this->_config->get_array('cdn.reject.ua'), array(
  733. W3TC_POWERED_BY
  734. ));
  735. foreach ($uas as $ua) {
  736. if (!empty($ua)) {
  737. if (isset($_SERVER['HTTP_USER_AGENT']) && stristr($_SERVER['HTTP_USER_AGENT'], $ua) !== false)
  738. return false;
  739. }
  740. }
  741. return true;
  742. }
  743. /**
  744. * Checks request URI
  745. *
  746. * @return boolean
  747. */
  748. function _check_request_uri() {
  749. $reject_uri = $this->_config->get_array('cdn.reject.uri');
  750. $reject_uri = array_map('w3_parse_path', $reject_uri);
  751. foreach ($reject_uri as $expr) {
  752. $expr = trim($expr);
  753. if ($expr != '' && preg_match('~' . $expr . '~i', $_SERVER['REQUEST_URI'])) {
  754. return false;
  755. }
  756. }
  757. w3_require_once(W3TC_LIB_W3_DIR . '/Request.php');
  758. if (W3_Request::get_string('wp_customize'))
  759. return false;
  760. return true;
  761. }
  762. /**
  763. * Check if logged in user role is allwed to use CDN
  764. *
  765. * @return boolean
  766. */
  767. private function _check_logged_in_role_allowed() {
  768. global $current_user;
  769. if (!is_user_logged_in())
  770. return true;
  771. $roles = $this->_config->get_array('cdn.reject.roles');
  772. if (empty($roles))
  773. return true;
  774. $role = array_shift( $current_user->roles );
  775. if (in_array($role, $roles)) {
  776. return false;
  777. }
  778. return true;
  779. }
  780. private function _replace_folder_placeholders($file) {
  781. static $content_dir, $plugin_dir, $upload_dir;
  782. if (empty($content_dir)) {
  783. $content_dir = str_replace(w3_get_document_root(), '', WP_CONTENT_DIR);
  784. $content_dir = substr($content_dir, strlen(w3_get_site_path()));
  785. $content_dir = trim($content_dir, '/');
  786. if (defined('WP_PLUGIN_DIR')) {
  787. $plugin_dir = str_replace(w3_get_document_root(), '', WP_PLUGIN_DIR);
  788. $plugin_dir = trim($plugin_dir, '/');
  789. } else {
  790. $plugin_dir = str_replace(w3_get_document_root(), '', WP_CONTENT_DIR . '/plugins');
  791. $plugin_dir = trim($plugin_dir, '/');
  792. }
  793. $upload_dir = wp_upload_dir();
  794. $upload_dir = str_replace(w3_get_document_root(), '', $upload_dir['basedir']);
  795. $upload_dir = trim($upload_dir, '/');
  796. }
  797. $file = str_replace('{wp_content_dir}', $content_dir, $file);
  798. $file = str_replace('{plugins_dir}', $plugin_dir, $file);
  799. $file = str_replace('{uploads_dir}', $upload_dir, $file);
  800. return $file;
  801. }
  802. /**
  803. * media_row_actions filter
  804. *
  805. * @param array $actions
  806. * @param object $post
  807. * @return array
  808. */
  809. function media_row_actions($actions, $post) {
  810. return $this->get_admin()->media_row_actions($actions, $post);
  811. }
  812. /**
  813. * @param $current_state
  814. * @return bool
  815. */
  816. function cdn_is_running($current_state) {
  817. $admin = $this->get_admin();
  818. return $admin->is_running();
  819. }
  820. /**
  821. * Change canonical header
  822. */
  823. function change_canonical_header() {
  824. $admin = $this->get_admin();
  825. $admin->change_canonical_header();
  826. }
  827. /**
  828. * @param $domain_url_regexp
  829. * @param $baseurl
  830. * @param $upload_info
  831. * @param $regexps
  832. * @return array
  833. */
  834. private function make_uploads_regexes($domain_url_regexp, $baseurl, $upload_info, $regexps) {
  835. if (preg_match('~' . $domain_url_regexp . '~i', $baseurl)) {
  836. $regexps[] = '~(["\'(])\s*((' . $domain_url_regexp . ')?(' . w3_preg_quote($upload_info['baseurlpath']) . '([^"\')>]+)))~';
  837. } else {
  838. $parsed = @parse_url($baseurl);
  839. $upload_url_domain_regexp = isset($parsed['host']) ? w3_get_url_regexp($parsed['scheme'] . '://' . $parsed['host']) : $domain_url_regexp;
  840. $baseurlpath = isset($parsed['path']) ? rtrim($parsed['path'], '/') : '';
  841. if ($baseurlpath)
  842. $regexps[] = '~(["\'])\s*((' . $upload_url_domain_regexp . ')?(' . w3_preg_quote($baseurlpath) . '([^"\'>]+)))~';
  843. else
  844. $regexps[] = '~(["\'])\s*((' . $upload_url_domain_regexp . ')(([^"\'>]+)))~';
  845. }
  846. return $regexps;
  847. }
  848. }