/functions.php

  1. <?php 
  2.  
  3. /** 
  4. * EXTENDED DIAGNOSTIC LOGGING - set value below from "0" to "1" to enable dx logging (or vice-versa). 
  5. * Note: If the plugin is already activated, leave this alone and change the setting on the "Advanced" tab. 
  6. * This option is intended only for logging installation and activation problems when the setting is not 
  7. * available. 
  8. *  
  9. * The diagnostic log should be written to a temporary table in your wp database. 
  10. *  
  11. * When this is set to "1", logging will be attempted regardless of the setting. 
  12. */ 
  13. @define( 'GDE_DX_LOGGING', 0 ); 
  14.  
  15. // set up environment 
  16. if ( ! defined( 'ABSPATH' ) ) { exit; } 
  17. @define( 'GDE_PLUGIN_DIR', trailingslashit( plugin_dir_path( __FILE__ ) ) ); 
  18. @define( 'GDE_PLUGIN_URL', trailingslashit( plugin_dir_url( __FILE__ ) ) ); 
  19.  
  20. // external urls (help, beta API, etc.) 
  21. @define( 'GDE_STDOPT_URL', 'http://www.davistribe.org/gde/settings/viewer-options/' ); 
  22. @define( 'GDE_ENHOPT_URL', 'http://www.davistribe.org/gde/settings/enhanced-options/' ); 
  23. @define( 'GDE_PROOPT_URL', 'http://www.davistribe.org/gde/settings/viewer-profiles/' ); 
  24. @define( 'GDE_ADVOPT_URL', 'http://www.davistribe.org/gde/settings/advanced-options/' ); 
  25. @define( 'GDE_FORUM_URL', 'http://wordpress.org/support/plugin/google-document-embedder' ); 
  26. @define( 'GDE_WP_URL', 'http://wordpress.org/extend/plugins/google-document-embedder/' ); 
  27. @define( 'GDE_BETA_API', 'http://dev.davismetro.com/api/1.0/' ); 
  28.  
  29. /** 
  30. * List supported extensions & MIME types 
  31. * 
  32. * @since 2.5.0.1 
  33. * @return array List of all supported extensions and their MIME types 
  34. */ 
  35. function gde_supported_types() { 
  36. global $gdetypes; 
  37.  
  38. if ( is_array( $gdetypes ) ) { 
  39. return $gdetypes; 
  40. } else { 
  41. $no_output = 1; 
  42. include_once( GDE_PLUGIN_DIR . 'libs/lib-exts.php' ); 
  43.  
  44. if ( isset( $types ) ) { 
  45. return $types; 
  46. } else { 
  47. return false; 
  48.  
  49. /** 
  50. * Get profile data 
  51. * 
  52. * @since 2.5.0.1 
  53. * @return array Array of profiles with their data, or a specific profile 
  54. */ 
  55. function gde_get_profiles( $ident = '', $include_id = true, $include_desc = false ) { 
  56. global $wpdb; 
  57. $table = $wpdb->prefix . 'gde_profiles'; 
  58.  
  59. if ( empty( $ident ) ) { 
  60. $where = "WHERE 1 = 1 ORDER BY profile_id ASC"; 
  61. } elseif ( ! is_numeric( $ident ) ) { 
  62. $where = "WHERE profile_name = '$ident'"; 
  63. } else { 
  64. $where = "WHERE profile_id = $ident"; 
  65.  
  66. $profiles = $wpdb->get_results( "SELECT * FROM $table $where", ARRAY_A ); 
  67.  
  68. if ( ! is_array( $profiles ) ) { 
  69. gde_dx_log("Requested profile $ident not found"); 
  70. return false; 
  71. } elseif ( ! empty( $ident ) ) { 
  72. // return specific profile data 
  73. if ( isset( $profiles[0] ) ) { 
  74. $data = unserialize($profiles[0]['profile_data']); 
  75. if ( $include_id ) { 
  76. $data['profile_id'] = $profiles[0]['profile_id']; 
  77. if ( $include_desc ) { 
  78. $data['profile_desc'] = $profiles[0]['profile_desc']; 
  79.  
  80. $profiles = $data; 
  81. } else { 
  82. gde_dx_log("Requested profile $ident doesn't exist"); 
  83. return false; 
  84.  
  85. return $profiles; 
  86.  
  87. /** 
  88. * Test for valid shortcode syntax, other file errors 
  89. * 
  90. * @return string Error message (if any) 
  91. */ 
  92. function gde_validate_file( $file = NULL, $force ) { 
  93.  
  94. // error messages 
  95. $nofile = __('File not specified, check shortcode syntax', 'gde'); 
  96. $badlink = __('Requested URL is invalid', 'gde'); 
  97. $badtype = __('Unsupported File Type', 'gde') . " (%e)"; 
  98. $notfound = __('Error retrieving file - if necessary turn off error checking', 'gde') . " (%e)"; 
  99.  
  100. if ( ! $file ) { 
  101. return $nofile; 
  102.  
  103. $result = gde_valid_url( $file ); 
  104. if ( $result === false ) { 
  105. // validation skipped due to service failure 
  106. return -1; 
  107. } elseif ( $force == "1" || $force == "yes" ) { 
  108. if ( is_array( $result ) ) { 
  109. return $result; 
  110. } else { 
  111. // couldn't get file size due to service failure 
  112. return -1; 
  113. } elseif ( ! $result ) { 
  114. // can't validate 
  115. return -1; 
  116. } else { 
  117. if ( isset( $result['code'] ) && $result['code'] != 200 ) { 
  118. if ( ! gde_valid_link( $file ) ) { 
  119. return $badlink; 
  120. } else { 
  121. $err = $result['code'] . ":" . $result['message']; 
  122. $notfound = str_replace( "%e", $err, $notfound ); 
  123.  
  124. return $notfound; 
  125. } else { 
  126. if ( ! gde_valid_type( $file ) ) { 
  127. $fn = basename( $file ); 
  128. $fnp = gde_split_filename( $fn ); 
  129. $type = $fnp[1]; 
  130. $badtype = str_replace( "%e", $type, $badtype ); 
  131.  
  132. return $badtype; 
  133. } else { 
  134. return $result; 
  135.  
  136. function gde_valid_link( $link ) { 
  137.  
  138. $urlregex = '/^(([\w]+:)?\/\/)(([\d\w]|%[a-fA-f\d]{2, 2})+(:([\d\w]|%[a-fA-f\d]{2, 2})+)?@)?([\d\w][-\d\w]{0, 253}[\d\w]\.)+[\w]{2, 4}(:[\d]+)?(\/([-+_~.\d\w]|%[a-fA-f\d]{2, 2})*)*(\?(&?([-+_~.\d\w]|%[a-fA-f\d]{2, 2})=?)*)?(#([-+_~.\d\w]|%[a-fA-f\d]{2, 2})*)?$/i'; 
  139.  
  140. if ( preg_match( $urlregex, $link ) ) { 
  141. return true; 
  142. } else { 
  143. return false; 
  144.  
  145. function gde_valid_type( $link ) { 
  146. global $gdetypes; 
  147.  
  148. if ( is_array( $gdetypes ) ) { 
  149. $supported_exts = implode( "|", array_keys( $gdetypes ) ); 
  150.  
  151. if ( preg_match( "/\.($supported_exts)$/i", $link ) ) { 
  152. return true; 
  153. } else { 
  154. return false; 
  155.  
  156. function gde_valid_url( $url, $method = "head", $stop = 0 ) { 
  157.  
  158. if ( $method == "head" ) { 
  159. $result = wp_remote_head( $url ); 
  160. } elseif ( $stop == 0 ) { 
  161. $stop++; 
  162. $result = wp_remote_get( $url ); 
  163. } else { 
  164. gde_dx_log("can't get URL to test; skipping"); 
  165. return false; 
  166.  
  167. if ( is_array( $result ) ) { 
  168. $code = $result['response']['code']; 
  169. if ( ! empty( $code ) && ( $code == "301" || $code == "302" ) ) { 
  170. // HEAD requests don't redirect. Probably a file/directory with spaces in it... 
  171. return gde_valid_url( $url, 'get', $stop ); 
  172. } else { 
  173. // capture file size if determined 
  174. if ( isset( $result['headers']['content-length'] ) ) { 
  175. $result['response']['fsize'] = $result['headers']['content-length']; 
  176. } else { 
  177. $result['response']['fsize'] = ''; 
  178. return $result['response']; 
  179. } elseif ( is_wp_error( $result ) ) { 
  180. // unable to get head 
  181. $error = $result->get_error_message(); 
  182. gde_dx_log("bypassing URL check; cant validate URL $url: $error"); 
  183. return false; 
  184. } else { 
  185. gde_dx_log("cant determine URL validity; skipping"); 
  186. return false; 
  187.  
  188. function gde_split_filename( $filename ) { 
  189. $pos = strrpos( $filename, '.' ); 
  190. if ( $pos === false ) { 
  191. return array( $filename, '' ); // no extension (dot is not found in the filename) 
  192. } else { 
  193. $basename = substr( $filename, 0, $pos ); 
  194. $ext = substr( $filename, $pos + 1 ); 
  195. return array( $basename, $ext ); 
  196.  
  197. function gde_format_bytes( $bytes, $precision = 2 ) { 
  198. if ( ! is_numeric( $bytes ) || $bytes < 1 ) { 
  199. return __('Unknown', 'gde'); 
  200. } else { 
  201. $units = array( 'B', 'KB', __('MB', 'gde'), 'GB', 'TB' ); 
  202.  
  203. $bytes = max( $bytes, 0 ); 
  204. $pow = floor( ( $bytes ? log( $bytes ) : 0 ) / log( 1024 ) ); 
  205. $pow = min( $pow, count( $units ) - 1 ); 
  206.  
  207. $bytes /= pow( 1024, $pow ); 
  208.  
  209. if ( $units[$pow] == "KB" ) { 
  210. // less precision for small file sizes 
  211. return round( $bytes ) . "KB"; 
  212. } else { 
  213. return round( $bytes, $precision ) . $units[$pow]; 
  214.  
  215. /** 
  216. * Sanitize dimensions (width, height) 
  217. * 
  218. * @since 2.5.0.1 
  219. * @return string Sanitized dimensions, or false if value is invalid 
  220. * @note Replaces old gde_sanitizeOpts function 
  221. */ 
  222. function gde_sanitize_dims( $dim ) { 
  223. // remove any spacing junk 
  224. $dim = trim( str_replace( " ", "", $dim ) ); 
  225.  
  226. if ( ! strstr( $dim, '%' ) ) { 
  227. $type = "px"; 
  228. $dim = preg_replace( "/[^0-9]*/", '', $dim ); 
  229. } else { 
  230. $type = "%"; 
  231. $dim = preg_replace( "/[^0-9]*/", '', $dim ); 
  232. if ( (int) $dim > 100 ) { 
  233. $dim = "100"; 
  234.  
  235. if ( $dim ) { 
  236. return $dim.$type; 
  237. } else { 
  238. return false; 
  239.  
  240. /** 
  241. * Shorten ("mask") the URL to the embedded file 
  242. * 
  243. * @since 2.5.0.1 
  244. * @return string Short url response from API call, or false on error 
  245. */ 
  246. function gde_get_short_url( $u ) { 
  247. $u = urlencode( $u ); 
  248. $service[] = "http://tinyurl.com/api-create.php?url=" . $u; 
  249. $service[] = "http://is.gd/create.php?format=simple&url=" . $u; 
  250.  
  251. foreach ( $service as $url ) { 
  252. $passed = false; 
  253. $response = wp_remote_get( $url ); 
  254. if ( is_wp_error( $response ) || empty ( $response['body'] ) ) { 
  255. continue; 
  256. } else { 
  257. // check for rate limit exceeded or other error response 
  258. if ( ! gde_valid_link( $response['body'] ) ) { 
  259. continue; 
  260. } else { 
  261. $passed = true; 
  262. break; 
  263.  
  264. if ( $passed ) { 
  265. return $response['body']; 
  266. } else { 
  267. // can't shorten - return original URL 
  268. gde_dx_log("Shorten URL failed: " . urldecode( $u )); 
  269. return urldecode( $u ); 
  270.  
  271. /** 
  272. * Request secure URL to document 
  273. * 
  274. * @since 2.5.0.1 
  275. * @return string Secure URL, or false on error 
  276. */ 
  277. function gde_get_secure_url( $u ) { 
  278. require_once( GDE_PLUGIN_DIR . 'libs/lib-secure.php' ); 
  279.  
  280. if ( ! $url = gde_make_secure_url( $u ) ) { 
  281. return false; 
  282. } else { 
  283. return $url; 
  284.  
  285. /** 
  286. * Check if settings allow a file to be privatized (downloads blocked) 
  287. * 
  288. * @since 2.5.0.2 
  289. * @return bool Whether or not the file can be blocked from download 
  290. */ 
  291. function gde_is_blockable( $profile ) { 
  292. if ( $profile['viewer'] == "standard" || $profile['link_show'] !== "none" ) { 
  293. return false; 
  294. } elseif ( ! strstr( $profile['tb_flags'], "n" ) && $profile['tb_fullscr'] == "default" ) { 
  295. return false; 
  296. } else { 
  297. return true; 
  298.  
  299. /** 
  300. * Google Analytics Integration 
  301. * 
  302. * @since 2.5.0.1 
  303. * @return string GA tracking event tag, or blank if disabled 
  304. */ 
  305. function gde_ga_event( $file ) { 
  306. global $gdeoptions; 
  307.  
  308. if ( $gdeoptions['ga_enable'] == "no" ) { 
  309. return ''; 
  310. } elseif ( $gdeoptions['ga_enable'] == "compat" ) { 
  311. $fnp = gde_split_filename( basename( $file ) ); 
  312. $category = "'Download'"; // intentionally not translated (it wasn't a translated string in < 2.5) 
  313. $action = "'" . strtoupper( $fnp[1] ) . "'"; 
  314. $label = "this.href"; 
  315. } else { 
  316. $category = "'" . addslashes( $gdeoptions['ga_category'] ) . "'"; 
  317. $action = "'" . __('Download', 'gde') . "'"; 
  318. if ( $gdeoptions['ga_label'] == "url" ) { 
  319. $label = "this.href"; 
  320. } else { 
  321. $label = "'" . basename( $file ) . "'"; 
  322.  
  323. $str = "_gaq.push(['_trackEvent', ".$category.", ".$action.", ".$label."]);"; 
  324. return " onClick=\"" . $str . "\""; 
  325.  
  326. /** 
  327. * Get plugin data 
  328. * 
  329. * @since 2.4.0.1 
  330. * @return array Array of plugin data parsed from main plugin file 
  331. */ 
  332. function gde_get_plugin_data() { 
  333. $mainfile = 'gviewer.php'; 
  334. $slug = 'google-document-embedder'; 
  335.  
  336. if ( ! function_exists( 'get_plugin_data' ) ) { 
  337. require_once( ABSPATH . '/wp-admin/includes/plugin.php' ); 
  338. $plugin_data = get_plugin_data( GDE_PLUGIN_DIR . $mainfile ); 
  339.  
  340. // add custom data (lowercase to avoid any future conflicts) 
  341. $plugin_data['slug'] = $slug; 
  342. $plugin_data['mainfile'] = $mainfile; 
  343. $plugin_data['basename'] = $plugin_data['slug'] . "/" . $mainfile; 
  344.  
  345. return $plugin_data; 
  346.  
  347. /** 
  348. * GDE Extended Logging 
  349. * 
  350. * @since 2.5.0.1 
  351. * @return bool Whether or not log write was successful 
  352. */ 
  353. function gde_dx_log( $text ) { 
  354. global $gdeoptions, $wpdb; 
  355.  
  356. if ( GDE_DX_LOGGING > 0 || ( isset( $gdeoptions['error_log'] ) && $gdeoptions['error_log'] == "yes" ) ) { 
  357. // filter to trap any "unexpected output" to log 
  358. add_action( 'activated_plugin', 'gde_save_error' ); 
  359.  
  360. $table = $wpdb->base_prefix . 'gde_dx_log'; 
  361.  
  362. // create/update table if necessary, then write to log 
  363. if ( gde_dx_log_create() ) { 
  364. // write to log 
  365. $blogid = get_current_blog_id(); 
  366. $text = date( "d-m-Y, H:i:s" ) . " - $text"; 
  367.  
  368. if ( ! $wpdb->insert( 
  369. $table,  
  370. array( 
  371. 'blogid' => $blogid,  
  372. 'data' => $text 
  373. ),  
  374. array( 
  375. '%d', '%s' 
  376. ) ) { 
  377. // couldn't write to db 
  378. return false; 
  379. } else { 
  380. return true; 
  381. } else { 
  382. // can't create db table 
  383. return false; 
  384. } else { 
  385. // logging disabled 
  386. return false; 
  387.  
  388. /** 
  389. * Create/update database table to store dx log 
  390. * 
  391. * @since 2.5.2.1 
  392. * @return bool Whether or not table creation/update was successful 
  393. */ 
  394. function gde_dx_log_create() { 
  395. global $wpdb, $gde_db_ver; 
  396.  
  397. $table = $wpdb->base_prefix . 'gde_dx_log'; 
  398. $db_ver_installed = get_site_option( 'gde_db_version', 0 ); 
  399.  
  400. $sql = "CREATE TABLE " . $table . " ( 
  401. id mediumint(9) UNSIGNED NOT NULL AUTO_INCREMENT,  
  402. blogid smallint(5) UNSIGNED NOT NULL,  
  403. data longtext NOT NULL,  
  404. UNIQUE KEY (id) 
  405. ) ENGINE=MyISAM DEFAULT CHARSET=utf8; "; 
  406.  
  407. if ( version_compare( $gde_db_ver, $db_ver_installed, ">" ) ) { 
  408. // upgrade table if needed 
  409. require_once( ABSPATH . 'wp-admin/includes/upgrade.php' ); 
  410. dbDelta( $sql ); 
  411. } elseif ( $wpdb->get_var( "SHOW TABLES LIKE '$table'" ) == $table ) { 
  412. // table's OK 
  413. return true; 
  414. } else { 
  415. // table doesn't exist, try to create 
  416. require_once( ABSPATH . 'wp-admin/includes/upgrade.php' ); 
  417. dbDelta( $sql ); 
  418.  
  419. if ( $wpdb->get_var( "SHOW TABLES LIKE '$table'" ) == $table ) { 
  420. // table's OK 
  421. return true; 
  422. } else { 
  423. // can't create 
  424. return false; 
  425.  
  426. /** 
  427. * Capture activation errors ("unexpected output") to dx log 
  428. * 
  429. * @since 2.5.0.1 
  430. * @return void 
  431. * @note Writes any activation errors to log, when enabled 
  432. */ 
  433. function gde_save_error() { 
  434. $buffer = ob_get_contents(); 
  435. if ( ! empty( $buffer ) ) { 
  436. gde_dx_log('Activation Msg: '. $buffer ); 
  437.  
  438. function gde_show_error( $status ) { 
  439. global $gdeoptions; 
  440.  
  441. $error = "GDE " . __('Error', 'gde') . ": " . $status; 
  442. if ( $gdeoptions['error_display'] == "no" ) { 
  443. $code = "\n<!-- $error -->\n"; 
  444. } else { 
  445. $code = "\n".'<div class="gde-error">' . $error . "</div>\n"; 
  446.  
  447. return $code; 
  448.  
  449. /** 
  450. * Check health of database tables 
  451. * 
  452. * @since 2.5.0.3 
  453. * @return mixed 
  454. * @note Verbose text used in debug information 
  455. */ 
  456. function gde_debug_tables( $table = array('gde_profiles', 'gde_secure'), $verbose = false ) { 
  457. global $wpdb; 
  458.  
  459. if ( is_array( $table ) ) { 
  460. $ok = true; 
  461. foreach ( $table as $t ) { 
  462. $t = $wpdb->prefix . $t; 
  463. if ( $wpdb->get_var( "SHOW TABLES LIKE '$t'" ) == $t ) { 
  464. // table good 
  465. } else { 
  466. $ok = false; 
  467. gde_dx_log($t . " table missing"); 
  468. break; 
  469. } else { 
  470. $ok = true; 
  471. $table = $wpdb->prefix . $table; 
  472. if ( $wpdb->get_var( "SHOW TABLES LIKE '$table'" ) == $table ) { 
  473. $s = "OK "; 
  474. $c = $wpdb->get_var( "SELECT COUNT(*) FROM $table WHERE 1=1" ); 
  475. $s = $s . "($c items)"; 
  476. } else { 
  477. $s = "NOT OK ($table missing)"; 
  478. $ok = false; 
  479.  
  480. if ( ! $verbose ) { 
  481. return $ok; 
  482. } else { 
  483. return $s; 
  484.  
  485. ?> 
.