Document Gallery - Version 2.0.3

Version Description

  • Enhancement: Now handles custom user CSS more securely.
  • Enhancement: Now handles calling Ghostscript executable more securely.
  • Enhancement: Now provides timing information for gallery generation when running WordPress in WP_DEBUG mode. When enabled, DG will log to the PHP error log file.
  • Info: Did you know that in tests I performed, Ghostscript (GS) performed 350% faster than using Imagick (IM)? Try testing with this file, which finished almost instantly using GS, but took multiple minutes when using IM on my test server (results may vary). See new FAQ tab to find out why.
Download this release

Release Info

Developer dan.rossiter
Plugin Icon 128x128 Document Gallery
Version 2.0.3
Comparing to
See all releases

Code changes from version 2.0.2 to 2.0.3

README.txt CHANGED
@@ -1,9 +1,10 @@
1
  === Document Gallery ===
2
  Contributors: dan.rossiter
3
  Tags: attachments, thumbnail, documents, gallery, MS office, pdf
 
4
  Requires at least: 3.6
5
  Tested up to: 3.8.1
6
- Stable tag: 2.0.2
7
  License: GPLv2
8
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
9
 
@@ -234,6 +235,43 @@ modifying the image tag, the anchor tag, or the title can be handled with this
234
  filter. Note that this function does not use the $id value it receives, which
235
  is perfectly alright.
236
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
237
  == Screenshots ==
238
 
239
  1. This is an example of "fancy" thumbnails. The images are a copy of the front
@@ -259,6 +297,18 @@ Note that the display inherits styling from your active theme.
259
  forum](http://wordpress.org/support/plugin/document-gallery) if you have
260
  ideas)!
261
 
 
 
 
 
 
 
 
 
 
 
 
 
262
  = 2.0.2 =
263
  * **Bug Fix:** Imagick was actually never working... My bad -- it is now! Thanks to
