/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. $unktype = __('Unable to determine file type from URL', 'gde'); 
  99. $notfound = __('Error retrieving file - if necessary turn off error checking', 'gde') . " (%e)"; 
  100.  
  101. if ( ! $file ) { 
  102. return $nofile; 
  103.  
  104. $result = gde_valid_url( $file ); 
  105. if ( $result === false ) { 
  106. // validation skipped due to service failure 
  107. return -1; 
  108. } elseif ( $force == "1" || $force == "yes" ) { 
  109. if ( is_array( $result ) ) { 
  110. return $result; 
  111. } else { 
  112. // couldn't get file size due to service failure 
  113. return -1; 
  114. } elseif ( ! $result ) { 
  115. // can't validate 
  116. return -1; 
  117. } else { 
  118. if ( isset( $result['code'] ) && $result['code'] != 200 ) { 
  119. if ( ! gde_valid_link( $file ) ) { 
  120. return $badlink; 
  121. } else { 
  122. $err = $result['code'] . ":" . $result['message']; 
  123. $notfound = str_replace( "%e", $err, $notfound ); 
  124.  
  125. return $notfound; 
  126. } else { 
  127. if ( ! gde_valid_type( $file ) ) { 
  128. $fn = basename( $file ); 
  129. $fnp = gde_split_filename( $fn ); 
  130. $type = $fnp[1]; 
  131.  
  132. if ( $type == '' ) { 
  133. return $unktype; 
  134. $badtype = str_replace( "%e", $type, $badtype ); 
  135.  
  136. return $badtype; 
  137. } else { 
  138. return $result; 
  139.  
  140. function gde_valid_link( $link ) { 
  141.  
  142. $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'; 
  143.  
  144. if ( preg_match( $urlregex, $link ) ) { 
  145. return true; 
  146. } else { 
  147. return false; 
  148.  
  149. function gde_valid_type( $link ) { 
  150. global $gdetypes; 
  151.  
  152. if ( is_array( $gdetypes ) ) { 
  153. $supported_exts = implode( "|", array_keys( $gdetypes ) ); 
  154.  
  155. if ( preg_match( "/\.($supported_exts)$/i", $link ) ) { 
  156. return true; 
  157. } else { 
  158. return false; 
  159.  
  160. function gde_valid_url( $url, $method = "head", $stop = 0 ) { 
  161.  
  162. if ( $method == "head" ) { 
  163. $result = wp_remote_head( $url ); 
  164. } elseif ( $stop == 0 ) { 
  165. $stop++; 
  166. $result = wp_remote_get( $url ); 
  167. } else { 
  168. gde_dx_log("can't get URL to test; skipping"); 
  169. return false; 
  170.  
  171. if ( is_array( $result ) ) { 
  172. $code = $result['response']['code']; 
  173. if ( ! empty( $code ) && ( $code == "301" || $code == "302" ) ) { 
  174. // HEAD requests don't redirect. Probably a file/directory with spaces in it... 
  175. return gde_valid_url( $url, 'get', $stop ); 
  176. } else { 
  177. // capture file size if determined 
  178. if ( isset( $result['headers']['content-length'] ) ) { 
  179. $result['response']['fsize'] = $result['headers']['content-length']; 
  180. } else { 
  181. $result['response']['fsize'] = ''; 
  182. return $result['response']; 
  183. } elseif ( is_wp_error( $result ) ) { 
  184. // unable to get head 
  185. $error = $result->get_error_message(); 
  186. gde_dx_log("bypassing URL check; cant validate URL $url: $error"); 
  187. return false; 
  188. } else { 
  189. gde_dx_log("cant determine URL validity; skipping"); 
  190. return false; 
  191.  
  192. function gde_split_filename( $filename ) { 
  193. $pos = strrpos( $filename, '.' ); 
  194. if ( $pos === false ) { 
  195. return array( $filename, '' ); // no extension (dot is not found in the filename) 
  196. } else { 
  197. $basename = substr( $filename, 0, $pos ); 
  198. $ext = substr( $filename, $pos + 1 ); 
  199. return array( $basename, $ext ); 
  200.  
  201. function gde_format_bytes( $bytes, $precision = 2 ) { 
  202. if ( ! is_numeric( $bytes ) || $bytes < 1 ) { 
  203. return __('Unknown', 'gde'); 
  204. } else { 
  205. $units = array( 'B', 'KB', __('MB', 'gde'), 'GB', 'TB' ); 
  206.  
  207. $bytes = max( $bytes, 0 ); 
  208. $pow = floor( ( $bytes ? log( $bytes ) : 0 ) / log( 1024 ) ); 
  209. $pow = min( $pow, count( $units ) - 1 ); 
  210.  
  211. $bytes /= pow( 1024, $pow ); 
  212.  
  213. if ( $units[$pow] == "KB" ) { 
  214. // less precision for small file sizes 
  215. return round( $bytes ) . "KB"; 
  216. } else { 
  217. return round( $bytes, $precision ) . $units[$pow]; 
  218.  
  219. /** 
  220. * Sanitize dimensions (width, height) 
  221. * 
  222. * @since 2.5.0.1 
  223. * @return string Sanitized dimensions, or false if value is invalid 
  224. * @note Replaces old gde_sanitizeOpts function 
  225. */ 
  226. function gde_sanitize_dims( $dim ) { 
  227. // remove any spacing junk 
  228. $dim = trim( str_replace( " ", "", $dim ) ); 
  229.  
  230. if ( ! strstr( $dim, '%' ) ) { 
  231. $type = "px"; 
  232. $dim = preg_replace( "/[^0-9]*/", '', $dim ); 
  233. } else { 
  234. $type = "%"; 
  235. $dim = preg_replace( "/[^0-9]*/", '', $dim ); 
  236. if ( (int) $dim > 100 ) { 
  237. $dim = "100"; 
  238.  
  239. if ( $dim ) { 
  240. return $dim.$type; 
  241. } else { 
  242. return false; 
  243.  
  244. /** 
  245. * Shorten ("mask") the URL to the embedded file 
  246. * 
  247. * @since 2.5.0.1 
  248. * @return string Short url response from API call, or false on error 
  249. */ 
  250. function gde_get_short_url( $u ) { 
  251. $u = urlencode( $u ); 
  252. $service[] = "http://tinyurl.com/api-create.php?url=" . $u; 
  253. $service[] = "http://is.gd/create.php?format=simple&url=" . $u; 
  254.  
  255. foreach ( $service as $url ) { 
  256. $passed = false; 
  257. $response = wp_remote_get( $url ); 
  258. if ( is_wp_error( $response ) || empty ( $response['body'] ) ) { 
  259. continue; 
  260. } else { 
  261. // check for rate limit exceeded or other error response 
  262. if ( ! gde_valid_link( $response['body'] ) ) { 
  263. continue; 
  264. } else { 
  265. $passed = true; 
  266. break; 
  267.  
  268. if ( $passed ) { 
  269. return $response['body']; 
  270. } else { 
  271. // can't shorten - return original URL 
  272. gde_dx_log("Shorten URL failed: " . urldecode( $u )); 
  273. return urldecode( $u ); 
  274.  
  275. /** 
  276. * Request secure URL to document 
  277. * 
  278. * @since 2.5.0.1 
  279. * @return string Secure URL, or false on error 
  280. */ 
  281. function gde_get_secure_url( $u ) { 
  282. require_once( GDE_PLUGIN_DIR . 'libs/lib-secure.php' ); 
  283.  
  284. if ( ! $url = gde_make_secure_url( $u ) ) { 
  285. return false; 
  286. } else { 
  287. return $url; 
  288.  
  289. /** 
  290. * Check if settings allow a file to be privatized (downloads blocked) 
  291. * 
  292. * @since 2.5.0.2 
  293. * @return bool Whether or not the file can be blocked from download 
  294. */ 
  295. function gde_is_blockable( $profile ) { 
  296. if ( $profile['viewer'] == "standard" || $profile['link_show'] !== "none" ) { 
  297. return false; 
  298. } elseif ( ! strstr( $profile['tb_flags'], "n" ) && $profile['tb_fullscr'] == "default" ) { 
  299. return false; 
  300. } else { 
  301. return true; 
  302.  
  303. /** 
  304. * Google Analytics Integration 
  305. * 
  306. * @since 2.5.0.1 
  307. * @return string GA tracking event tag, or blank if disabled 
  308. */ 
  309. function gde_ga_event( $file ) { 
  310. global $gdeoptions; 
  311.  
  312. if ( $gdeoptions['ga_enable'] == "no" ) { 
  313. return ''; 
  314. } elseif ( $gdeoptions['ga_enable'] == "compat" ) { 
  315. $fnp = gde_split_filename( basename( $file ) ); 
  316. $category = "'Download'"; // intentionally not translated (it wasn't a translated string in < 2.5) 
  317. $action = "'" . strtoupper( $fnp[1] ) . "'"; 
  318. $label = "this.href"; 
  319. } else { 
  320. $category = "'" . addslashes( $gdeoptions['ga_category'] ) . "'"; 
  321. $action = "'" . __('Download', 'gde') . "'"; 
  322. if ( $gdeoptions['ga_label'] == "url" ) { 
  323. $label = "this.href"; 
  324. } else { 
  325. $label = "'" . basename( $file ) . "'"; 
  326.  
  327. $str = "_gaq.push(['_trackEvent', ".$category.", ".$action.", ".$label."]);"; 
  328. return " onClick=\"" . $str . "\""; 
  329.  
  330. /** 
  331. * Get plugin data 
  332. * 
  333. * @since 2.4.0.1 
  334. * @return array Array of plugin data parsed from main plugin file 
  335. */ 
  336. function gde_get_plugin_data() { 
  337. $mainfile = 'gviewer.php'; 
  338. $slug = 'google-document-embedder'; 
  339.  
  340. if ( ! function_exists( 'get_plugin_data' ) ) { 
  341. require_once( ABSPATH . '/wp-admin/includes/plugin.php' ); 
  342. $plugin_data = get_plugin_data( GDE_PLUGIN_DIR . $mainfile ); 
  343.  
  344. // add custom data (lowercase to avoid any future conflicts) 
  345. $plugin_data['slug'] = $slug; 
  346. $plugin_data['mainfile'] = $mainfile; 
  347. $plugin_data['basename'] = $plugin_data['slug'] . "/" . $mainfile; 
  348.  
  349. return $plugin_data; 
  350.  
  351. /** 
  352. * GDE Extended Logging 
  353. * 
  354. * @since 2.5.0.1 
  355. * @return bool Whether or not log write was successful 
  356. */ 
  357. function gde_dx_log( $text ) { 
  358. global $gdeoptions, $wpdb; 
  359.  
  360. if ( GDE_DX_LOGGING > 0 || ( isset( $gdeoptions['error_log'] ) && $gdeoptions['error_log'] == "yes" ) ) { 
  361. // filter to trap any "unexpected output" to log 
  362. add_action( 'activated_plugin', 'gde_save_error' ); 
  363.  
  364. $table = $wpdb->base_prefix . 'gde_dx_log'; 
  365.  
  366. // create/update table if necessary, then write to log 
  367. if ( gde_dx_log_create() ) { 
  368. // write to log 
  369. $blogid = get_current_blog_id(); 
  370. $text = date( "d-m-Y, H:i:s" ) . " - $text"; 
  371.  
  372. if ( ! $wpdb->insert( 
  373. $table,  
  374. array( 
  375. 'blogid' => $blogid,  
  376. 'data' => $text 
  377. ),  
  378. array( 
  379. '%d', '%s' 
  380. ) ) { 
  381. // couldn't write to db 
  382. return false; 
  383. } else { 
  384. return true; 
  385. } else { 
  386. // can't create db table 
  387. return false; 
  388. } else { 
  389. // logging disabled 
  390. return false; 
  391.  
  392. /** 
  393. * Create/update database table to store dx log 
  394. * 
  395. * @since 2.5.2.1 
  396. * @return bool Whether or not table creation/update was successful 
  397. */ 
  398. function gde_dx_log_create() { 
  399. global $wpdb, $gde_db_ver; 
  400.  
  401. $table = $wpdb->base_prefix . 'gde_dx_log'; 
  402. $db_ver_installed = get_site_option( 'gde_db_version', 0 ); 
  403.  
  404. $sql = "CREATE TABLE " . $table . " ( 
  405. id mediumint(9) UNSIGNED NOT NULL AUTO_INCREMENT,  
  406. blogid smallint(5) UNSIGNED NOT NULL,  
  407. data longtext NOT NULL,  
  408. UNIQUE KEY (id) 
  409. ) ENGINE=MyISAM DEFAULT CHARSET=utf8; "; 
  410.  
  411. if ( version_compare( $gde_db_ver, $db_ver_installed, ">" ) ) { 
  412. // upgrade table if needed 
  413. require_once( ABSPATH . 'wp-admin/includes/upgrade.php' ); 
  414. dbDelta( $sql ); 
  415. } elseif ( $wpdb->get_var( "SHOW TABLES LIKE '$table'" ) == $table ) { 
  416. // table's OK 
  417. return true; 
  418. } else { 
  419. // table doesn't exist, try to create 
  420. require_once( ABSPATH . 'wp-admin/includes/upgrade.php' ); 
  421. dbDelta( $sql ); 
  422.  
  423. if ( $wpdb->get_var( "SHOW TABLES LIKE '$table'" ) == $table ) { 
  424. // table's OK 
  425. return true; 
  426. } else { 
  427. // can't create 
  428. return false; 
  429.  
  430. /** 
  431. * Capture activation errors ("unexpected output") to dx log 
  432. * 
  433. * @since 2.5.0.1 
  434. * @return void 
  435. * @note Writes any activation errors to log, when enabled 
  436. */ 
  437. function gde_save_error() { 
  438. $buffer = ob_get_contents(); 
  439. if ( ! empty( $buffer ) ) { 
  440. gde_dx_log('Activation Msg: '. $buffer ); 
  441.  
  442. function gde_show_error( $status ) { 
  443. global $gdeoptions; 
  444.  
  445. $error = "GDE " . __('Error', 'gde') . ": " . $status; 
  446. if ( $gdeoptions['error_display'] == "no" ) { 
  447. $code = "\n<!-- $error -->\n"; 
  448. } else { 
  449. $code = "\n".'<div class="gde-error">' . $error . "</div>\n"; 
  450.  
  451. return $code; 
  452.  
  453. /** 
  454. * Check health of database tables 
  455. * 
  456. * @since 2.5.0.3 
  457. * @return mixed 
  458. * @note Verbose text used in debug information 
  459. */ 
  460. function gde_debug_tables( $table = array('gde_profiles', 'gde_secure'), $verbose = false ) { 
  461. global $wpdb; 
  462.  
  463. if ( is_array( $table ) ) { 
  464. $ok = true; 
  465. foreach ( $table as $t ) { 
  466. $t = $wpdb->prefix . $t; 
  467. if ( $wpdb->get_var( "SHOW TABLES LIKE '$t'" ) == $t ) { 
  468. // table good 
  469. } else { 
  470. $ok = false; 
  471. gde_dx_log($t . " table missing"); 
  472. break; 
  473. } else { 
  474. $ok = true; 
  475. $table = $wpdb->prefix . $table; 
  476. if ( $wpdb->get_var( "SHOW TABLES LIKE '$table'" ) == $table ) { 
  477. $s = "OK "; 
  478. $c = $wpdb->get_var( "SELECT COUNT(*) FROM $table WHERE 1=1" ); 
  479. $s = $s . "($c items)"; 
  480. } else { 
  481. $s = "NOT OK ($table missing)"; 
  482. $ok = false; 
  483.  
  484. if ( ! $verbose ) { 
  485. return $ok; 
  486. } else { 
  487. return $s; 
  488.  
  489. ?> 
.