264
  [kaldimar](http://wordpress.org/support/profile/kaldimar) for reporting this.
@@ -289,7 +339,7 @@ Note that the display inherits styling from your active theme.
289
  in your dashboard and enter valid CSS in the "Custom CSS" textbox. See the changes
290
  instantly in your galleries!
291
  * **Enhancement:** Entire plugin is now
292
- [Internalization-enabled](https://codex.wordpress.org/I18n_for_WordPress_Developers).
293
  This means that we can now support users speaking all languages. If you are
294
  interested in translating Document Gallery into a language that you speak,
295
  please [let me know](http://wordpress.org/support/topic/seeking-translators)!
1
  === Document Gallery ===
2
  Contributors: dan.rossiter
3
  Tags: attachments, thumbnail, documents, gallery, MS office, pdf
4
+ Donate link: https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=EE5LWRLG933EN&lc=US&item_name=Document%20Gallery%20Plugin&item_number=document%2dgallery&currency_code=USD&bn=PP%2dDonationsBF%3abtn_donateCC_LG%2egif%3aNonHosted
5
  Requires at least: 3.6
6
  Tested up to: 3.8.1
7
+ Stable tag: 2.0.3
8
  License: GPLv2
9
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
10
 
235
  filter. Note that this function does not use the $id value it receives, which
236
  is perfectly alright.
237
 
238
+ == Frequently Asked Questions ==
239
+
240
+ = Q: Why is *-insert thumbnail generation method-* enabled on one of my WordPress
241
+ installs, but not on another one? =
242
+
243
+ A: Document Gallery works very hard behind the scenes to ensure that it enables
244
+ as much as is possible for any given server, but some servers just can't do
245
+ some of the things that the plugin supports. Document Gallery detects when a
246
+ server can't do something (run Ghostscript, for example) and disables that option.
247
+ If you later modify your server to handle one of the thumbnail generation methods,
248
+ Document Gallery will notice this and re-enable the option on the settings page,
249
+ though you will need to go in and tell Document Gallery that it should use this
250
+ newly-enabled method.
251
+
252
+ = Q: Why is Ghostscript so much faster than Imagick? =
253
+
254
+ A: This comes down to how the two programs work. Imagick actually delegates
255
+ handling of PDFs to Ghostscript behind the scenes, but it doesn't do so
256
+ intelligently. Before passing off the PDF, it first reads the entire contents
257
+ of the PDF into memory. Since we only need a single page to generate the
258
+ thumbnail, this is much more work than is needed. Ghostscript, on the other hand,
259
+ can handle reading only one page into memory, thus doing much less work before
260
+ returning our thumbnail.
261
+
262
+ = Q: Why isn't Google Drive Viewer enabled by default? =
263
+
264
+ A: Google Drive Viewer is the most commonly-supported thumbnail generation method,
265
+ alongside the Audio/Video generation, but is disabled by default. The reason
266
+ for this is that in order to use this method, Document Gallery has to send your
267
+ document over to Google's servers, where Google will generate the thumbnail for
268
+ you. For most users, this shouldn't be a big deal, but since some users
269
+ retain sensitive documents on their site, this was made opt-in to avoid
270
+ compromising anyone's security. If you don't have sensitive documents, I
271
+ would recommend enabling it, since it's currently the only way to generate a
272
+ thumbnail for any of the Microsoft Office files, as well as some less common
273
+ file types.
274
+
275
  == Screenshots ==
276
 
277
  1. This is an example of "fancy" thumbnails. The images are a copy of the front
297
  forum](http://wordpress.org/support/plugin/document-gallery) if you have
298
  ideas)!
299
 
300
+ = 2.0.3 =
301
+ * **Enhancement:** Now handles custom user CSS more securely.
302
+ * **Enhancement:** Now handles calling Ghostscript executable more securely.
303
+ * **Enhancement:** Now provides timing information for gallery generation
304
+ when running WordPress in [WP_DEBUG](https://codex.wordpress.org/WP_DEBUG)
305
+ mode. When enabled, DG will log to the PHP error log file.
306
+ * **Info:** Did you know that in tests I performed, Ghostscript (GS) performed
307
+ 350% faster than using Imagick (IM)? Try testing with
308
+ [this file](http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf),
309
+ which finished almost instantly using GS, but took multiple minutes when
310
+ using IM on my test server (results may vary). See new FAQ tab to find out why.
311
+
312
  = 2.0.2 =
313
  * **Bug Fix:** Imagick was actually never working... My bad -- it is now! Thanks to
314
  [kaldimar](http://wordpress.org/support/profile/kaldimar) for reporting this.
339
  in your dashboard and enter valid CSS in the "Custom CSS" textbox. See the changes
340
  instantly in your galleries!
341
  * **Enhancement:** Entire plugin is now
342
+ [Internationalization-enabled](https://codex.wordpress.org/I18n_for_WordPress_Developers).
343
  This means that we can now support users speaking all languages. If you are
344
  interested in translating Document Gallery into a language that you speak,
345
  please [let me know](http://wordpress.org/support/topic/seeking-translators)!
admin/class-admin.php CHANGED
@@ -37,15 +37,6 @@ class DG_Admin {
37
  __('Document Gallery Settings', 'document-gallery'),
38
  __('Document Gallery', 'document-gallery'),
39
  'manage_options', 'document_gallery', array(__CLASS__, 'renderOptions'));
40
-
41
- add_action('admin_print_styles-' . $page, array(__CLASS__, 'enqueueAdminStyle'));
42
- }
43
-
44
- /**
45
- * Registers stylesheet for admin options page.
46
- */
47
- public static function registerAdminStyle() {
48
- wp_register_style('dg-admin', DG_URL . 'admin/css/style.css', null, DG_VERSION);
49
  }
50
 
51
  /**
@@ -377,15 +368,12 @@ class DG_Admin {
377
  }
378
  }
379
 
380
- // handle changed CSS
381
- if (trim($values['css']) != trim($ret['css']['text'])) {
382
- if (DocumentGallery::updateUserGalleryStyle($values['css'])) {
383
- $ret['css']['text'] = $values['css'];
384
- $ret['css']['version']++;
385
- } else {
386
- add_settings_error(DG_OPTION_NAME, 'css',
387
- __('Failed to update CSS file.', 'document-gallery'));
388
- }
389
  }
390
 
391
  // handle setting the Ghostscript path
@@ -403,13 +391,6 @@ class DG_Admin {
403
  return $ret;
404
  }
405
 
406
- /**
407
- * Enqueues stylesheet for admin options page.
408
- */
409
- public static function enqueueAdminStyle() {
410
- wp_enqueue_style('dg-admin');
411
- }
412
-
413
  /**
414
  * Blocks instantiation. All functions are static.
415
  */
37
  __('Document Gallery Settings', 'document-gallery'),
38
  __('Document Gallery', 'document-gallery'),
39
  'manage_options', 'document_gallery', array(__CLASS__, 'renderOptions'));
 
 
 
 
 
 
 
 
 
40
  }
41
 
42
  /**
368
  }
369
  }
370
 
371
+ // handle modified CSS
372
+ if (trim($ret['css']['text']) !== trim($values['css'])) {
373
+ $ret['css']['text'] = trim($values['css']);
374
+ $ret['css']['version']++;
375
+ $ret['css']['last-modified'] = gmdate('D, d M Y H:i:s');
376
+ $ret['css']['etag'] = md5($ret['css']['last-modified']);
 
 
 
377
  }
378
 
379
  // handle setting the Ghostscript path
391
  return $ret;
392
  }
393
 
 
 
 
 
 
 
 
394
  /**
395
  * Blocks instantiation. All functions are static.
396
  */
admin/css/style.css DELETED
@@ -1,17 +0,0 @@
1
- #cached-thumbs {
2
- }
3
-
4
- #cached-thumbs tr {
5
- height: 100px;
6
- }
7
-
8
- table#cached-thumbs td.thumb-img {
9
- width: 75px;
10
- text-align: center;
11
- padding-right: 5px;
12
- }
13
-
14
- #cached-thumbs td.thumb-img > img {
15
- max-width: 75px;
16
- max-height: 75px;
17
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
assets/css/style.css CHANGED
@@ -62,6 +62,4 @@ div.descriptions.document-icon-wrapper:after{
62
  div.descriptions.document-icon-wrapper{
63
  zoom: 1; /* For IE 6/7 (trigger hasLayout) */
64
  }
65
- /* END WITH DESCRIPTION */
66
-
67
- /* CUSTOM USER CSS */
62
  div.descriptions.document-icon-wrapper{
63
  zoom: 1; /* For IE 6/7 (trigger hasLayout) */
64
  }
65
+ /* END WITH DESCRIPTION */
 
 
document-gallery.php CHANGED
@@ -3,8 +3,9 @@ defined('WPINC') OR exit;
3
 
4
  /*
5
  Plugin Name: Document Gallery
 
6
  Description: Display non-images (and images) in gallery format on a page or post with the [dg] shortcode.
7
- Version: 2.0.2
8
  Author: Dan Rossiter
9
  Author URI: http://danrossiter.org/
10
  License: GPLv2
@@ -12,7 +13,7 @@ defined('WPINC') OR exit;
12
  */
13
 
14
  // define helper paths & URLs
15
- define('DG_VERSION', '2.0.2');
16
  define('DG_URL', plugin_dir_url(__FILE__));
17
  define('DG_PATH', plugin_dir_path(__FILE__));
18
  if(!defined('WP_INCLUDE_DIR')) {
@@ -52,12 +53,17 @@ if (is_admin()) {
52
  if (!empty($GLOBALS['pagenow'])
53
  && ('options-general.php' === $GLOBALS['pagenow'] // output
54
  || 'options.php' === $GLOBALS['pagenow'])) { // validation
55
- add_action('admin_init', array('DG_Admin', 'registerAdminStyle'));
56
  add_action('admin_init', array('DG_Admin', 'registerSettings'));
57
  }
58
  } else {
59
  // styling for gallery
60
- add_action('wp_enqueue_scripts', array('DocumentGallery', 'enqueueGalleryStyle'));
 
 
 
 
 
 
61
  }
62
 
63
  // adds 'dg' shortcode
@@ -70,6 +76,11 @@ add_shortcode('dg', array('DocumentGallery', 'doShortcode'));
70
  */
71
  class DocumentGallery {
72
 
 
 
 
 
 
73
  /*==========================================================================
74
  * THE SHORTCODE
75
  *=========================================================================*/
@@ -83,29 +94,85 @@ class DocumentGallery {
83
  */
84
  public static function doShortcode($atts) {
85
  include_once 'inc/class-gallery.php';
86
- return new DG_Gallery($atts);
 
 
 
 
 
87
  }
88
 
89
  /**
90
  * Enqueue standard DG CSS.
91
  */
92
  public static function enqueueGalleryStyle() {
 
 
 
 
 
 
 
 
93
  global $dg_options;
94
- wp_register_style('dg-main', DG_URL . 'assets/css/style.css', null,
95
- DG_VERSION . ':' . $dg_options['css']['version']);
96
- wp_enqueue_style('dg-main');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
97
  }
98
 
99
- public static function updateUserGalleryStyle($css) {
100
- $ret = false;
 
101
 
102
- if ($css_file = file_get_contents(DG_PATH . 'assets/css/style.css')) {
103
- $css_file = preg_replace('#/\* CUSTOM USER CSS \*/.*#s',
104
- "/* CUSTOM USER CSS */\n" . $css, $css_file);
105
- $ret = (bool)file_put_contents(DG_PATH . 'assets/css/style.css', $css_file, LOCK_EX);
 
 
 
 
 
 
 
 
 
106
  }
107
-
108
- return $ret;
109
  }
110
 
111
  /*==========================================================================
3
 
4
  /*
5
  Plugin Name: Document Gallery
6
+ Plugin URI: http://wordpress.org/extend/plugins/document-gallery/
7
  Description: Display non-images (and images) in gallery format on a page or post with the [dg] shortcode.
8
+ Version: 2.0.3
9
  Author: Dan Rossiter
10
  Author URI: http://danrossiter.org/
11
  License: GPLv2
13
  */
14
 
15
  // define helper paths & URLs
16
+ define('DG_VERSION', '2.0.3');
17
  define('DG_URL', plugin_dir_url(__FILE__));
18
  define('DG_PATH', plugin_dir_path(__FILE__));
19
  if(!defined('WP_INCLUDE_DIR')) {
53
  if (!empty($GLOBALS['pagenow'])
54
  && ('options-general.php' === $GLOBALS['pagenow'] // output
55
  || 'options.php' === $GLOBALS['pagenow'])) { // validation
 
56
  add_action('admin_init', array('DG_Admin', 'registerSettings'));
57
  }
58
  } else {
59
  // styling for gallery
60
+ if (empty($dg_options['css']['text'])) {
61
+ add_action('wp_enqueue_scripts', array('DocumentGallery', 'enqueueGalleryStyle'));
62
+ } else {
63
+ add_action('template_redirect', array('DocumentGallery', 'buildCustomCss'));
64
+ add_action('wp_enqueue_scripts', array('DocumentGallery', 'enqueueCustomStyle'));
65
+ add_filter('query_vars', array('DocumentGallery', 'addCustomStyleQueryVar'));
66
+ }
67
  }
68
 
69
  // adds 'dg' shortcode
76
  */
77
  class DocumentGallery {
78
 
79
+ /**
80
+ * @var str Name of the query var used to check whether we should print custom CSS.
81
+ */
82
+ private static $query_var = 'document-gallery-css';
83
+
84
  /*==========================================================================
85
  * THE SHORTCODE
86
  *=========================================================================*/
94
  */
95
  public static function doShortcode($atts) {
96
  include_once 'inc/class-gallery.php';
97
+
98
+ $start = microtime(true);
99
+ $gallery = (string)new DG_Gallery($atts);
100
+ DocumentGallery::writeLog('Generation Time: ' . (microtime(true) - $start) . ' s');
101
+
102
+ return $gallery;
103
  }
104
 
105
  /**
106
  * Enqueue standard DG CSS.
107
  */
108
  public static function enqueueGalleryStyle() {
109
+ wp_register_style('document-gallery', DG_URL . 'assets/css/style.css', null, DG_VERSION);
110
+ wp_enqueue_style('document-gallery');
111
+ }
112
+
113
+ /**
114
+ * Enqueue user's custom DG CSS.
115
+ */
116
+ public static function enqueueCustomStyle() {
117
  global $dg_options;
118
+ wp_register_style('document-gallery', add_query_arg(self::$query_var, 1, home_url('/')),
119
+ null, DG_VERSION . ':' . $dg_options['css']['version']);
120
+ wp_enqueue_style('document-gallery');
121
+ }
122
+
123
+ /**
124
+ * Add query custom CSS query string.
125
+ * Taken from here: http://ottopress.com/2010/dont-include-wp-load-please/
126
+ * @param array $vars
127
+ * @return array
128
+ */
129
+ public static function addCustomStyleQueryVar($vars) {
130
+ $vars[] = self::$query_var;
131
+ return $vars;
132
+ }
133
+
134
+ /**
135
+ * Constructs user's custom CSS dynamically, then instructs
136
+ * browser to cache for a year. Cache is busted by versioning
137
+ * CSS any time the user makes a change.
138
+ */
139
+ public static function buildCustomCss() {
140
+ if (1 == intval(get_query_var(self::$query_var))) {
141
+ global $dg_options;
142
+
143
+ header('Content-type: text/css; charset=UTF-8');
144
+ header('Cache-Control: no-transform,public,maxage=' . 31536000);
145
+ header('Expires: ' . gmdate('D, d M Y H:i:s', time() + 31536000) . ' GMT');
146
+ header('Last-Modified: ' . $dg_options['css']['last-modified']);
147
+ header('ETag: ' . $dg_options['css']['etag']);
148
+
149
+ // standard CSS
150
+ echo file_get_contents(DG_PATH . 'assets/css/style.css') . PHP_EOL;
151
+
152
+ // custom CSS
153
+ echo str_replace('>', '>', esc_html($dg_options['css']['text']));
154
+ exit;
155
+ }
156
  }
157
 
158
+ /*==========================================================================
159
+ * Logging
160
+ *=========================================================================*/
161
 
162
+ /**
163
+ * Appends error log with $entry if WordPress is in debug mode.
164
+ *
165
+ * @param str $entry
166
+ */
167
+ public static function writeLog($entry) {
168
+ if (defined('WP_DEBUG') && WP_DEBUG) {
169
+ $err = 'DG: ' . print_r($entry, true) . PHP_EOL;
170
+ if (defined('ERRORLOGFILE')) {
171
+ error_log($err, 3, ERRORLOGFILE);
172
+ } else {
173
+ error_log($err);
174
+ }
175
  }
 
 
176
  }
177
 
178
  /*==========================================================================
inc/class-gallery.php CHANGED
@@ -406,42 +406,25 @@ class DG_Gallery {
406
  */
407
  private function setTaxa(&$query) {
408
  if(!empty($this->taxa)) {
409
- global $wp_version;
410
  $taxa = array();
411
 
412
- // use preferred tax_query if supported
413
- if (version_compare($wp_version, '3.1', '>=')) {
414
- // only include relation if we have multiple taxa
415
- if(count($this->taxa) > 1) {
416
- $taxa['relation'] = $this->atts['relation'];
417
- }
418
-
419
- foreach ($this->taxa as $taxon => $terms) {
420
- $terms = $this->getTermIdsByNames($taxon, explode(',', $terms));
421
-
422
- $taxa[] = array(
423
- 'taxonomy' => $taxon,
424
- 'field' => 'id',
425
- 'terms' => $terms
426
- );
427
- }
428
 
429
- // create nested structure
430
- $query['tax_query'] = $taxa;
431
- } elseif (version_compare($wp_version, '2.3', '>=')) {
432
- // fallback to deprecated {tax_name} => {term_slug} construct
433
- foreach ($this->taxa as $taxon => $terms) {
434
- $taxa[$taxon] = ($taxon == 'category')
435
- ? implode(',', $this->getTermIdsByNames($taxon, explode(',', $terms)))
436
- : implode(',', $this->getTermSlugsByNames($taxon, explode(',', $terms)));
437
- }
438
 
439
- $query = array_merge($taxa, $query);
440
- } else {
441
- // WP < 2.3 not supported for category/custom taxa
442
- $this->errs[] = __('The following attributes are invalid: ', 'document-gallery') .
443
- implode(', ', array_keys($this->taxa));
444
  }
 
 
 
445
  }
446
  }
447
 
406
  */
407
  private function setTaxa(&$query) {
408
  if(!empty($this->taxa)) {
 
409
  $taxa = array();
410
 
411
+ // only include relation if we have multiple taxa
412
+ if(count($this->taxa) > 1) {
413
+ $taxa['relation'] = $this->atts['relation'];
414
+ }
 
 
 
 
 
 
 
 
 
 
 
 
415
 
416
+ foreach ($this->taxa as $taxon => $terms) {
417
+ $terms = $this->getTermIdsByNames($taxon, explode(',', $terms));
 
 
 
 
 
 
 
418
 
419
+ $taxa[] = array(
420
+ 'taxonomy' => $taxon,
421
+ 'field' => 'id',
422
+ 'terms' => $terms
423
+ );
424
  }
425
+
426
+ // create nested structure
427
+ $query['tax_query'] = $taxa;
428
  }
429
  }
430
 
inc/class-image-editor-imagick.php CHANGED
@@ -32,13 +32,35 @@ class DG_Image_Editor_Imagick extends WP_Image_Editor_Imagick {
32
  $ret = parent::load();
33
 
34
  // set correct page number
35
- if (!is_wp_error($ret) && !is_null($this->pg)) {
36
- if (is_callable(array($this->image, 'setIteratorIndex'))) {
37
- $this->image->setIteratorIndex($this->pg);
 
 
 
 
 
 
 
 
 
 
 
38
  }
39
  }
40
 
41
  return $ret;
42
  }
 
 
 
 
 
 
 
 
 
 
 
43
  }
44
  ?>
32
  $ret = parent::load();
33
 
34
  // set correct page number
35
+ if (!is_wp_error($ret) && !is_null($this->pg)
36
+ && is_callable(array($this->image, 'setIteratorIndex'))) {
37
+ $err = __('Failed to set Imagick page number');
38
+
39
+ // setIteratorIndex() should return false on failure, but I've found
40
+ // reports of it throwing an error so handling both cases.
41
+ // NOTE: I've also seen it fail and return true, so we may not
42
+ // log anything on failure...
43
+ try {
44
+ if (!$this->image->setIteratorIndex($this->pg)) {
45
+ DocumentGallery::writeLog($err . '.');
46
+ }
47
+ } catch(Exception $e) {
48
+ DocumentGallery::writeLog($err . ': ' . $e->getMessage());
49
  }
50
  }
51
 
52
  return $ret;
53
  }
54
+
55
+ /**
56
+ * @return array/bool The formats supported by Imagick, or false
57
+ */
58
+ public static function query_formats() {
59
+ try {
60
+ return @Imagick::queryFormats();
61
+ } catch (Exception $ex) {
62
+ return false;
63
+ }
64
+ }
65
  }
66
  ?>
inc/class-setup.php CHANGED
@@ -13,6 +13,8 @@ class DG_Setup {
13
  */
14
  public static function getDefaultOptions() {
15
  include_once DG_PATH . 'inc/class-thumber.php';
 
 
16
  return array(
17
  'thumber' => array(
18
  'thumbs' => array(),
@@ -39,7 +41,12 @@ class DG_Setup {
39
  'relation' => 'AND'
40
  )
41
  ),
42
- 'css' => array('version' => 0, 'text' => ''),
 
 
 
 
 
43
  'version' => DG_VERSION
44
  );
45
  }
@@ -52,14 +59,18 @@ class DG_Setup {
52
 
53
  // first installation
54
  if (empty($dg_options)) {
55
- $options = self::getDefaultOptions();
56
- add_option(DG_OPTION_NAME, $options);
57
  }
58
 
59
  // do update
60
  elseif (DG_VERSION !== $dg_options['version']) {
61
- // update version in DB
62
  $dg_options['version'] = DG_VERSION;
 
 
 
 
63
 
64
  // remove previously-failed thumbs
65
  $thumbs = $dg_options['thumber']['thumbs'];
@@ -69,11 +80,6 @@ class DG_Setup {
69
  }
70
  }
71
 
72
- // re-edit CSS file
73
- if ('' !== $dg_options['css']['text']) {
74
- DocumentGallery::updateUserGalleryStyle($dg_options['css']['text']);
75
- }
76
-
77
  // commit DB changes
78
  update_option(DG_OPTION_NAME, $dg_options);
79
  }
13
  */
14
  public static function getDefaultOptions() {
15
  include_once DG_PATH . 'inc/class-thumber.php';
16
+ $date = gmdate('D, d M Y H:i:s');
17
+ $etag = md5($date);
18
  return array(
19
  'thumber' => array(
20
  'thumbs' => array(),
41
  'relation' => 'AND'
42
  )
43
  ),
44
+ 'css' => array(
45
+ 'text' => '',
46
+ 'last-modified' => $date,
47
+ 'etag' => $etag,
48
+ 'version' => 0
49
+ ),
50
  'version' => DG_VERSION
51
  );
52
  }
59
 
60
  // first installation
61
  if (empty($dg_options)) {
62
+ $dg_options = self::getDefaultOptions();
63
+ add_option(DG_OPTION_NAME, $dg_options);
64
  }
65
 
66
  // do update
67
  elseif (DG_VERSION !== $dg_options['version']) {
68
+ // update plugin version
69
  $dg_options['version'] = DG_VERSION;
70
+
71
+ // used in dynamic CSS HTTP headers
72
+ $dg_options['css']['last-modified'] = gmdate('D, d M Y H:i:s');
73
+ $dg_options['css']['etag'] = md5($dg_options['css']['last-modified']);
74
 
75
  // remove previously-failed thumbs
76
  $thumbs = $dg_options['thumber']['thumbs'];
80
  }
81
  }
82
 
 
 
 
 
 
83
  // commit DB changes
84
  update_option(DG_OPTION_NAME, $dg_options);
85
  }
inc/class-thumber.php CHANGED
@@ -87,17 +87,11 @@ class DG_Thumber {
87
  * Uses wp_read_video_metadata() and wp_read_audio_metadata() to retrieve
88
  * an embedded image to use as a thumbnail.
89
  *
90
- * NOTE: Caller must verify that WP version >= 3.6.
91
- *
92
  * @param str $ID The attachment ID to retrieve thumbnail from.
93
  * @param int $pg Unused.
94
  * @return bool|str False on failure, URL to thumb on success.
95
  */
96
  public static function getAudioVideoThumbnail($ID, $pg = 1) {
97
- if(!file_exists(WP_ADMIN_DIR . '/includes/media.php')) {
98
- return false;
99
- }
100
-
101
  include_once WP_ADMIN_DIR . '/includes/media.php';
102
 
103
  $attachment = get_post($ID);
@@ -128,12 +122,12 @@ class DG_Thumber {
128
  $temp_file = self::getTempFile($ext);
129
 
130
  if (!$fp = @fopen($temp_file, 'wb')) {
131
- self::writeLog(__('Could not open file: ', 'document-gallery') . $temp_file);
132
  return false;
133
  }
134
 
135
  if (!@fwrite($fp, $metadata['image']['data'])) {
136
- self::writeLog(__('Could not write file: ', 'document-gallery') . $temp_file);
137
  fclose($fp);
138
  return false;
139
  }
@@ -168,7 +162,7 @@ class DG_Thumber {
168
  $img = new DG_Image_Editor_Imagick($doc_path, $pg - 1);
169
  $err = $img->load();
170
  if(is_wp_error($err)) {
171
- self::writeLog(
172
  __('Failed to open file in Imagick: ', 'document-gallery') .
173
  $err->get_error_message());
174
  return false;
@@ -178,7 +172,7 @@ class DG_Thumber {
178
 
179
  $err = $img->save($temp_file, 'image/png');
180
  if (is_wp_error($err)) {
181
- self::writeLog(
182
  __('Failed to save image in Imagick: ', 'document-gallery') .
183
  $err->get_error_message());
184
  return false;
@@ -194,12 +188,9 @@ class DG_Thumber {
194
  static $ret = null;
195
 
196
  if (is_null($ret)) {
197
- $ret = false;
198
- if (file_exists(WP_INCLUDE_DIR . '/class-wp-image-editor-imagick.php')) {
199
- include_once WP_INCLUDE_DIR . '/class-wp-image-editor.php';
200
- include_once WP_INCLUDE_DIR . '/class-wp-image-editor-imagick.php';
201
- $ret = WP_Image_Editor_Imagick::test();
202
- }
203
  }
204
 
205
  return $ret;
@@ -223,9 +214,10 @@ class DG_Thumber {
223
  if (is_null($gs)) {
224
  $options = self::getOptions();
225
  $gs = $options['gs'];
 
226
  if (false !== $gs) {
227
- $gs = "\"$gs\" -sDEVICE=png16m -dFirstPage=%d -dLastPage=%d"
228
- . ' -dBATCH -dNOPAUSE -dPDFFitPage -sOutputFile=%s %s';
229
  }
230
  }
231
 
@@ -239,7 +231,7 @@ class DG_Thumber {
239
  exec(sprintf($gs, $pg, $pg, $temp_path, $doc_path), $out, $ret);
240
 
241
  if ($ret != 0) {
242
- self::writeLog(__('Ghostscript failed: ', 'document-gallery') . print_r($out));
243
  @unlink($temp_path);
244
  return false;
245
  }
@@ -255,7 +247,10 @@ class DG_Thumber {
255
  }
256
 
257
  /**
258
- * Checks whether we may call gs through exec().
 
 
 
259
  *
260
  * @return bool|str If available, returns exe path. False otherwise.
261
  */
@@ -271,11 +266,11 @@ class DG_Thumber {
271
  if ('WIN' === strtoupper(substr(PHP_OS, 0, 3))) {
272
  // look for environment variable
273
  $executable = getenv('GSC');
274
- if($executable) return $executable;
275
 
276
  // hope GS in the path
277
  $executable = exec('where gswin*c.exe');
278
- if(!empty($executable)) return $executable;
279
 
280
  // look directly in filesystem
281
  // 64- or 32-bit binary
@@ -352,7 +347,7 @@ class DG_Thumber {
352
  $response = wp_remote_get($google_viewer, $args);
353
 
354
  if (is_wp_error($response) || !preg_match('/[23][0-9]{2}/', $response['response']['code'])) {
355
- self::writeLog(__('Failed to retrieve thumbnail from Google: ', 'document-gallery') .
356
  (is_wp_error($response)
357
  ? $response->get_error_message()
358
  : $response['response']['message']));
@@ -563,7 +558,7 @@ class DG_Thumber {
563
  $thumbers = array();
564
 
565
  // Audio/Video embedded images
566
- if ($active['av'] && version_compare($wp_version, '3.6', '>=')) {
567
  $exts = implode('|', self::getAudioVideoExts());
568
  $thumbers[$exts] = array(__CLASS__, 'getAudioVideoThumbnail');
569
  }
@@ -576,17 +571,10 @@ class DG_Thumber {
576
 
577
  // Imagick
578
  if ($active['imagick'] && self::isImagickAvailable()) {
579
- include_once WP_INCLUDE_DIR . '/class-wp-image-editor.php';
580
- include_once WP_INCLUDE_DIR . '/class-wp-image-editor-imagick.php';
581
- try {
582
- $exts = @Imagick::queryFormats();
583
- if($exts) {
584
- $exts = implode('|', $exts);
585
- $thumbers[$exts] = array(__CLASS__, 'getImagickThumbnail');
586
- }
587
- }
588
- catch (Exception $e) {
589
-
590
  }
591
  }
592
 
@@ -638,7 +626,7 @@ class DG_Thumber {
638
  $img = wp_get_image_editor($temp_path);
639
 
640
  if (is_wp_error($img)) {
641
- self::writeLog(
642
  __('Failed to get image editor: ', 'document-gallery') .
643
  $img->get_error_message());
644
  return false;
@@ -649,7 +637,7 @@ class DG_Thumber {
649
  $err = $img->save($thumb_path);
650
 
651
  if (is_wp_error($err)) {
652
- self::writeLog(
653
  __('Failed to save image: ', 'document-gallery') .
654
  $err->get_error_message());
655
  return false;
@@ -759,22 +747,6 @@ class DG_Thumber {
759
  return false;
760
  }
761
 
762
- /**
763
- * Appends error log with $entry if WordPress is in debug mode.
764
- *
765
- * @param str $entry
766
- */
767
- private static function writeLog($entry) {
768
- if (defined('WP_DEBUG') && WP_DEBUG) {
769
- $err = 'DG: ' . print_r($entry, true) . PHP_EOL;
770
- if (defined('ERRORLOGFILE')) {
771
- error_log($err, 3, ERRORLOGFILE);
772
- } else {
773
- error_log($err);
774
- }
775
- }
776
- }
777
-
778
  /**
779
  * Blocks instantiation. All functions are static.
780
  */
87
  * Uses wp_read_video_metadata() and wp_read_audio_metadata() to retrieve
88
  * an embedded image to use as a thumbnail.
89
  *
 
 
90
  * @param str $ID The attachment ID to retrieve thumbnail from.
91
  * @param int $pg Unused.
92
  * @return bool|str False on failure, URL to thumb on success.
93
  */
94
  public static function getAudioVideoThumbnail($ID, $pg = 1) {
 
 
 
 
95
  include_once WP_ADMIN_DIR . '/includes/media.php';
96
 
97
  $attachment = get_post($ID);
122
  $temp_file = self::getTempFile($ext);
123
 
124
  if (!$fp = @fopen($temp_file, 'wb')) {
125
+ DocumentGallery::writeLog(__('Could not open file: ', 'document-gallery') . $temp_file);
126
  return false;
127
  }
128
 
129
  if (!@fwrite($fp, $metadata['image']['data'])) {
130
+ DocumentGallery::writeLog(__('Could not write file: ', 'document-gallery') . $temp_file);
131
  fclose($fp);
132
  return false;
133
  }
162
  $img = new DG_Image_Editor_Imagick($doc_path, $pg - 1);
163
  $err = $img->load();
164
  if(is_wp_error($err)) {
165
+ DocumentGallery::writeLog(
166
  __('Failed to open file in Imagick: ', 'document-gallery') .
167
  $err->get_error_message());
168
  return false;
172
 
173
  $err = $img->save($temp_file, 'image/png');
174
  if (is_wp_error($err)) {
175
+ DocumentGallery::writeLog(
176
  __('Failed to save image in Imagick: ', 'document-gallery') .
177
  $err->get_error_message());
178
  return false;
188
  static $ret = null;
189
 
190
  if (is_null($ret)) {
191
+ include_once WP_INCLUDE_DIR . '/class-wp-image-editor.php';
192
+ include_once WP_INCLUDE_DIR . '/class-wp-image-editor-imagick.php';
193
+ $ret = WP_Image_Editor_Imagick::test();
 
 
 
194
  }
195
 
196
  return $ret;
214
  if (is_null($gs)) {
215
  $options = self::getOptions();
216
  $gs = $options['gs'];
217
+
218
  if (false !== $gs) {
219
+ $gs = escapeshellarg($gs) . ' -sDEVICE=png16m -dFirstPage=%d'
220
+ . ' -dLastPage=%d -dBATCH -dNOPAUSE -dPDFFitPage -sOutputFile=%s %s';
221
  }
222
  }
223
 
231
  exec(sprintf($gs, $pg, $pg, $temp_path, $doc_path), $out, $ret);
232
 
233
  if ($ret != 0) {
234
+ DocumentGallery::writeLog(__('Ghostscript failed: ', 'document-gallery') . print_r($out));
235
  @unlink($temp_path);
236
  return false;
237
  }
247
  }
248
 
249
  /**
250
+ * Dynamically determines whether we may call gs through exec().
251
+ *
252
+ * NOTE: This does not check the options for gs path. Don't use in
253
+ * thumbnail generation as it's slow and not configurable.
254
  *
255
  * @return bool|str If available, returns exe path. False otherwise.
256
  */
266
  if ('WIN' === strtoupper(substr(PHP_OS, 0, 3))) {
267
  // look for environment variable
268
  $executable = getenv('GSC');
269
+ if ($executable) return $executable;
270
 
271
  // hope GS in the path
272
  $executable = exec('where gswin*c.exe');
273
+ if (!empty($executable)) return $executable;
274
 
275
  // look directly in filesystem
276
  // 64- or 32-bit binary
347
  $response = wp_remote_get($google_viewer, $args);
348
 
349
  if (is_wp_error($response) || !preg_match('/[23][0-9]{2}/', $response['response']['code'])) {
350
+ DocumentGallery::writeLog(__('Failed to retrieve thumbnail from Google: ', 'document-gallery') .
351
  (is_wp_error($response)
352
  ? $response->get_error_message()
353
  : $response['response']['message']));
558
  $thumbers = array();
559
 
560
  // Audio/Video embedded images
561
+ if ($active['av']) {
562
  $exts = implode('|', self::getAudioVideoExts());
563
  $thumbers[$exts] = array(__CLASS__, 'getAudioVideoThumbnail');
564
  }
571
 
572
  // Imagick
573
  if ($active['imagick'] && self::isImagickAvailable()) {
574
+ include_once DG_PATH . 'inc/class-image-editor-imagick.php';
575
+ if ($exts = DG_Image_Editor_Imagick::query_formats()) {
576
+ $exts = implode('|', $exts);
577
+ $thumbers[$exts] = array(__CLASS__, 'getImagickThumbnail');
 
 
 
 
 
 
 
578
  }
579
  }
580
 
626
  $img = wp_get_image_editor($temp_path);
627
 
628
  if (is_wp_error($img)) {
629
+ DocumentGallery::writeLog(
630
  __('Failed to get image editor: ', 'document-gallery') .
631
  $img->get_error_message());
632
  return false;
637
  $err = $img->save($thumb_path);
638
 
639
  if (is_wp_error($err)) {
640
+ DocumentGallery::writeLog(
641
  __('Failed to save image: ', 'document-gallery') .
642
  $err->get_error_message());
643
  return false;
747
  return false;
748
  }
749
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
750
  /**
751
  * Blocks instantiation. All functions are static.
752
  */
languages/document-gallery.pot CHANGED
@@ -2,9 +2,9 @@
2
  # This file is distributed under the same license as the Document Gallery package.
3
  msgid ""
4
  msgstr ""
5
- "Project-Id-Version: Document Gallery 2.0.2\n"
6
  "Report-Msgid-Bugs-To: http://wordpress.org/tag/document-gallery\n"
7
- "POT-Creation-Date: 2014-03-22 07:07:30+00:00\n"
8
  "MIME-Version: 1.0\n"
9
  "Content-Type: text/plain; charset=UTF-8\n"
10
  "Content-Transfer-Encoding: 8bit\n"
@@ -20,203 +20,199 @@ msgstr ""
20
  msgid "Document Gallery Settings"
21
  msgstr ""
22
 
23
- #. #-#-#-#-# plugin.pot (Document Gallery 2.0) #-#-#-#-#
24
  #. Plugin Name of the plugin/theme
25
  #: admin/class-admin.php:38
26
  msgid "Document Gallery"
27
  msgstr ""
28
 
29
- #: admin/class-admin.php:67
30
  msgid "Default Settings"
31
  msgstr ""
32
 
33
- #: admin/class-admin.php:71
34
  msgid "Thumbnail Generation"
35
  msgstr ""
36
 
37
- #: admin/class-admin.php:75
38
  msgid "Custon CSS"
39
  msgstr ""
40
 
41
- #: admin/class-admin.php:79
42
  msgid "Advanced Thumbnail Generation"
43
  msgstr ""
44
 
45
- #: admin/class-admin.php:91
46
  msgid "Link to attachment page rather than to file"
47
  msgstr ""
48
 
49
- #: admin/class-admin.php:103
50
  msgid "Include document descriptions"
51
  msgstr ""
52
 
53
- #: admin/class-admin.php:115
54
  msgid "Use auto-generated document thumbnails"
55
  msgstr ""
56
 
57
- #: admin/class-admin.php:127
58
  msgid "Include image attachments in gallery"
59
  msgstr ""
60
 
61
- #: admin/class-admin.php:139
62
  msgid "Only look for attachments in post where [dg] is used"
63
  msgstr ""
64
 
65
- #: admin/class-admin.php:152
66
  msgid "Ascending or decending sorting of documents"
67
  msgstr ""
68
 
69
- #: admin/class-admin.php:165
70
  msgid "Which field to order documents by"
71
  msgstr ""
72
 
73
- #: admin/class-admin.php:178
74
  msgid ""
75
  "Whether matched documents must have all taxa_names (AND) or at least one (OR)"
76
  msgstr ""
77
 
78
- #: admin/class-admin.php:190
79
  msgid "Locally generate thumbnails for audio & video files."
80
  msgstr ""
81
 
82
- #: admin/class-admin.php:203
83
  msgid ""
84
  "Use <a href=\"http://www.ghostscript.com/\" target=\"_blank\">Ghostscript</"
85
  "a> for faster local PDF processing (compared to Imagick)."
86
  msgstr ""
87
 
88
- #: admin/class-admin.php:204
89
  msgid ""
90
  "Your server is not configured to run <a href=\"http://www.ghostscript.com/\" "
91
  "target=\"_blank\">Ghostscript</a>."
92
  msgstr ""
93
 
94
- #: admin/class-admin.php:218
95
  msgid ""
96
  "Use <a href=\"http://www.php.net/manual/en/book.imagick.php\" target=\"_blank"
97
  "\">Imagick</a> to handle lots of filetypes locally."
98
  msgstr ""
99
 
100
- #: admin/class-admin.php:219
101
  msgid ""
102
  "Your server is not configured to run <a href=\"http://www.php.net/manual/en/"
103
  "book.imagick.php\" target=\"_blank\">Imagick</a>."
104
  msgstr ""
105
 
106
- #: admin/class-admin.php:233
107
  msgid ""
108
  "Use <a href=\"https://drive.google.com/viewer\" target=\"_blank\">Google "
109
  "Drive Viewer</a> to generate thumbnails for MS Office files and many other "
110
  "file types remotely."
111
  msgstr ""
112
 
113
- #: admin/class-admin.php:234
114
  msgid "Your server does not allow remote HTTP access."
115
  msgstr ""
116
 
117
- #: admin/class-admin.php:248
118
  msgid "Successfully auto-detected the location of Ghostscript."
119
  msgstr ""
120
 
121
- #: admin/class-admin.php:249
122
  msgid "Failed to auto-detect the location of Ghostscript."
123
  msgstr ""
124
 
125
- #: admin/class-admin.php:257
126
  msgid ""
127
  "The following values will be used by default in the shortcode. You can still "
128
  "manually set each of these values in each individual shortcode."
129
  msgstr ""
130
 
131
- #: admin/class-admin.php:264
132
  msgid "Select which tools to use when generating thumbnails."
133
  msgstr ""
134
 
135
- #: admin/class-admin.php:270
136
  msgid ""
137
  "Enter custom CSS styling for use with document galleries. To see which ids "
138
  "and classes you can style, take a look at <a href=\"%s\" target=\"_blank"
139
  "\">style.css</a>."
140
  msgstr ""
141
 
142
- #: admin/class-admin.php:288
143
  msgid ""
144
  "Unless you <em>really</em> know what you're doing, you should not touch "
145
  "these values."
146
  msgstr ""
147
 
148
- #: admin/class-admin.php:290
149
  msgid ""
150
  "NOTE: <code>exec()</code> is not accessible. Ghostscript will not function."
151
  msgstr ""
152
 
153
- #: admin/class-admin.php:387
154
- msgid "Failed to update CSS file."
155
- msgstr ""
156
-
157
- #: admin/class-admin.php:398
158
  msgid "Invalid Ghostscript path given: "
159
  msgstr ""
160
 
161
- #: inc/class-gallery.php:88
162
  msgid "Generated using Document Gallery. Get yours here: "
163
  msgstr ""
164
 
165
- #: inc/class-gallery.php:91
166
  msgid "No attachments to display. How boring! :("
167
  msgstr ""
168
 
169
- #: inc/class-gallery.php:92
170
  msgid "The %s parameter may only be \"%s\" or \"%s.\" You entered \"%s.\""
171
  msgstr ""
172
 
173
- #: inc/class-gallery.php:263
174
  msgid "The following ID is invalid: "
175
  msgid_plural "The following IDs are invalid: "
176
  msgstr[0] ""
177
  msgstr[1] ""
178
 
179
- #: inc/class-gallery.php:329
180
  msgid "The orderby value entered, \"%s,\" is not valid."
181
  msgstr ""
182
 
183
- #: inc/class-gallery.php:438
184
- msgid "The following attributes are invalid: "
185
  msgstr ""
186
 
187
- #: inc/class-gallery.php:488
188
- msgid "%s is not a valid term name in %s."
189
  msgstr ""
190
 
191
- #: inc/class-thumber.php:131
192
  msgid "Could not open file: "
193
  msgstr ""
194
 
195
- #: inc/class-thumber.php:136
196
  msgid "Could not write file: "
197
  msgstr ""
198
 
199
- #: inc/class-thumber.php:174
200
  msgid "Failed to open file in Imagick: "
201
  msgstr ""
202
 
203
- #: inc/class-thumber.php:184
204
  msgid "Failed to save image in Imagick: "
205
  msgstr ""
206
 
207
- #: inc/class-thumber.php:244
208
  msgid "Ghostscript failed: "
209
  msgstr ""
210
 
211
- #: inc/class-thumber.php:357
212
  msgid "Failed to retrieve thumbnail from Google: "
213
  msgstr ""
214
 
215
- #: inc/class-thumber.php:644
216
  msgid "Failed to get image editor: "
217
  msgstr ""
218
 
219
- #: inc/class-thumber.php:655
220
  msgid "Failed to save image: "
221
  msgstr ""
222
 
2
  # This file is distributed under the same license as the Document Gallery package.
3
  msgid ""
4
  msgstr ""
5
+ "Project-Id-Version: Document Gallery 2.0.3\n"
6
  "Report-Msgid-Bugs-To: http://wordpress.org/tag/document-gallery\n"
7
+ "POT-Creation-Date: 2014-04-01 01:22:00+00:00\n"
8
  "MIME-Version: 1.0\n"
9
  "Content-Type: text/plain; charset=UTF-8\n"
10
  "Content-Transfer-Encoding: 8bit\n"
20
  msgid "Document Gallery Settings"
21
  msgstr ""
22
 
23
+ #. #-#-#-#-# plugin.pot (Document Gallery 2.0.3) #-#-#-#-#
24
  #. Plugin Name of the plugin/theme
25
  #: admin/class-admin.php:38
26
  msgid "Document Gallery"
27
  msgstr ""
28
 
29
+ #: admin/class-admin.php:58
30
  msgid "Default Settings"
31
  msgstr ""
32
 
33
+ #: admin/class-admin.php:62
34
  msgid "Thumbnail Generation"
35
  msgstr ""
36
 
37
+ #: admin/class-admin.php:66
38
  msgid "Custon CSS"
39
  msgstr ""
40
 
41
+ #: admin/class-admin.php:70
42
  msgid "Advanced Thumbnail Generation"
43
  msgstr ""
44
 
45
+ #: admin/class-admin.php:82
46
  msgid "Link to attachment page rather than to file"
47
  msgstr ""
48
 
49
+ #: admin/class-admin.php:94
50
  msgid "Include document descriptions"
51
  msgstr ""
52
 
53
+ #: admin/class-admin.php:106
54
  msgid "Use auto-generated document thumbnails"
55
  msgstr ""
56
 
57
+ #: admin/class-admin.php:118
58
  msgid "Include image attachments in gallery"
59
  msgstr ""
60
 
61
+ #: admin/class-admin.php:130
62
  msgid "Only look for attachments in post where [dg] is used"
63
  msgstr ""
64
 
65
+ #: admin/class-admin.php:143
66
  msgid "Ascending or decending sorting of documents"
67
  msgstr ""
68
 
69
+ #: admin/class-admin.php:156
70
  msgid "Which field to order documents by"
71
  msgstr ""
72
 
73
+ #: admin/class-admin.php:169
74
  msgid ""
75
  "Whether matched documents must have all taxa_names (AND) or at least one (OR)"
76
  msgstr ""
77
 
78
+ #: admin/class-admin.php:181
79
  msgid "Locally generate thumbnails for audio & video files."
80
  msgstr ""
81
 
82
+ #: admin/class-admin.php:194
83
  msgid ""
84
  "Use <a href=\"http://www.ghostscript.com/\" target=\"_blank\">Ghostscript</"
85
  "a> for faster local PDF processing (compared to Imagick)."
86
  msgstr ""
87
 
88
+ #: admin/class-admin.php:195
89
  msgid ""
90
  "Your server is not configured to run <a href=\"http://www.ghostscript.com/\" "
91
  "target=\"_blank\">Ghostscript</a>."
92
  msgstr ""
93
 
94
+ #: admin/class-admin.php:209
95
  msgid ""
96
  "Use <a href=\"http://www.php.net/manual/en/book.imagick.php\" target=\"_blank"
97
  "\">Imagick</a> to handle lots of filetypes locally."
98
  msgstr ""
99
 
100
+ #: admin/class-admin.php:210
101
  msgid ""
102
  "Your server is not configured to run <a href=\"http://www.php.net/manual/en/"
103
  "book.imagick.php\" target=\"_blank\">Imagick</a>."
104
  msgstr ""
105
 
106
+ #: admin/class-admin.php:224
107
  msgid ""
108
  "Use <a href=\"https://drive.google.com/viewer\" target=\"_blank\">Google "
109
  "Drive Viewer</a> to generate thumbnails for MS Office files and many other "
110
  "file types remotely."
111
  msgstr ""
112
 
113
+ #: admin/class-admin.php:225
114
  msgid "Your server does not allow remote HTTP access."
115
  msgstr ""
116
 
117
+ #: admin/class-admin.php:239
118
  msgid "Successfully auto-detected the location of Ghostscript."
119
  msgstr ""
120
 
121
+ #: admin/class-admin.php:240
122
  msgid "Failed to auto-detect the location of Ghostscript."
123
  msgstr ""
124
 
125
+ #: admin/class-admin.php:248
126
  msgid ""
127
  "The following values will be used by default in the shortcode. You can still "
128
  "manually set each of these values in each individual shortcode."
129
  msgstr ""
130
 
131
+ #: admin/class-admin.php:255
132
  msgid "Select which tools to use when generating thumbnails."
133
  msgstr ""
134
 
135
+ #: admin/class-admin.php:261
136
  msgid ""
137
  "Enter custom CSS styling for use with document galleries. To see which ids "
138
  "and classes you can style, take a look at <a href=\"%s\" target=\"_blank"
139
  "\">style.css</a>."
140
  msgstr ""
141
 
142
+ #: admin/class-admin.php:279
143
  msgid ""
144
  "Unless you <em>really</em> know what you're doing, you should not touch "
145
  "these values."
146
  msgstr ""
147
 
148
+ #: admin/class-admin.php:281
149
  msgid ""
150
  "NOTE: <code>exec()</code> is not accessible. Ghostscript will not function."
151
  msgstr ""
152
 
153
+ #: admin/class-admin.php:386
 
 
 
 
154
  msgid "Invalid Ghostscript path given: "
155
  msgstr ""
156
 
157
+ #: inc/class-gallery.php:92
158
  msgid "Generated using Document Gallery. Get yours here: "
159
  msgstr ""
160
 
161
+ #: inc/class-gallery.php:95
162
  msgid "No attachments to display. How boring! :("
163
  msgstr ""
164
 
165
+ #: inc/class-gallery.php:96
166
  msgid "The %s parameter may only be \"%s\" or \"%s.\" You entered \"%s.\""
167
  msgstr ""
168
 
169
+ #: inc/class-gallery.php:267
170
  msgid "The following ID is invalid: "
171
  msgid_plural "The following IDs are invalid: "
172
  msgstr[0] ""
173
  msgstr[1] ""
174
 
175
+ #: inc/class-gallery.php:333
176
  msgid "The orderby value entered, \"%s,\" is not valid."
177
  msgstr ""
178
 
179
+ #: inc/class-gallery.php:475
180
+ msgid "%s is not a valid term name in %s."
181
  msgstr ""
182
 
183
+ #: inc/class-image-editor-imagick.php:37
184
+ msgid "Failed to set Imagick page number"
185
  msgstr ""
186
 
187
+ #: inc/class-thumber.php:125
188
  msgid "Could not open file: "
189
  msgstr ""
190
 
191
+ #: inc/class-thumber.php:130
192
  msgid "Could not write file: "
193
  msgstr ""
194
 
195
+ #: inc/class-thumber.php:166
196
  msgid "Failed to open file in Imagick: "
197
  msgstr ""
198
 
199
+ #: inc/class-thumber.php:176
200
  msgid "Failed to save image in Imagick: "
201
  msgstr ""
202
 
203
+ #: inc/class-thumber.php:234
204
  msgid "Ghostscript failed: "
205
  msgstr ""
206
 
207
+ #: inc/class-thumber.php:350
208
  msgid "Failed to retrieve thumbnail from Google: "
209
  msgstr ""
210
 
211
+ #: inc/class-thumber.php:630
212
  msgid "Failed to get image editor: "
213
  msgstr ""
214
 
215
+ #: inc/class-thumber.php:641
216
  msgid "Failed to save image: "
217
  msgstr ""
218