Gallery Bank: WordPress Photo Gallery Plugin - Version 1.8.3

Version Description

  • Introduced Timthumb for Thumbnails
  • Title Alignment - Fixed.
  • Thumbnails were disorted - Fixed.
Download this release

Release Info

Developer Gallery-Bank
Plugin Icon 128x128 Gallery Bank: WordPress Photo Gallery Plugin
Version 1.8.3
Comparing to
See all releases

Code changes from version 1.8.2 to 1.8.3

css/visuallightbox.css CHANGED
@@ -1,28 +1,3 @@
1
- .imagecontainter {
2
- background: #FFF;
3
- padding: 5px;
4
- margin-bottom: 20px;
5
- border-radius: 5px;
6
- clear: both;
7
- -webkit-border-radius: 5px;
8
- -moz-border-radius: 5px;
9
- border-radius: 5px;
10
- }
11
-
12
- .centered { margin: 0 auto; }
13
-
14
- .imgContainerSingle {
15
- margin: 5px;
16
- padding: 5px;
17
-
18
- font-size: 11px;
19
- line-height: 1.4em;
20
- float: left;
21
- -webkit-border-radius: 5px;
22
- -moz-border-radius: 5px;
23
- border-radius: 5px;
24
- }
25
-
26
  #vlb1overlay{
27
  position:absolute;
28
  top:0;
@@ -30,7 +5,7 @@
30
  z-index:190;
31
  width:100%;
32
  height:auto;
33
- background-color:#ffffff;
34
  }
35
 
36
  #vlb1lightbox{
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  #vlb1overlay{
2
  position:absolute;
3
  top:0;
5
  z-index:190;
6
  width:100%;
7
  height:auto;
8
+ background-color:#000;
9
  }
10
 
11
  #vlb1lightbox{
gallery-bank.php CHANGED
@@ -4,7 +4,7 @@
4
  Plugin URI: http://gallery-bank.com
5
  Description: Gallery Bank is an interactive WordPress photo gallery plugin, best fit for creative and corporate portfolio websites.
6
  Author: Gallery-Bank
7
- Version: 1.8.2
8
  Author URI: http://gallery-bank.com
9
  */
10
  ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4
  Plugin URI: http://gallery-bank.com
5
  Description: Gallery Bank is an interactive WordPress photo gallery plugin, best fit for creative and corporate portfolio websites.
6
  Author: Gallery-Bank
7
+ Version: 1.8.3
8
  Author URI: http://gallery-bank.com
9
  */
10
  ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
images/screenshot.png ADDED
Binary file
install-script.php CHANGED
@@ -17,6 +17,7 @@ if (count($wpdb->get_var('SHOW TABLES LIKE "' . gallery_bank_albums() . '"')) ==
17
  border_color VARCHAR(10) NOT NULL,
18
  slideshow INTEGER(1) NOT NULL,
19
  slideshow_interval INTEGER(5) UNSIGNED NOT NULL,
 
20
  PRIMARY KEY (album_id)
21
  ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE utf8_general_ci';
22
  dbDelta($sql);
@@ -169,13 +170,13 @@ if (count($wpdb->get_var('SHOW TABLES LIKE "' . gallery_bank_albums() . '"')) !=
169
  "SHOW COLUMNS FROM " . gallery_bank_albums() . " LIKE 'images_in_row'",""
170
  )
171
  );
172
- if($check != "")
173
  {
174
  $wpdb->query
175
  (
176
  $wpdb->prepare
177
  (
178
- "ALTER TABLE " . gallery_bank_albums() . " DROP images_in_row",""
179
  )
180
  );
181
  }
17
  border_color VARCHAR(10) NOT NULL,
18
  slideshow INTEGER(1) NOT NULL,
19
  slideshow_interval INTEGER(5) UNSIGNED NOT NULL,
20
+ images_in_row INTEGER(5) UNSIGNED NOT NULL,
21
  PRIMARY KEY (album_id)
22
  ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE utf8_general_ci';
23
  dbDelta($sql);
170
  "SHOW COLUMNS FROM " . gallery_bank_albums() . " LIKE 'images_in_row'",""
171
  )
172
  );
173
+ if($check != "images_in_row")
174
  {
175
  $wpdb->query
176
  (
177
  $wpdb->prepare
178
  (
179
+ "ALTER TABLE " . gallery_bank_albums() . " ADD images_in_row INTEGER(5) NOT NULL",""
180
  )
181
  );
182
  }
js/jquery.masonry.min.js DELETED
@@ -1,203 +0,0 @@
1
-
2
- (function(e, t, n) {"use strict";
3
- var r = t.event, i;
4
- r.special.smartresize = {
5
- setup : function() {
6
- t(this).bind("resize", r.special.smartresize.handler)
7
- },
8
- teardown : function() {
9
- t(this).unbind("resize", r.special.smartresize.handler)
10
- },
11
- handler : function(e, t) {
12
- var n = this, s = arguments;
13
- e.type = "smartresize", i && clearTimeout(i), i = setTimeout(function() {
14
- r.dispatch.apply(n, s)
15
- }, t === "execAsap" ? 0 : 100)
16
- }
17
- }, t.fn.smartresize = function(e) {
18
- return e ? this.bind("smartresize", e) : this.trigger("smartresize", ["execAsap"])
19
- }, t.Mason = function(e, n) {this.element = t(n), this._create(e), this._init()
20
- }, t.Mason.settings = {
21
- isResizable : !0,
22
- isAnimated : !1,
23
- animationOptions : {
24
- queue : !1,
25
- duration : 500
26
- },
27
- gutterWidth : 0,
28
- isRTL : !1,
29
- isFitWidth : !1,
30
- containerStyle : {
31
- position : "relative"
32
- }
33
- }, t.Mason.prototype = {
34
- _filterFindBricks : function(e) {
35
- var t = this.options.itemSelector;
36
- return t ? e.filter(t).add(e.find(t)) : e
37
- },
38
- _getBricks : function(e) {
39
- var t = this._filterFindBricks(e).css({
40
- position : "absolute"
41
- }).addClass("masonry-brick");
42
- return t
43
- },
44
- _create : function(n) {this.options = t.extend(!0, {}, t.Mason.settings, n), this.styleQueue = [];
45
- var r = this.element[0].style;
46
- this.originalStyle = {
47
- height : r.height || ""
48
- };
49
- var i = this.options.containerStyle;
50
- for(var s in i)
51
- this.originalStyle[s] = r[s] || "";
52
- this.element.css(i), this.horizontalDirection = this.options.isRTL ? "right" : "left";
53
- var o = this.element.css("padding-" + this.horizontalDirection), u = this.element.css("padding-top");
54
- this.offset = {
55
- x : o ? parseInt(o, 10) : 0,
56
- y : u ? parseInt(u, 10) : 0
57
- }, this.isFluid = this.options.columnWidth && typeof this.options.columnWidth == "function";
58
- var a = this;
59
- setTimeout(function() {
60
- a.element.addClass("masonry")
61
- }, 0), this.options.isResizable && t(e).bind("smartresize.masonry", function() {
62
- a.resize()
63
- }), this.reloadItems()
64
- },
65
- _init : function(e) {this._getColumns(), this._reLayout(e)
66
- },
67
- option : function(e, n) {t.isPlainObject(e) && (this.options = t.extend(!0, this.options, e))
68
- },
69
- layout : function(e, t) {
70
- for(var n = 0, r = e.length; n < r; n++)
71
- this._placeBrick(e[n]);
72
- var i = {};
73
- i.height = Math.max.apply(Math, this.colYs);
74
- if(this.options.isFitWidth) {
75
- var s = 0;
76
- n = this.cols;
77
- while(--n) {
78
- if(this.colYs[n] !== 0)
79
- break;
80
- s++
81
- }
82
- i.width = (this.cols - s) * this.columnWidth - this.options.gutterWidth
83
- }
84
- this.styleQueue.push({
85
- $el : this.element,
86
- style : i
87
- });
88
- var o = this.isLaidOut ? this.options.isAnimated ? "animate" : "css" : "css", u = this.options.animationOptions, a;
89
- for( n = 0, r = this.styleQueue.length; n < r; n++) a = this.styleQueue[n], a.$el[o](a.style, u);this.styleQueue = [], t && t.call(e), this.isLaidOut = !0
90
- },
91
- _getColumns : function() {
92
- var e = this.options.isFitWidth ? this.element.parent() : this.element, t = e.width();
93
- this.columnWidth = this.isFluid ? this.options.columnWidth(t) : this.options.columnWidth || this.$bricks.outerWidth(!0) || t, this.columnWidth += this.options.gutterWidth, this.cols = Math.floor((t + this.options.gutterWidth) / this.columnWidth), this.cols = Math.max(this.cols, 1)
94
- },
95
- _placeBrick : function(e) {
96
- var n = t(e), r, i, s, o, u;
97
- r = Math.ceil(n.outerWidth(!0) / this.columnWidth), r = Math.min(r, this.cols);
98
- if(r === 1)
99
- s = this.colYs;
100
- else { i = this.cols + 1 - r, s = [];
101
- for( u = 0; u < i; u++) o = this.colYs.slice(u, u + r), s[u] = Math.max.apply(Math, o)
102
- }
103
- var a = Math.min.apply(Math, s), f = 0;
104
- for(var l = 0, c = s.length; l < c; l++)
105
- if(s[l] === a) {
106
- f = l;
107
- break
108
- }
109
- var h = {
110
- top : a + this.offset.y
111
- };
112
- h[this.horizontalDirection] = this.columnWidth * f + this.offset.x, this.styleQueue.push({
113
- $el : n,
114
- style : h
115
- });
116
- var p = a + n.outerHeight(!0), d = this.cols + 1 - c;
117
- for( l = 0; l < d; l++)
118
- this.colYs[f + l] = p
119
- },
120
- resize : function() {
121
- var e = this.cols;
122
- this._getColumns(), (this.isFluid || this.cols !== e) && this._reLayout()
123
- },
124
- _reLayout : function(e) {
125
- var t = this.cols;
126
- this.colYs = [];
127
- while(t--)
128
- this.colYs.push(0);
129
- this.layout(this.$bricks, e)
130
- },
131
- reloadItems : function() {
132
- this.$bricks = this._getBricks(this.element.children())
133
- },
134
- reload : function(e) {this.reloadItems(), this._init(e)
135
- },
136
- appended : function(e, t, n) {
137
- if(t) {
138
- this._filterFindBricks(e).css({
139
- top : this.element.height()
140
- });
141
- var r = this;
142
- setTimeout(function() {
143
- r._appended(e, n)
144
- }, 1)
145
- } else
146
- this._appended(e, n)
147
- },
148
- _appended : function(e, t) {
149
- var n = this._getBricks(e);
150
- this.$bricks = this.$bricks.add(n), this.layout(n, t)
151
- },
152
- remove : function(e) {this.$bricks = this.$bricks.not(e), e.remove()
153
- },
154
- destroy : function() {
155
- this.$bricks.removeClass("masonry-brick").each(function() {this.style.position = "", this.style.top = "", this.style.left = ""
156
- });
157
- var n = this.element[0].style;
158
- for(var r in this.originalStyle)
159
- n[r] = this.originalStyle[r];
160
- this.element.unbind(".masonry").removeClass("masonry").removeData("masonry"), t(e).unbind(".masonry")
161
- }
162
- }, t.fn.imagesLoaded = function(e) {
163
- function u() {
164
- e.call(n, r)
165
- }
166
-
167
- function a(e) {
168
- var n = e.target;
169
- n.src !== s && t.inArray(n, o) === -1 && (o.push(n), --i <= 0 && (setTimeout(u), r.unbind(".imagesLoaded", a)))
170
- }
171
-
172
- var n = this, r = n.find("img").add(n.filter("img")), i = r.length, s = "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///ywAAAAAAQABAAACAUwAOw==", o = [];
173
- return i || u(), r.bind("load.imagesLoaded error.imagesLoaded", a).each(function() {
174
- var e = this.src;
175
- this.src = s, this.src = e
176
- }), n
177
- };
178
- var s = function(t) {
179
- e.console && e.console.error(t)
180
- };
181
- t.fn.masonry = function(e) {
182
- if( typeof e == "string") {
183
- var n = Array.prototype.slice.call(arguments, 1);
184
- this.each(function() {
185
- var r = t.data(this, "masonry");
186
- if(!r) {
187
- s("cannot call methods on masonry prior to initialization; attempted to call method '" + e + "'");
188
- return
189
- }
190
- if(!t.isFunction(r[e]) || e.charAt(0) === "_") {
191
- s("no such method '" + e + "' for masonry instance");
192
- return
193
- }
194
- r[e].apply(r, n)
195
- })
196
- } else
197
- this.each(function() {
198
- var n = t.data(this, "masonry");
199
- n ? (n.option(e || {}), n._init()) : t.data(this, "masonry", new t.Mason(e, this))
200
- });
201
- return this
202
- }
203
- })(window, jQuery);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
lib/album-gallery-bank-class.php CHANGED
@@ -22,13 +22,14 @@ else
22
  $ux_slide_interval = 2;
23
  $ux_slide = 0;
24
  $ux_border = 1;
 
25
  $wpdb->query
26
  (
27
  $wpdb->prepare
28
  (
29
  "INSERT INTO ".gallery_bank_albums()."(album_name,description,image_width,image_height,border_enable,
30
- border_width,border_color,slideshow,slideshow_interval,album_date,author)
31
- VALUES(%s,%s,%d,%d,%d,%d,%s,%d,%d,CURDATE(),%s)",
32
  $ux_album_name,
33
  $ux_desciption,
34
  $ux_image_width,
@@ -38,7 +39,8 @@ else
38
  $ux_border_color,
39
  $ux_slide,
40
  $ux_slide_interval,
41
- $current_user->display_name
 
42
  )
43
  );
44
  echo $EventLastId=$wpdb->insert_id;
@@ -58,6 +60,7 @@ else
58
  $ux_edit_slide_interval = 2;
59
  $ux_edit_slide = 0;
60
  $ux_edit_image_border = 1;
 
61
  $wpdb->query
62
  (
63
  $wpdb->prepare
22
  $ux_slide_interval = 2;
23
  $ux_slide = 0;
24
  $ux_border = 1;
25
+ $images_in_row = 3;
26
  $wpdb->query
27
  (
28
  $wpdb->prepare
29
  (
30
  "INSERT INTO ".gallery_bank_albums()."(album_name,description,image_width,image_height,border_enable,
31
+ border_width,border_color,slideshow,slideshow_interval,album_date,author,images_in_row)
32
+ VALUES(%s,%s,%d,%d,%d,%d,%s,%d,%d,CURDATE(),%s,%d)",
33
  $ux_album_name,
34
  $ux_desciption,
35
  $ux_image_width,
39
  $ux_border_color,
40
  $ux_slide,
41
  $ux_slide_interval,
42
+ $current_user->display_name,
43
+ $images_in_row
44
  )
45
  );
46
  echo $EventLastId=$wpdb->insert_id;
60
  $ux_edit_slide_interval = 2;
61
  $ux_edit_slide = 0;
62
  $ux_edit_image_border = 1;
63
+
64
  $wpdb->query
65
  (
66
  $wpdb->prepare
lib/front-view-album-class.php CHANGED
@@ -21,32 +21,49 @@
21
  $album_id
22
  )
23
  );
 
24
  for ($flag = 0; $flag <count($pic_detail); $flag++)
25
  {
26
  ?>
27
- <div class="imgContainerSingle">
28
  <?php
29
  if($pic_detail[$flag]->description == "")
30
  {
 
 
31
  ?>
32
-
33
- <a class="vlightbox1<?php echo $album_id;?>" id="<?php echo $pic_detail[$flag]->pic_id; ?>" href="<?php echo $pic_detail[$flag]->pic_path; ?>" title="<?php echo $pic_detail[$flag]->title; ?>">
34
- <img src="<?php echo $pic_detail[$flag]->pic_path; ?>" width="150px" /></a>
35
-
36
  <?php
 
 
 
 
 
 
 
 
37
  }
38
  else
39
  {
40
- ?>
41
-
 
 
42
  <a class="vlightbox1<?php echo $album_id;?>" id="<?php echo $pic_detail[$flag]->pic_id; ?>" href="<?php echo $pic_detail[$flag]->pic_path; ?>" title="<?php echo $pic_detail[$flag]->title; ?> (<?php echo $pic_detail[$flag]->description; ?>)">
43
- <img src="<?php echo $pic_detail[$flag]->pic_path; ?>" width="150px" /></a>
44
-
45
- <?php
 
 
 
 
 
 
 
46
  }
47
  ?>
48
  </a>
49
- </div>
50
  <?php
51
  }
52
  ?>
21
  $album_id
22
  )
23
  );
24
+ $row = $album ->images_in_row;
25
  for ($flag = 0; $flag <count($pic_detail); $flag++)
26
  {
27
  ?>
 
28
  <?php
29
  if($pic_detail[$flag]->description == "")
30
  {
31
+ if(($flag % $row ==0) && $flag != 0)
32
+ {
33
  ?>
34
+ <br/>
35
+ <a class="vlightbox1<?php echo $album_id;?>" id="<?php echo $pic_detail[$flag]->pic_id; ?>" href="<?php echo $pic_detail[$flag]->pic_path; ?>" title="<?php echo $pic_detail[$flag]->title; ?>">
36
+ <img style="margin:5px;" src="<?php echo stripcslashes(GALLERY_BK_PLUGIN_URL).'/lib/timthumb.php?src='.stripcslashes($pic_detail[$flag]->pic_path).'&h=150&w=150&zc=1&q=100';?>"/></a>
 
37
  <?php
38
+ }
39
+ else
40
+ {
41
+ ?>
42
+ <a class="vlightbox1<?php echo $album_id;?>" id="<?php echo $pic_detail[$flag]->pic_id; ?>" href="<?php echo $pic_detail[$flag]->pic_path; ?>" title="<?php echo $pic_detail[$flag]->title; ?>">
43
+ <img style="margin:5px;" src="<?php echo stripcslashes(GALLERY_BK_PLUGIN_URL).'/lib/timthumb.php?src='.stripcslashes($pic_detail[$flag]->pic_path).'&h=150&w=150&zc=1&q=100';?>"/></a>
44
+ <?php
45
+ }
46
  }
47
  else
48
  {
49
+ if(($flag % $row ==0) && $flag != 0)
50
+ {
51
+ ?>
52
+ <br/>
53
  <a class="vlightbox1<?php echo $album_id;?>" id="<?php echo $pic_detail[$flag]->pic_id; ?>" href="<?php echo $pic_detail[$flag]->pic_path; ?>" title="<?php echo $pic_detail[$flag]->title; ?> (<?php echo $pic_detail[$flag]->description; ?>)">
54
+ <img style="margin:5px;" src="<?php echo stripcslashes(GALLERY_BK_PLUGIN_URL).'/lib/timthumb.php?src='.stripcslashes($pic_detail[$flag]->pic_path).'&h=150&w=150&zc=1&q=100';?>"/></a>
55
+ <?php
56
+ }
57
+ else
58
+ {
59
+ ?>
60
+ <a class="vlightbox1<?php echo $album_id;?>" id="<?php echo $pic_detail[$flag]->pic_id; ?>" href="<?php echo $pic_detail[$flag]->pic_path; ?>" title="<?php echo $pic_detail[$flag]->title; ?> (<?php echo $pic_detail[$flag]->description; ?>)">
61
+ <img style="margin:5px;" src="<?php echo stripcslashes(GALLERY_BK_PLUGIN_URL).'/lib/timthumb.php?src='.stripcslashes($pic_detail[$flag]->pic_path).'&h=150&w=150&zc=1&q=100';?>"/></a>
62
+ <?php
63
+ }
64
  }
65
  ?>
66
  </a>
 
67
  <?php
68
  }
69
  ?>
lib/gallery-bank-class.php CHANGED
@@ -98,7 +98,6 @@ function frontend_plugin_js_scripts_gallery_bank()
98
  {
99
  wp_enqueue_script('jquery');
100
  wp_enqueue_script('visuallightbox.js', GALLERY_BK_PLUGIN_URL .'/js/visuallightbox.js');
101
- wp_enqueue_script('jquery.masonry.min.js', GALLERY_BK_PLUGIN_URL .'/js/jquery.masonry.min.js');
102
  }
103
 
104
  //--------------------------------------------------------------------------------------------------------------//
98
  {
99
  wp_enqueue_script('jquery');
100
  wp_enqueue_script('visuallightbox.js', GALLERY_BK_PLUGIN_URL .'/js/visuallightbox.js');
 
101
  }
102
 
103
  //--------------------------------------------------------------------------------------------------------------//
lib/timthumb.php ADDED
@@ -0,0 +1,1195 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * TimThumb by Ben Gillbanks and Mark Maunder
4
+ * Based on work done by Tim McDaniels and Darren Hoyt
5
+ * http://code.google.com/p/timthumb/
6
+ *
7
+ * GNU General Public License, version 2
8
+ * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
9
+ *
10
+ * Examples and documentation available on the project homepage
11
+ * http://www.binarymoon.co.uk/projects/timthumb/
12
+ */
13
+
14
+ /*
15
+ -----TimThumb CONFIGURATION-----
16
+ You can either edit the configuration variables manually here, or you can
17
+ create a file called timthumb-config.php and define variables you want
18
+ to customize in there. It will automatically be loaded by timthumb.
19
+ This will save you having to re-edit these variables everytime you download
20
+ a new version of timthumb.
21
+
22
+ */
23
+ define ('VERSION', '2.8.2'); // Version of this script
24
+ //Load a config file if it exists. Otherwise, use the values below
25
+ if( file_exists(dirname(__FILE__) . '/timthumb-config.php')) require_once('timthumb-config.php');
26
+ if(! defined('DEBUG_ON') ) define ('DEBUG_ON', false); // Enable debug logging to web server error log (STDERR)
27
+ if(! defined('DEBUG_LEVEL') ) define ('DEBUG_LEVEL', 1); // Debug level 1 is less noisy and 3 is the most noisy
28
+ if(! defined('MEMORY_LIMIT') ) define ('MEMORY_LIMIT', '30M'); // Set PHP memory limit
29
+ if(! defined('BLOCK_EXTERNAL_LEECHERS') ) define ('BLOCK_EXTERNAL_LEECHERS', false); // If the image or webshot is being loaded on an external site, display a red "No Hotlinking" gif.
30
+
31
+ //Image fetching and caching
32
+ if(! defined('ALLOW_EXTERNAL') ) define ('ALLOW_EXTERNAL', TRUE); // Allow image fetching from external websites. Will check against ALLOWED_SITES if ALLOW_ALL_EXTERNAL_SITES is false
33
+ if(! defined('ALLOW_ALL_EXTERNAL_SITES') ) define ('ALLOW_ALL_EXTERNAL_SITES', false); // Less secure.
34
+ if(! defined('FILE_CACHE_ENABLED') ) define ('FILE_CACHE_ENABLED', TRUE); // Should we store resized/modified images on disk to speed things up?
35
+ if(! defined('FILE_CACHE_TIME_BETWEEN_CLEANS')) define ('FILE_CACHE_TIME_BETWEEN_CLEANS', 86400); // How often the cache is cleaned
36
+ if(! defined('FILE_CACHE_MAX_FILE_AGE') ) define ('FILE_CACHE_MAX_FILE_AGE', 86400); // How old does a file have to be to be deleted from the cache
37
+ if(! defined('FILE_CACHE_SUFFIX') ) define ('FILE_CACHE_SUFFIX', '.timthumb.txt'); // What to put at the end of all files in the cache directory so we can identify them
38
+ if(! defined('FILE_CACHE_DIRECTORY') ) define ('FILE_CACHE_DIRECTORY', './cache'); // Directory where images are cached. Left blank it will use the system temporary directory (which is better for security)
39
+ if(! defined('MAX_FILE_SIZE') ) define ('MAX_FILE_SIZE', 10485760); // 10 Megs is 10485760. This is the max internal or external file size that we'll process.
40
+ if(! defined('CURL_TIMEOUT') ) define ('CURL_TIMEOUT', 20); // Timeout duration for Curl. This only applies if you have Curl installed and aren't using PHP's default URL fetching mechanism.
41
+ if(! defined('WAIT_BETWEEN_FETCH_ERRORS') ) define ('WAIT_BETWEEN_FETCH_ERRORS', 3600); //Time to wait between errors fetching remote file
42
+ //Browser caching
43
+ if(! defined('BROWSER_CACHE_MAX_AGE') ) define ('BROWSER_CACHE_MAX_AGE', 864000); // Time to cache in the browser
44
+ if(! defined('BROWSER_CACHE_DISABLE') ) define ('BROWSER_CACHE_DISABLE', false); // Use for testing if you want to disable all browser caching
45
+
46
+ //Image size and defaults
47
+ if(! defined('MAX_WIDTH') ) define ('MAX_WIDTH', 1500); // Maximum image width
48
+ if(! defined('MAX_HEIGHT') ) define ('MAX_HEIGHT', 1500); // Maximum image height
49
+ if(! defined('NOT_FOUND_IMAGE') ) define ('NOT_FOUND_IMAGE', ''); //Image to serve if any 404 occurs
50
+ if(! defined('ERROR_IMAGE') ) define ('ERROR_IMAGE', ''); //Image to serve if an error occurs instead of showing error message
51
+
52
+ //Image compression is enabled if either of these point to valid paths
53
+
54
+ //These are now disabled by default because the file sizes of PNGs (and GIFs) are much smaller than we used to generate.
55
+ //They only work for PNGs. GIFs and JPEGs are not affected.
56
+ if(! defined('OPTIPNG_ENABLED') ) define ('OPTIPNG_ENABLED', false);
57
+ if(! defined('OPTIPNG_PATH') ) define ('OPTIPNG_PATH', '/usr/bin/optipng'); //This will run first because it gives better compression than pngcrush.
58
+ if(! defined('PNGCRUSH_ENABLED') ) define ('PNGCRUSH_ENABLED', false);
59
+ if(! defined('PNGCRUSH_PATH') ) define ('PNGCRUSH_PATH', '/usr/bin/pngcrush'); //This will only run if OPTIPNG_PATH is not set or is not valid
60
+
61
+ /*
62
+ -------====Website Screenshots configuration - BETA====-------
63
+
64
+ If you just want image thumbnails and don't want website screenshots, you can safely leave this as is.
65
+
66
+ If you would like to get website screenshots set up, you will need root access to your own server.
67
+
68
+ Enable ALLOW_ALL_EXTERNAL_SITES so you can fetch any external web page. This is more secure now that we're using a non-web folder for cache.
69
+ Enable BLOCK_EXTERNAL_LEECHERS so that your site doesn't generate thumbnails for the whole Internet.
70
+
71
+ Instructions to get website screenshots enabled on Ubuntu Linux:
72
+
73
+ 1. Install Xvfb with the following command: sudo apt-get install subversion libqt4-webkit libqt4-dev g++ xvfb
74
+ 2. Go to a directory where you can download some code
75
+ 3. Check-out the latest version of CutyCapt with the following command: svn co https://cutycapt.svn.sourceforge.net/svnroot/cutycapt
76
+ 4. Compile CutyCapt by doing: cd cutycapt/CutyCapt
77
+ 5. qmake
78
+ 6. make
79
+ 7. cp CutyCapt /usr/local/bin/
80
+ 8. Test it by running: xvfb-run --server-args="-screen 0, 1024x768x24" CutyCapt --url="http://markmaunder.com/" --out=test.png
81
+ 9. If you get a file called test.png with something in it, it probably worked. Now test the script by accessing it as follows:
82
+ 10. http://yoursite.com/path/to/timthumb.php?src=http://markmaunder.com/&webshot=1
83
+
84
+ Notes on performance:
85
+ The first time a webshot loads, it will take a few seconds.
86
+ From then on it uses the regular timthumb caching mechanism with the configurable options above
87
+ and loading will be very fast.
88
+
89
+ --ADVANCED USERS ONLY--
90
+ If you'd like a slight speedup (about 25%) and you know Linux, you can run the following command which will keep Xvfb running in the background.
91
+ nohup Xvfb :100 -ac -nolisten tcp -screen 0, 1024x768x24 > /dev/null 2>&1 &
92
+ Then set WEBSHOT_XVFB_RUNNING = true below. This will save your server having to fire off a new Xvfb server and shut it down every time a new shot is generated.
93
+ You will need to take responsibility for keeping Xvfb running in case it crashes. (It seems pretty stable)
94
+ You will also need to take responsibility for server security if you're running Xvfb as root.
95
+
96
+
97
+ */
98
+ if(! defined('WEBSHOT_ENABLED') ) define ('WEBSHOT_ENABLED', false); //Beta feature. Adding webshot=1 to your query string will cause the script to return a browser screenshot rather than try to fetch an image.
99
+ if(! defined('WEBSHOT_CUTYCAPT') ) define ('WEBSHOT_CUTYCAPT', '/usr/local/bin/CutyCapt'); //The path to CutyCapt.
100
+ if(! defined('WEBSHOT_XVFB') ) define ('WEBSHOT_XVFB', '/usr/bin/xvfb-run'); //The path to the Xvfb server
101
+ if(! defined('WEBSHOT_SCREEN_X') ) define ('WEBSHOT_SCREEN_X', '1024'); //1024 works ok
102
+ if(! defined('WEBSHOT_SCREEN_Y') ) define ('WEBSHOT_SCREEN_Y', '768'); //768 works ok
103
+ if(! defined('WEBSHOT_COLOR_DEPTH') ) define ('WEBSHOT_COLOR_DEPTH', '24'); //I haven't tested anything besides 24
104
+ if(! defined('WEBSHOT_IMAGE_FORMAT') ) define ('WEBSHOT_IMAGE_FORMAT', 'png'); //png is about 2.5 times the size of jpg but is a LOT better quality
105
+ if(! defined('WEBSHOT_TIMEOUT') ) define ('WEBSHOT_TIMEOUT', '20'); //Seconds to wait for a webshot
106
+ if(! defined('WEBSHOT_USER_AGENT') ) define ('WEBSHOT_USER_AGENT', "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-GB; rv:1.9.2.18) Gecko/20110614 Firefox/3.6.18"); //I hate to do this, but a non-browser robot user agent might not show what humans see. So we pretend to be Firefox
107
+ if(! defined('WEBSHOT_JAVASCRIPT_ON') ) define ('WEBSHOT_JAVASCRIPT_ON', true); //Setting to false might give you a slight speedup and block ads. But it could cause other issues.
108
+ if(! defined('WEBSHOT_JAVA_ON') ) define ('WEBSHOT_JAVA_ON', false); //Have only tested this as fase
109
+ if(! defined('WEBSHOT_PLUGINS_ON') ) define ('WEBSHOT_PLUGINS_ON', true); //Enable flash and other plugins
110
+ if(! defined('WEBSHOT_PROXY') ) define ('WEBSHOT_PROXY', ''); //In case you're behind a proxy server.
111
+ if(! defined('WEBSHOT_XVFB_RUNNING') ) define ('WEBSHOT_XVFB_RUNNING', false); //ADVANCED: Enable this if you've got Xvfb running in the background.
112
+
113
+
114
+ // If ALLOW_EXTERNAL is true and ALLOW_ALL_EXTERNAL_SITES is false, then external images will only be fetched from these domains and their subdomains.
115
+ if(! isset($ALLOWED_SITES)){
116
+ $ALLOWED_SITES = array ();
117
+ }
118
+ // -------------------------------------------------------------
119
+ // -------------- STOP EDITING CONFIGURATION HERE --------------
120
+ // -------------------------------------------------------------
121
+
122
+ timthumb::start();
123
+
124
+ class timthumb {
125
+ protected $src = "";
126
+ protected $is404 = false;
127
+ protected $docRoot = "";
128
+ protected $lastURLError = false;
129
+ protected $localImage = "";
130
+ protected $localImageMTime = 0;
131
+ protected $url = false;
132
+ protected $myHost = "";
133
+ protected $isURL = false;
134
+ protected $cachefile = '';
135
+ protected $errors = array();
136
+ protected $toDeletes = array();
137
+ protected $cacheDirectory = '';
138
+ protected $startTime = 0;
139
+ protected $lastBenchTime = 0;
140
+ protected $cropTop = false;
141
+ protected $salt = "";
142
+ protected $fileCacheVersion = 1; //Generally if timthumb.php is modifed (upgraded) then the salt changes and all cache files are recreated. This is a backup mechanism to force regen.
143
+ protected $filePrependSecurityBlock = "<?php die('Execution denied!'); //"; //Designed to have three letter mime type, space, question mark and greater than symbol appended. 6 bytes total.
144
+ protected static $curlDataWritten = 0;
145
+ protected static $curlFH = false;
146
+ public static function start(){
147
+ $tim = new timthumb();
148
+ $tim->handleErrors();
149
+ $tim->securityChecks();
150
+ if($tim->tryBrowserCache()){
151
+ exit(0);
152
+ }
153
+ $tim->handleErrors();
154
+ if(FILE_CACHE_ENABLED && $tim->tryServerCache()){
155
+ exit(0);
156
+ }
157
+ $tim->handleErrors();
158
+ $tim->run();
159
+ $tim->handleErrors();
160
+ exit(0);
161
+ }
162
+ public function __construct(){
163
+ global $ALLOWED_SITES;
164
+ $this->startTime = microtime(true);
165
+ date_default_timezone_set('UTC');
166
+ $this->debug(1, "Starting new request from " . $this->getIP() . " to " . $_SERVER['REQUEST_URI']);
167
+ $this->calcDocRoot();
168
+ //On windows systems I'm assuming fileinode returns an empty string or a number that doesn't change. Check this.
169
+ $this->salt = @filemtime(__FILE__) . '-' . @fileinode(__FILE__);
170
+ $this->debug(3, "Salt is: " . $this->salt);
171
+ if(FILE_CACHE_DIRECTORY){
172
+ if(! is_dir(FILE_CACHE_DIRECTORY)){
173
+ @mkdir(FILE_CACHE_DIRECTORY);
174
+ if(! is_dir(FILE_CACHE_DIRECTORY)){
175
+ $this->error("Could not create the file cache directory.");
176
+ return false;
177
+ }
178
+ }
179
+ $this->cacheDirectory = FILE_CACHE_DIRECTORY;
180
+ if (!touch($this->cacheDirectory . '/index.html')) {
181
+ $this->error("Could note create the index.html file.");
182
+ }
183
+ } else {
184
+ $this->cacheDirectory = sys_get_temp_dir();
185
+ }
186
+ //Clean the cache before we do anything because we don't want the first visitor after FILE_CACHE_TIME_BETWEEN_CLEANS expires to get a stale image.
187
+ $this->cleanCache();
188
+
189
+ $this->myHost = preg_replace('/^www\./i', '', $_SERVER['HTTP_HOST']);
190
+ $this->src = $this->param('src');
191
+ $this->url = parse_url($this->src);
192
+ if(strlen($this->src) <= 3){
193
+ $this->error("No image specified");
194
+ return false;
195
+ }
196
+ if(BLOCK_EXTERNAL_LEECHERS && array_key_exists('HTTP_REFERER', $_SERVER) && (! preg_match('/^https?:\/\/(?:www\.)?' . $this->myHost . '(?:$|\/)/i', $_SERVER['HTTP_REFERER']))){
197
+ // base64 encoded red image that says 'no hotlinkers'
198
+ // nothing to worry about! :)
199
+ $imgData = base64_decode("R0lGODlhUAAMAIAAAP8AAP///yH5BAAHAP8ALAAAAABQAAwAAAJpjI+py+0Po5y0OgAMjjv01YUZ\nOGplhWXfNa6JCLnWkXplrcBmW+spbwvaVr/cDyg7IoFC2KbYVC2NQ5MQ4ZNao9Ynzjl9ScNYpneb\nDULB3RP6JuPuaGfuuV4fumf8PuvqFyhYtjdoeFgAADs=");
200
+ header('Content-Type: image/gif');
201
+ header('Content-Length: ' . sizeof($imgData));
202
+ header('Cache-Control: no-store, no-cache, must-revalidate, max-age=0');
203
+ header("Pragma: no-cache");
204
+ header('Expires: ' . gmdate ('D, d M Y H:i:s', time()));
205
+ echo $imgData;
206
+ return false;
207
+ exit(0);
208
+ }
209
+ if(preg_match('/https?:\/\/(?:www\.)?' . $this->myHost . '(?:$|\/)/i', $this->src)){
210
+ $this->src = preg_replace('/https?:\/\/(?:www\.)?' . $this->myHost . '/i', '', $this->src);
211
+ }
212
+ if(preg_match('/^https?:\/\/[^\/]+/i', $this->src)){
213
+ $this->debug(2, "Is a request for an external URL: " . $this->src);
214
+ $this->isURL = true;
215
+ } else {
216
+ $this->debug(2, "Is a request for an internal file: " . $this->src);
217
+ }
218
+ if($this->isURL && (! ALLOW_EXTERNAL)){
219
+ $this->error("You are not allowed to fetch images from an external website.");
220
+ return false;
221
+ }
222
+ if($this->isURL){
223
+ if(ALLOW_ALL_EXTERNAL_SITES){
224
+ $this->debug(2, "Fetching from all external sites is enabled.");
225
+ } else {
226
+ $this->debug(2, "Fetching only from selected external sites is enabled.");
227
+ $allowed = false;
228
+ foreach($ALLOWED_SITES as $site){
229
+ if ((strtolower(substr($this->url['host'],-strlen($site)-1)) === strtolower(".$site")) || (strtolower($this->url['host'])===strtolower($site))) {
230
+ $this->debug(3, "URL hostname {$this->url['host']} matches $site so allowing.");
231
+ $allowed = true;
232
+ }
233
+ }
234
+ if(! $allowed){
235
+ return $this->error("You may not fetch images from that site. To enable this site in timthumb, you can either add it to \$ALLOWED_SITES and set ALLOW_EXTERNAL=true. Or you can set ALLOW_ALL_EXTERNAL_SITES=true, depending on your security needs.");
236
+ }
237
+ }
238
+ }
239
+
240
+ $cachePrefix = ($this->isURL ? 'timthumb_ext_' : 'timthumb_int_');
241
+ if($this->isURL){
242
+ $this->cachefile = $this->cacheDirectory . '/' . $cachePrefix . md5($this->salt . $_SERVER ['QUERY_STRING'] . $this->fileCacheVersion) . FILE_CACHE_SUFFIX;
243
+ } else {
244
+ $this->localImage = $this->getLocalImagePath($this->src);
245
+ if(! $this->localImage){
246
+ $this->debug(1, "Could not find the local image: {$this->localImage}");
247
+ $this->error("Could not find the internal image you specified.");
248
+ $this->set404();
249
+ return false;
250
+ }
251
+ $this->debug(1, "Local image path is {$this->localImage}");
252
+ $this->localImageMTime = @filemtime($this->localImage);
253
+ //We include the mtime of the local file in case in changes on disk.
254
+ $this->cachefile = $this->cacheDirectory . '/' . $cachePrefix . md5($this->salt . $this->localImageMTime . $_SERVER ['QUERY_STRING'] . $this->fileCacheVersion) . FILE_CACHE_SUFFIX;
255
+ }
256
+ $this->debug(2, "Cache file is: " . $this->cachefile);
257
+
258
+ return true;
259
+ }
260
+ public function __destruct(){
261
+ foreach($this->toDeletes as $del){
262
+ $this->debug(2, "Deleting temp file $del");
263
+ @unlink($del);
264
+ }
265
+ }
266
+ public function run(){
267
+ if($this->isURL){
268
+ if(! ALLOW_EXTERNAL){
269
+ $this->debug(1, "Got a request for an external image but ALLOW_EXTERNAL is disabled so returning error msg.");
270
+ $this->error("You are not allowed to fetch images from an external website.");
271
+ return false;
272
+ }
273
+ $this->debug(3, "Got request for external image. Starting serveExternalImage.");
274
+ if($this->param('webshot')){
275
+ if(WEBSHOT_ENABLED){
276
+ $this->debug(3, "webshot param is set, so we're going to take a webshot.");
277
+ $this->serveWebshot();
278
+ } else {
279
+ $this->error("You added the webshot parameter but webshots are disabled on this server. You need to set WEBSHOT_ENABLED == true to enable webshots.");
280
+ }
281
+ } else {
282
+ $this->debug(3, "webshot is NOT set so we're going to try to fetch a regular image.");
283
+ $this->serveExternalImage();
284
+
285
+ }
286
+ } else {
287
+ $this->debug(3, "Got request for internal image. Starting serveInternalImage()");
288
+ $this->serveInternalImage();
289
+ }
290
+ return true;
291
+ }
292
+ protected function handleErrors(){
293
+ if($this->haveErrors()){
294
+ if(NOT_FOUND_IMAGE && $this->is404()){
295
+ if($this->serveImg(NOT_FOUND_IMAGE)){
296
+ exit(0);
297
+ } else {
298
+ $this->error("Additionally, the 404 image that is configured could not be found or there was an error serving it.");
299
+ }
300
+ }
301
+ if(ERROR_IMAGE){
302
+ if($this->serveImg(ERROR_IMAGE)){
303
+ exit(0);
304
+ } else {
305
+ $this->error("Additionally, the error image that is configured could not be found or there was an error serving it.");
306
+ }
307
+ }
308
+
309
+ $this->serveErrors();
310
+ exit(0);
311
+ }
312
+ return false;
313
+ }
314
+ protected function tryBrowserCache(){
315
+ if(BROWSER_CACHE_DISABLE){ $this->debug(3, "Browser caching is disabled"); return false; }
316
+ if(!empty($_SERVER['HTTP_IF_MODIFIED_SINCE']) ){
317
+ $this->debug(3, "Got a conditional get");
318
+ $mtime = false;
319
+ //We've already checked if the real file exists in the constructor
320
+ if(! is_file($this->cachefile)){
321
+ //If we don't have something cached, regenerate the cached image.
322
+ return false;
323
+ }
324
+ if($this->localImageMTime){
325
+ $mtime = $this->localImageMTime;
326
+ $this->debug(3, "Local real file's modification time is $mtime");
327
+ } else if(is_file($this->cachefile)){ //If it's not a local request then use the mtime of the cached file to determine the 304
328
+ $mtime = @filemtime($this->cachefile);
329
+ $this->debug(3, "Cached file's modification time is $mtime");
330
+ }
331
+ if(! $mtime){ return false; }
332
+
333
+ $iftime = strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']);
334
+ $this->debug(3, "The conditional get's if-modified-since unixtime is $iftime");
335
+ if($iftime < 1){
336
+ $this->debug(3, "Got an invalid conditional get modified since time. Returning false.");
337
+ return false;
338
+ }
339
+ if($iftime < $mtime){ //Real file or cache file has been modified since last request, so force refetch.
340
+ $this->debug(3, "File has been modified since last fetch.");
341
+ return false;
342
+ } else { //Otherwise serve a 304
343
+ $this->debug(3, "File has not been modified since last get, so serving a 304.");
344
+ header ($_SERVER['SERVER_PROTOCOL'] . ' 304 Not Modified');
345
+ $this->debug(1, "Returning 304 not modified");
346
+ return true;
347
+ }
348
+ }
349
+ return false;
350
+ }
351
+ protected function tryServerCache(){
352
+ $this->debug(3, "Trying server cache");
353
+ if(file_exists($this->cachefile)){
354
+ $this->debug(3, "Cachefile {$this->cachefile} exists");
355
+ if($this->isURL){
356
+ $this->debug(3, "This is an external request, so checking if the cachefile is empty which means the request failed previously.");
357
+ if(filesize($this->cachefile) < 1){
358
+ $this->debug(3, "Found an empty cachefile indicating a failed earlier request. Checking how old it is.");
359
+ //Fetching error occured previously
360
+ if(time() - @filemtime($this->cachefile) > WAIT_BETWEEN_FETCH_ERRORS){
361
+ $this->debug(3, "File is older than " . WAIT_BETWEEN_FETCH_ERRORS . " seconds. Deleting and returning false so app can try and load file.");
362
+ @unlink($this->cachefile);
363
+ return false; //to indicate we didn't serve from cache and app should try and load
364
+ } else {
365
+ $this->debug(3, "Empty cachefile is still fresh so returning message saying we had an error fetching this image from remote host.");
366
+ $this->set404();
367
+ $this->error("An error occured fetching image.");
368
+ return false;
369
+ }
370
+ }
371
+ } else {
372
+ $this->debug(3, "Trying to serve cachefile {$this->cachefile}");
373
+ }
374
+ if($this->serveCacheFile()){
375
+ $this->debug(3, "Succesfully served cachefile {$this->cachefile}");
376
+ return true;
377
+ } else {
378
+ $this->debug(3, "Failed to serve cachefile {$this->cachefile} - Deleting it from cache.");
379
+ //Image serving failed. We can't retry at this point, but lets remove it from cache so the next request recreates it
380
+ @unlink($this->cachefile);
381
+ return true;
382
+ }
383
+ }
384
+ }
385
+ protected function error($err){
386
+ $this->debug(3, "Adding error message: $err");
387
+ $this->errors[] = $err;
388
+ return false;
389
+
390
+ }
391
+ protected function haveErrors(){
392
+ if(sizeof($this->errors) > 0){
393
+ return true;
394
+ }
395
+ return false;
396
+ }
397
+ protected function serveErrors(){
398
+ $html = '<ul>';
399
+ foreach($this->errors as $err){
400
+ $html .= '<li>' . htmlentities($err) . '</li>';
401
+ }
402
+ $html .= '</ul>';
403
+ header ($_SERVER['SERVER_PROTOCOL'] . ' 400 Bad Request');
404
+ echo '<h1>A TimThumb error has occured</h1>The following error(s) occured:<br />' . $html . '<br />';
405
+ echo '<br />Query String : ' . htmlentities ($_SERVER['QUERY_STRING']);
406
+ echo '<br />TimThumb version : ' . VERSION . '</pre>';
407
+ }
408
+ protected function serveInternalImage(){
409
+ $this->debug(3, "Local image path is $this->localImage");
410
+ if(! $this->localImage){
411
+ $this->sanityFail("localImage not set after verifying it earlier in the code.");
412
+ return false;
413
+ }
414
+ $fileSize = filesize($this->localImage);
415
+ if($fileSize > MAX_FILE_SIZE){
416
+ $this->error("The file you specified is greater than the maximum allowed file size.");
417
+ return false;
418
+ }
419
+ if($fileSize <= 0){
420
+ $this->error("The file you specified is <= 0 bytes.");
421
+ return false;
422
+ }
423
+ $this->debug(3, "Calling processImageAndWriteToCache() for local image.");
424
+ if($this->processImageAndWriteToCache($this->localImage)){
425
+ $this->serveCacheFile();
426
+ return true;
427
+ } else {
428
+ return false;
429
+ }
430
+ }
431
+ protected function cleanCache(){
432
+ $this->debug(3, "cleanCache() called");
433
+ $lastCleanFile = $this->cacheDirectory . '/timthumb_cacheLastCleanTime.touch';
434
+
435
+ //If this is a new timthumb installation we need to create the file
436
+ if(! is_file($lastCleanFile)){
437
+ $this->debug(1, "File tracking last clean doesn't exist. Creating $lastCleanFile");
438
+ if (!touch($lastCleanFile)) {
439
+ $this->error("Could note create cache clean timestamp file.");
440
+ }
441
+ return;
442
+ }
443
+ if(@filemtime($lastCleanFile) < (time() - FILE_CACHE_TIME_BETWEEN_CLEANS) ){ //Cache was last cleaned more than 1 day ago
444
+ $this->debug(1, "Cache was last cleaned more than " . FILE_CACHE_TIME_BETWEEN_CLEANS . " seconds ago. Cleaning now.");
445
+ // Very slight race condition here, but worst case we'll have 2 or 3 servers cleaning the cache simultaneously once a day.
446
+ if (!touch($lastCleanFile)) {
447
+ $this->error("Could note create cache clean timestamp file.");
448
+ }
449
+ $files = glob($this->cacheDirectory . '/*' . FILE_CACHE_SUFFIX);
450
+ $timeAgo = time() - FILE_CACHE_MAX_FILE_AGE;
451
+ foreach($files as $file){
452
+ if(@filemtime($file) < $timeAgo){
453
+ $this->debug(3, "Deleting cache file $file older than max age: " . FILE_CACHE_MAX_FILE_AGE . " seconds");
454
+ @unlink($file);
455
+ }
456
+ }
457
+ return true;
458
+ } else {
459
+ $this->debug(3, "Cache was cleaned less than " . FILE_CACHE_TIME_BETWEEN_CLEANS . " seconds ago so no cleaning needed.");
460
+ }
461
+ return false;
462
+ }
463
+ protected function processImageAndWriteToCache($localImage){
464
+ $sData = getimagesize($localImage);
465
+ $origType = $sData[2];
466
+ $mimeType = $sData['mime'];
467
+
468
+ $this->debug(3, "Mime type of image is $mimeType");
469
+ if(! preg_match('/^image\/(?:gif|jpg|jpeg|png)$/i', $mimeType)){
470
+ return $this->error("The image being resized is not a valid gif, jpg or png.");
471
+ }
472
+
473
+ if (!function_exists ('imagecreatetruecolor')) {
474
+ return $this->error('GD Library Error: imagecreatetruecolor does not exist - please contact your webhost and ask them to install the GD library');
475
+ }
476
+
477
+ if (function_exists ('imagefilter') && defined ('IMG_FILTER_NEGATE')) {
478
+ $imageFilters = array (
479
+ 1 => array (IMG_FILTER_NEGATE, 0),
480
+ 2 => array (IMG_FILTER_GRAYSCALE, 0),
481
+ 3 => array (IMG_FILTER_BRIGHTNESS, 1),
482
+ 4 => array (IMG_FILTER_CONTRAST, 1),
483
+ 5 => array (IMG_FILTER_COLORIZE, 4),
484
+ 6 => array (IMG_FILTER_EDGEDETECT, 0),
485
+ 7 => array (IMG_FILTER_EMBOSS, 0),
486
+ 8 => array (IMG_FILTER_GAUSSIAN_BLUR, 0),
487
+ 9 => array (IMG_FILTER_SELECTIVE_BLUR, 0),
488
+ 10 => array (IMG_FILTER_MEAN_REMOVAL, 0),
489
+ 11 => array (IMG_FILTER_SMOOTH, 0),
490
+ );
491
+ }
492
+
493
+ // get standard input properties
494
+ $new_width = (int) abs ($this->param('w', 0));
495
+ $new_height = (int) abs ($this->param('h', 0));
496
+ $zoom_crop = (int) $this->param('zc', 1);
497
+ $quality = (int) abs ($this->param('q', 90));
498
+ $align = $this->cropTop ? 't' : $this->param('a', 'c');
499
+ $filters = $this->param('f', '');
500
+ $sharpen = (bool) $this->param('s', 0);
501
+ $canvas_color = $this->param('cc', 'ffffff');
502
+
503
+ // set default width and height if neither are set already
504
+ if ($new_width == 0 && $new_height == 0) {
505
+ $new_width = 100;
506
+ $new_height = 100;
507
+ }
508
+
509
+ // ensure size limits can not be abused
510
+ $new_width = min ($new_width, MAX_WIDTH);
511
+ $new_height = min ($new_height, MAX_HEIGHT);
512
+
513
+ // set memory limit to be able to have enough space to resize larger images
514
+ $this->setMemoryLimit();
515
+
516
+ // open the existing image
517
+ $image = $this->openImage ($mimeType, $localImage);
518
+ if ($image === false) {
519
+ return $this->error('Unable to open image.');
520
+ }
521
+
522
+ // Get original width and height
523
+ $width = imagesx ($image);
524
+ $height = imagesy ($image);
525
+ $origin_x = 0;
526
+ $origin_y = 0;
527
+
528
+ // generate new w/h if not provided
529
+ if ($new_width && !$new_height) {
530
+ $new_height = floor ($height * ($new_width / $width));
531
+ } else if ($new_height && !$new_width) {
532
+ $new_width = floor ($width * ($new_height / $height));
533
+ }
534
+
535
+ // scale down and add borders
536
+ if ($zoom_crop == 3) {
537
+
538
+ $final_height = $height * ($new_width / $width);
539
+
540
+ if ($final_height > $new_height) {
541
+ $new_width = $width * ($new_height / $height);
542
+ } else {
543
+ $new_height = $final_height;
544
+ }
545
+
546
+ }
547
+
548
+ // create a new true color image
549
+ $canvas = imagecreatetruecolor ($new_width, $new_height);
550
+ imagealphablending ($canvas, false);
551
+
552
+ if (strlen ($canvas_color) < 6) {
553
+ $canvas_color = 'ffffff';
554
+ }
555
+
556
+ $canvas_color_R = hexdec (substr ($canvas_color, 0, 2));
557
+ $canvas_color_G = hexdec (substr ($canvas_color, 2, 2));
558
+ $canvas_color_B = hexdec (substr ($canvas_color, 2, 2));
559
+
560
+ // Create a new transparent color for image
561
+ $color = imagecolorallocatealpha ($canvas, $canvas_color_R, $canvas_color_G, $canvas_color_B, 127);
562
+
563
+ // Completely fill the background of the new image with allocated color.
564
+ imagefill ($canvas, 0, 0, $color);
565
+
566
+ // scale down and add borders
567
+ if ($zoom_crop == 2) {
568
+
569
+ $final_height = $height * ($new_width / $width);
570
+
571
+ if ($final_height > $new_height) {
572
+
573
+ $origin_x = $new_width / 2;
574
+ $new_width = $width * ($new_height / $height);
575
+ $origin_x = round ($origin_x - ($new_width / 2));
576
+
577
+ } else {
578
+
579
+ $origin_y = $new_height / 2;
580
+ $new_height = $final_height;
581
+ $origin_y = round ($origin_y - ($new_height / 2));
582
+
583
+ }
584
+
585
+ }
586
+
587
+ // Restore transparency blending
588
+ imagesavealpha ($canvas, true);
589
+
590
+ if ($zoom_crop > 0) {
591
+
592
+ $src_x = $src_y = 0;
593
+ $src_w = $width;
594
+ $src_h = $height;
595
+
596
+ $cmp_x = $width / $new_width;
597
+ $cmp_y = $height / $new_height;
598
+
599
+ // calculate x or y coordinate and width or height of source
600
+ if ($cmp_x > $cmp_y) {
601
+
602
+ $src_w = round ($width / $cmp_x * $cmp_y);
603
+ $src_x = round (($width - ($width / $cmp_x * $cmp_y)) / 2);
604
+
605
+ } else if ($cmp_y > $cmp_x) {
606
+
607
+ $src_h = round ($height / $cmp_y * $cmp_x);
608
+ $src_y = round (($height - ($height / $cmp_y * $cmp_x)) / 2);
609
+
610
+ }
611
+
612
+ // positional cropping!
613
+ if ($align) {
614
+ if (strpos ($align, 't') !== false) {
615
+ $src_y = 0;
616
+ }
617
+ if (strpos ($align, 'b') !== false) {
618
+ $src_y = $height - $src_h;
619
+ }
620
+ if (strpos ($align, 'l') !== false) {
621
+ $src_x = 0;
622
+ }
623
+ if (strpos ($align, 'r') !== false) {
624
+ $src_x = $width - $src_w;
625
+ }
626
+ }
627
+
628
+ imagecopyresampled ($canvas, $image, $origin_x, $origin_y, $src_x, $src_y, $new_width, $new_height, $src_w, $src_h);
629
+
630
+ } else {
631
+
632
+ // copy and resize part of an image with resampling
633
+ imagecopyresampled ($canvas, $image, 0, 0, 0, 0, $new_width, $new_height, $width, $height);
634
+
635
+ }
636
+
637
+ if ($filters != '' && function_exists ('imagefilter') && defined ('IMG_FILTER_NEGATE')) {
638
+ // apply filters to image
639
+ $filterList = explode ('|', $filters);
640
+ foreach ($filterList as $fl) {
641
+
642
+ $filterSettings = explode (',', $fl);
643
+ if (isset ($imageFilters[$filterSettings[0]])) {
644
+
645
+ for ($i = 0; $i < 4; $i ++) {
646
+ if (!isset ($filterSettings[$i])) {
647
+ $filterSettings[$i] = null;
648
+ } else {
649
+ $filterSettings[$i] = (int) $filterSettings[$i];
650
+ }
651
+ }
652
+
653
+ switch ($imageFilters[$filterSettings[0]][1]) {
654
+
655
+ case 1:
656
+
657
+ imagefilter ($canvas, $imageFilters[$filterSettings[0]][0], $filterSettings[1]);
658
+ break;
659
+
660
+ case 2:
661
+
662
+ imagefilter ($canvas, $imageFilters[$filterSettings[0]][0], $filterSettings[1], $filterSettings[2]);
663
+ break;
664
+
665
+ case 3:
666
+
667
+ imagefilter ($canvas, $imageFilters[$filterSettings[0]][0], $filterSettings[1], $filterSettings[2], $filterSettings[3]);
668
+ break;
669
+
670
+ case 4:
671
+
672
+ imagefilter ($canvas, $imageFilters[$filterSettings[0]][0], $filterSettings[1], $filterSettings[2], $filterSettings[3], $filterSettings[4]);
673
+ break;
674
+
675
+ default:
676
+
677
+ imagefilter ($canvas, $imageFilters[$filterSettings[0]][0]);
678
+ break;
679
+
680
+ }
681
+ }
682
+ }
683
+ }
684
+
685
+ // sharpen image
686
+ if ($sharpen && function_exists ('imageconvolution')) {
687
+
688
+ $sharpenMatrix = array (
689
+ array (-1,-1,-1),
690
+ array (-1,16,-1),
691
+ array (-1,-1,-1),
692
+ );
693
+
694
+ $divisor = 8;
695
+ $offset = 0;
696
+
697
+ imageconvolution ($canvas, $sharpenMatrix, $divisor, $offset);
698
+
699
+ }
700
+ //Straight from Wordpress core code. Reduces filesize by up to 70% for PNG's
701
+ if ( (IMAGETYPE_PNG == $origType || IMAGETYPE_GIF == $origType) && function_exists('imageistruecolor') && !imageistruecolor( $image ) && imagecolortransparent( $image ) > 0 ){
702
+ imagetruecolortopalette( $canvas, false, imagecolorstotal( $image ) );
703
+ }
704
+
705
+ $imgType = "";
706
+ $tempfile = tempnam($this->cacheDirectory, 'timthumb_tmpimg_');
707
+ if(preg_match('/^image\/(?:jpg|jpeg)$/i', $mimeType)){
708
+ $imgType = 'jpg';
709
+ imagejpeg($canvas, $tempfile, $quality);
710
+ } else if(preg_match('/^image\/png$/i', $mimeType)){
711
+ $imgType = 'png';
712
+ imagepng($canvas, $tempfile, floor($quality * 0.09));
713
+ } else if(preg_match('/^image\/gif$/i', $mimeType)){
714
+ $imgType = 'gif';
715
+ imagegif($canvas, $tempfile);
716
+ } else {
717
+ return $this->sanityFail("Could not match mime type after verifying it previously.");
718
+ }
719
+
720
+ if($imgType == 'png' && OPTIPNG_ENABLED && OPTIPNG_PATH && @is_file(OPTIPNG_PATH)){
721
+ $exec = OPTIPNG_PATH;
722
+ $this->debug(3, "optipng'ing $tempfile");
723
+ $presize = filesize($tempfile);
724
+ $out = `$exec -o1 $tempfile`; //you can use up to -o7 but it really slows things down
725
+ clearstatcache();
726
+ $aftersize = filesize($tempfile);
727
+ $sizeDrop = $presize - $aftersize;
728
+ if($sizeDrop > 0){
729
+ $this->debug(1, "optipng reduced size by $sizeDrop");
730
+ } else if($sizeDrop < 0){
731
+ $this->debug(1, "optipng increased size! Difference was: $sizeDrop");
732
+ } else {
733
+ $this->debug(1, "optipng did not change image size.");
734
+ }
735
+ } else if($imgType == 'png' && PNGCRUSH_ENABLED && PNGCRUSH_PATH && @is_file(PNGCRUSH_PATH)){
736
+ $exec = PNGCRUSH_PATH;
737
+ $tempfile2 = tempnam($this->cacheDirectory, 'timthumb_tmpimg_');
738
+ $this->debug(3, "pngcrush'ing $tempfile to $tempfile2");
739
+ $out = `$exec $tempfile $tempfile2`;
740
+ $todel = "";
741
+ if(is_file($tempfile2)){
742
+ $sizeDrop = filesize($tempfile) - filesize($tempfile2);
743
+ if($sizeDrop > 0){
744
+ $this->debug(1, "pngcrush was succesful and gave a $sizeDrop byte size reduction");
745
+ $todel = $tempfile;
746
+ $tempfile = $tempfile2;
747
+ } else {
748
+ $this->debug(1, "pngcrush did not reduce file size. Difference was $sizeDrop bytes.");
749
+ $todel = $tempfile2;
750
+ }
751
+ } else {
752
+ $this->debug(3, "pngcrush failed with output: $out");
753
+ $todel = $tempfile2;
754
+ }
755
+ @unlink($todel);
756
+ }
757
+
758
+ $this->debug(3, "Rewriting image with security header.");
759
+ $tempfile4 = tempnam($this->cacheDirectory, 'timthumb_tmpimg_');
760
+ $context = stream_context_create ();
761
+ $fp = fopen($tempfile,'r',0,$context);
762
+ file_put_contents($tempfile4, $this->filePrependSecurityBlock . $imgType . ' ?' . '>'); //6 extra bytes, first 3 being image type
763
+ file_put_contents($tempfile4, $fp, FILE_APPEND);
764
+ fclose($fp);
765
+ @unlink($tempfile);
766
+ $this->debug(3, "Locking and replacing cache file.");
767
+ $lockFile = $this->cachefile . '.lock';
768
+ $fh = fopen($lockFile, 'w');
769
+ if(! $fh){
770
+ return $this->error("Could not open the lockfile for writing an image.");
771
+ }
772
+ if(flock($fh, LOCK_EX)){
773
+ @unlink($this->cachefile); //rename generally overwrites, but doing this in case of platform specific quirks. File might not exist yet.
774
+ rename($tempfile4, $this->cachefile);
775
+ flock($fh, LOCK_UN);
776
+ fclose($fh);
777
+ @unlink($lockFile);
778
+ } else {
779
+ fclose($fh);
780
+ @unlink($lockFile);
781
+ @unlink($tempfile4);
782
+ return $this->error("Could not get a lock for writing.");
783
+ }
784
+ $this->debug(3, "Done image replace with security header. Cleaning up and running cleanCache()");
785
+ imagedestroy($canvas);
786
+ imagedestroy($image);
787
+ return true;
788
+ }
789
+ protected function calcDocRoot(){
790
+ $docRoot = @$_SERVER['DOCUMENT_ROOT'];
791
+ if(!isset($docRoot)){
792
+ $this->debug(3, "DOCUMENT_ROOT is not set. This is probably windows. Starting search 1.");
793
+ if(isset($_SERVER['SCRIPT_FILENAME'])){
794
+ $docRoot = str_replace( '\\', '/', substr($_SERVER['SCRIPT_FILENAME'], 0, 0-strlen($_SERVER['PHP_SELF'])));
795
+ $this->debug(3, "Generated docRoot using SCRIPT_FILENAME and PHP_SELF as: $docRoot");
796
+ }
797
+ }
798
+ if(!isset($docRoot)){
799
+ $this->debug(3, "DOCUMENT_ROOT still is not set. Starting search 2.");
800
+ if(isset($_SERVER['PATH_TRANSLATED'])){
801
+ $docRoot = str_replace( '\\', '/', substr(str_replace('\\\\', '\\', $_SERVER['PATH_TRANSLATED']), 0, 0-strlen($_SERVER['PHP_SELF'])));
802
+ $this->debug(3, "Generated docRoot using PATH_TRANSLATED and PHP_SELF as: $docRoot");
803
+ }
804
+ }
805
+ if($docRoot && $_SERVER['DOCUMENT_ROOT'] != '/'){ $docRoot = preg_replace('/\/$/', '', $docRoot); }
806
+ $this->debug(3, "Doc root is: " . $docRoot);
807
+ $this->docRoot = $docRoot;
808
+
809
+ }
810
+ protected function getLocalImagePath($src){
811
+ $src = preg_replace('/^\//', '', $src); //strip off the leading '/'
812
+ $realDocRoot = realpath($this->docRoot);
813
+ if(! $this->docRoot){
814
+ $this->debug(3, "We have no document root set, so as a last resort, lets check if the image is in the current dir and serve that.");
815
+ //We don't support serving images outside the current dir if we don't have a doc root for security reasons.
816
+ $file = preg_replace('/^.*?([^\/\\\\]+)$/', '$1', $src); //strip off any path info and just leave the filename.
817
+ if(is_file($file)){
818
+ return realpath($file);
819
+ }
820
+ return $this->error("Could not find your website document root and the file specified doesn't exist in timthumbs directory. We don't support serving files outside timthumb's directory without a document root for security reasons.");
821
+ } //Do not go past this point without docRoot set
822
+
823
+ //Try src under docRoot
824
+ if(file_exists ($this->docRoot . '/' . $src)) {
825
+ $this->debug(3, "Found file as " . $this->docRoot . '/' . $src);
826
+ $real = realpath($this->docRoot . '/' . $src);
827
+ if(stripos($real, $realDocRoot) === 0){
828
+ return $real;
829
+ } else {
830
+ $this->debug(1, "Security block: The file specified occurs outside the document root.");
831
+ //allow search to continue
832
+ }
833
+ }
834
+ //Check absolute paths and then verify the real path is under doc root
835
+ $absolute = realpath('/' . $src);
836
+ if($absolute && file_exists($absolute)){ //realpath does file_exists check, so can probably skip the exists check here
837
+ $this->debug(3, "Found absolute path: $absolute");
838
+ if(! $this->docRoot){ $this->sanityFail("docRoot not set when checking absolute path."); }
839
+ if(stripos($absolute, $realDocRoot) === 0){
840
+ return $absolute;
841
+ } else {
842
+ $this->debug(1, "Security block: The file specified occurs outside the document root.");
843
+ //and continue search
844
+ }
845
+ }
846
+
847
+ $base = $this->docRoot;
848
+
849
+ // account for Windows directory structure
850
+ if (strstr($_SERVER['SCRIPT_FILENAME'],':')) {
851
+ $sub_directories = explode('\\', str_replace($this->docRoot, '', $_SERVER['SCRIPT_FILENAME']));
852
+ } else {
853
+ $sub_directories = explode('/', str_replace($this->docRoot, '', $_SERVER['SCRIPT_FILENAME']));
854
+ }
855
+
856
+ foreach ($sub_directories as $sub){
857
+ $base .= $sub . '/';
858
+ $this->debug(3, "Trying file as: " . $base . $src);
859
+ if(file_exists($base . $src)){
860
+ $this->debug(3, "Found file as: " . $base . $src);
861
+ $real = realpath($base . $src);
862
+ if(stripos($real, $realDocRoot) === 0){
863
+ return $real;
864
+ } else {
865
+ $this->debug(1, "Security block: The file specified occurs outside the document root.");
866
+ //And continue search
867
+ }
868
+ }
869
+ }
870
+ return false;
871
+ }
872
+ protected function toDelete($name){
873
+ $this->debug(3, "Scheduling file $name to delete on destruct.");
874
+ $this->toDeletes[] = $name;
875
+ }
876
+ protected function serveWebshot(){
877
+ $this->debug(3, "Starting serveWebshot");
878
+ $instr = "Please follow the instructions at http://code.google.com/p/timthumb/ to set your server up for taking website screenshots.";
879
+ if(! is_file(WEBSHOT_CUTYCAPT)){
880
+ return $this->error("CutyCapt is not installed. $instr");
881
+ }
882
+ if(! is_file(WEBSHOT_XVFB)){
883
+ return $this->Error("Xvfb is not installed. $instr");
884
+ }
885
+ $cuty = WEBSHOT_CUTYCAPT;
886
+ $xv = WEBSHOT_XVFB;
887
+ $screenX = WEBSHOT_SCREEN_X;
888
+ $screenY = WEBSHOT_SCREEN_Y;
889
+ $colDepth = WEBSHOT_COLOR_DEPTH;
890
+ $format = WEBSHOT_IMAGE_FORMAT;
891
+ $timeout = WEBSHOT_TIMEOUT * 1000;
892
+ $ua = WEBSHOT_USER_AGENT;
893
+ $jsOn = WEBSHOT_JAVASCRIPT_ON ? 'on' : 'off';
894
+ $javaOn = WEBSHOT_JAVA_ON ? 'on' : 'off';
895
+ $pluginsOn = WEBSHOT_PLUGINS_ON ? 'on' : 'off';
896
+ $proxy = WEBSHOT_PROXY ? ' --http-proxy=' . WEBSHOT_PROXY : '';
897
+ $tempfile = tempnam($this->cacheDirectory, 'timthumb_webshot');
898
+ $url = $this->src;
899
+ if(! preg_match('/^https?:\/\/[a-zA-Z0-9\.\-]+/i', $url)){
900
+ return $this->error("Invalid URL supplied.");
901
+ }
902
+ $url = preg_replace('/[^A-Za-z0-9\-\.\_\~:\/\?\#\[\]\@\!\$\&\'\(\)\*\+\,\;\=]+/', '', $url); //RFC 3986
903
+ //Very important we don't allow injection of shell commands here. URL is between quotes and we are only allowing through chars allowed by a the RFC
904
+ // which AFAIKT can't be used for shell injection.
905
+ if(WEBSHOT_XVFB_RUNNING){
906
+ putenv('DISPLAY=:100.0');
907
+ $command = "$cuty $proxy --max-wait=$timeout --user-agent=\"$ua\" --javascript=$jsOn --java=$javaOn --plugins=$pluginsOn --js-can-open-windows=off --url=\"$url\" --out-format=$format --out=$tempfile";
908
+ } else {
909
+ $command = "$xv --server-args=\"-screen 0, {$screenX}x{$screenY}x{$colDepth}\" $cuty $proxy --max-wait=$timeout --user-agent=\"$ua\" --javascript=$jsOn --java=$javaOn --plugins=$pluginsOn --js-can-open-windows=off --url=\"$url\" --out-format=$format --out=$tempfile";
910
+ }
911
+ $this->debug(3, "Executing command: $command");
912
+ $out = `$command`;
913
+ $this->debug(3, "Received output: $out");
914
+ if(! is_file($tempfile)){
915
+ $this->set404();
916
+ return $this->error("The command to create a thumbnail failed.");
917
+ }
918
+ $this->cropTop = true;
919
+ if($this->processImageAndWriteToCache($tempfile)){
920
+ $this->debug(3, "Image processed succesfully. Serving from cache");
921
+ return $this->serveCacheFile();
922
+ } else {
923
+ return false;
924
+ }
925
+ }
926
+ protected function serveExternalImage(){
927
+ if(! preg_match('/^https?:\/\/[a-zA-Z0-9\-\.]+/i', $this->src)){
928
+ $this->error("Invalid URL supplied.");
929
+ return false;
930
+ }
931
+ $tempfile = tempnam($this->cacheDirectory, 'timthumb');
932
+ $this->debug(3, "Fetching external image into temporary file $tempfile");
933
+ $this->toDelete($tempfile);
934
+ #fetch file here
935
+ if(! $this->getURL($this->src, $tempfile)){
936
+ @unlink($this->cachefile);
937
+ touch($this->cachefile);
938
+ $this->debug(3, "Error fetching URL: " . $this->lastURLError);
939
+ $this->error("Error reading the URL you specified from remote host." . $this->lastURLError);
940
+ return false;
941
+ }
942
+
943
+ $mimeType = $this->getMimeType($tempfile);
944
+ if(! preg_match("/^image\/(?:jpg|jpeg|gif|png)$/i", $mimeType)){
945
+ $this->debug(3, "Remote file has invalid mime type: $mimeType");
946
+ @unlink($this->cachefile);
947
+ touch($this->cachefile);
948
+ $this->error("The remote file is not a valid image.");
949
+ return false;
950
+ }
951
+ if($this->processImageAndWriteToCache($tempfile)){
952
+ $this->debug(3, "Image processed succesfully. Serving from cache");
953
+ return $this->serveCacheFile();
954
+ } else {
955
+ return false;
956
+ }
957
+ }
958
+ public static function curlWrite($h, $d){
959
+ fwrite(self::$curlFH, $d);
960
+ self::$curlDataWritten += strlen($d);
961
+ if(self::$curlDataWritten > MAX_FILE_SIZE){
962
+ return 0;
963
+ } else {
964
+ return strlen($d);
965
+ }
966
+ }
967
+ protected function serveCacheFile(){
968
+ $this->debug(3, "Serving {$this->cachefile}");
969
+ if(! is_file($this->cachefile)){
970
+ $this->error("serveCacheFile called in timthumb but we couldn't find the cached file.");
971
+ return false;
972
+ }
973
+ $fp = fopen($this->cachefile, 'rb');
974
+ if(! $fp){ return $this->error("Could not open cachefile."); }
975
+ fseek($fp, strlen($this->filePrependSecurityBlock), SEEK_SET);
976
+ $imgType = fread($fp, 3);
977
+ fseek($fp, 3, SEEK_CUR);
978
+ if(ftell($fp) != strlen($this->filePrependSecurityBlock) + 6){
979
+ @unlink($this->cachefile);
980
+ return $this->error("The cached image file seems to be corrupt.");
981
+ }
982
+ $imageDataSize = filesize($this->cachefile) - (strlen($this->filePrependSecurityBlock) + 6);
983
+ $this->sendImageHeaders($imgType, $imageDataSize);
984
+ $bytesSent = @fpassthru($fp);
985
+ fclose($fp);
986
+ if($bytesSent > 0){
987
+ return true;
988
+ }
989
+ $content = file_get_contents ($this->cachefile);
990
+ if ($content != FALSE) {
991
+ $content = substr($content, strlen($this->filePrependSecurityBlock) + 6);
992
+ echo $content;
993
+ $this->debug(3, "Served using file_get_contents and echo");
994
+ return true;
995
+ } else {
996
+ $this->error("Cache file could not be loaded.");
997
+ return false;
998
+ }
999
+ }
1000
+ protected function sendImageHeaders($mimeType, $dataSize){
1001
+ if(! preg_match('/^image\//i', $mimeType)){
1002
+ $mimeType = 'image/' . $mimeType;
1003
+ }
1004
+ if(strtolower($mimeType) == 'image/jpg'){
1005
+ $mimeType = 'image/jpeg';
1006
+ }
1007
+ $gmdate_expires = gmdate ('D, d M Y H:i:s', strtotime ('now +10 days')) . ' GMT';
1008
+ $gmdate_modified = gmdate ('D, d M Y H:i:s') . ' GMT';
1009
+ // send content headers then display image
1010
+ header ('Content-Type: ' . $mimeType);
1011
+ header ('Accept-Ranges: none'); //Changed this because we don't accept range requests
1012
+ header ('Last-Modified: ' . $gmdate_modified);
1013
+ header ('Content-Length: ' . $dataSize);
1014
+ if(BROWSER_CACHE_DISABLE){
1015
+ $this->debug(3, "Browser cache is disabled so setting non-caching headers.");
1016
+ header('Cache-Control: no-store, no-cache, must-revalidate, max-age=0');
1017
+ header("Pragma: no-cache");
1018
+ header('Expires: ' . gmdate ('D, d M Y H:i:s', time()));
1019
+ } else {
1020
+ $this->debug(3, "Browser caching is enabled");
1021
+ header('Cache-Control: max-age=' . BROWSER_CACHE_MAX_AGE . ', must-revalidate');
1022
+ header('Expires: ' . $gmdate_expires);
1023
+ }
1024
+ return true;
1025
+ }
1026
+ protected function securityChecks(){
1027
+ }
1028
+ protected function param($property, $default = ''){
1029
+ if (isset ($_GET[$property])) {
1030
+ return $_GET[$property];
1031
+ } else {
1032
+ return $default;
1033
+ }
1034
+ }
1035
+ protected function openImage($mimeType, $src){
1036
+ switch ($mimeType) {
1037
+ case 'image/jpg': //This isn't a valid mime type so we should probably remove it
1038
+ case 'image/jpeg':
1039
+ $image = imagecreatefromjpeg ($src);
1040
+ break;
1041
+
1042
+ case 'image/png':
1043
+ $image = imagecreatefrompng ($src);
1044
+ break;
1045
+
1046
+ case 'image/gif':
1047
+ $image = imagecreatefromgif ($src);
1048
+ break;
1049
+ }
1050
+
1051
+ return $image;
1052
+ }
1053
+ protected function getIP(){
1054
+ $rem = @$_SERVER["REMOTE_ADDR"];
1055
+ $ff = @$_SERVER["HTTP_X_FORWARDED_FOR"];
1056
+ $ci = @$_SERVER["HTTP_CLIENT_IP"];
1057
+ if(preg_match('/^(?:192\.168|172\.16|10\.|127\.)/', $rem)){
1058
+ if($ff){ return $ff; }
1059
+ if($ci){ return $ci; }
1060
+ return $rem;
1061
+ } else {
1062
+ if($rem){ return $rem; }
1063
+ if($ff){ return $ff; }
1064
+ if($ci){ return $ci; }
1065
+ return "UNKNOWN";
1066
+ }
1067
+ }
1068
+ protected function debug($level, $msg){
1069
+ if(DEBUG_ON && $level <= DEBUG_LEVEL){
1070
+ $execTime = sprintf('%.6f', microtime(true) - $this->startTime);
1071
+ $tick = sprintf('%.6f', 0);
1072
+ if($this->lastBenchTime > 0){
1073
+ $tick = sprintf('%.6f', microtime(true) - $this->lastBenchTime);
1074
+ }
1075
+ $this->lastBenchTime = microtime(true);
1076
+ error_log("TimThumb Debug line " . __LINE__ . " [$execTime : $tick]: $msg");
1077
+ }
1078
+ }
1079
+ protected function sanityFail($msg){
1080
+ return $this->error("There is a problem in the timthumb code. Message: Please report this error at <a href='http://code.google.com/p/timthumb/issues/list'>timthumb's bug tracking page</a>: $msg");
1081
+ }
1082
+ protected function getMimeType($file){
1083
+ $info = getimagesize($file);
1084
+ if(is_array($info) && $info['mime']){
1085
+ return $info['mime'];
1086
+ }
1087
+ return '';
1088
+ }
1089
+ protected function setMemoryLimit(){
1090
+ $inimem = ini_get('memory_limit');
1091
+ $inibytes = timthumb::returnBytes($inimem);
1092
+ $ourbytes = timthumb::returnBytes(MEMORY_LIMIT);
1093
+ if($inibytes < $ourbytes){
1094
+ ini_set ('memory_limit', MEMORY_LIMIT);
1095
+ $this->debug(3, "Increased memory from $inimem to " . MEMORY_LIMIT);
1096
+ } else {
1097
+ $this->debug(3, "Not adjusting memory size because the current setting is " . $inimem . " and our size of " . MEMORY_LIMIT . " is smaller.");
1098
+ }
1099
+ }
1100
+ protected static function returnBytes($size_str){
1101
+ switch (substr ($size_str, -1))
1102
+ {
1103
+ case 'M': case 'm': return (int)$size_str * 1048576;
1104
+ case 'K': case 'k': return (int)$size_str * 1024;
1105
+ case 'G': case 'g': return (int)$size_str * 1073741824;
1106
+ default: return $size_str;
1107
+ }
1108
+ }
1109
+ protected function getURL($url, $tempfile){
1110
+ $this->lastURLError = false;
1111
+ $url = preg_replace('/ /', '%20', $url);
1112
+ if(function_exists('curl_init')){
1113
+ $this->debug(3, "Curl is installed so using it to fetch URL.");
1114
+ self::$curlFH = fopen($tempfile, 'w');
1115
+ if(! self::$curlFH){
1116
+ $this->error("Could not open $tempfile for writing.");
1117
+ return false;
1118
+ }
1119
+ self::$curlDataWritten = 0;
1120
+ $this->debug(3, "Fetching url with curl: $url");
1121
+ $curl = curl_init($url);
1122
+ curl_setopt ($curl, CURLOPT_TIMEOUT, CURL_TIMEOUT);
1123
+ curl_setopt ($curl, CURLOPT_USERAGENT, "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/534.30 (KHTML, like Gecko) Chrome/12.0.742.122 Safari/534.30");
1124
+ curl_setopt ($curl, CURLOPT_RETURNTRANSFER, TRUE);
1125
+ curl_setopt ($curl, CURLOPT_HEADER, 0);
1126
+ curl_setopt ($curl, CURLOPT_SSL_VERIFYPEER, FALSE);
1127
+ curl_setopt ($curl, CURLOPT_WRITEFUNCTION, 'timthumb::curlWrite');
1128
+ @curl_setopt ($curl, CURLOPT_FOLLOWLOCATION, true);
1129
+ @curl_setopt ($curl, CURLOPT_MAXREDIRS, 10);
1130
+
1131
+ $curlResult = curl_exec($curl);
1132
+ fclose(self::$curlFH);
1133
+ $httpStatus = curl_getinfo($curl, CURLINFO_HTTP_CODE);
1134
+ if($httpStatus == 404){
1135
+ $this->set404();
1136
+ }
1137
+ if($curlResult){
1138
+ curl_close($curl);
1139
+ return true;
1140
+ } else {
1141
+ $this->lastURLError = curl_error($curl);
1142
+ curl_close($curl);
1143
+ return false;
1144
+ }
1145
+ } else {
1146
+ $img = @file_get_contents ($url);
1147
+ if($img === false){
1148
+ $err = error_get_last();
1149
+ if(is_array($err) && $err['message']){
1150
+ $this->lastURLError = $err['message'];
1151
+ } else {
1152
+ $this->lastURLError = $err;
1153
+ }
1154
+ if(preg_match('/404/', $this->lastURLError)){
1155
+ $this->set404();
1156
+ }
1157
+
1158
+ return false;
1159
+ }
1160
+ if(! file_put_contents($tempfile, $img)){
1161
+ $this->error("Could not write to $tempfile.");
1162
+ return false;
1163
+ }
1164
+ return true;
1165
+ }
1166
+
1167
+ }
1168
+ protected function serveImg($file){
1169
+ $s = getimagesize($file);
1170
+ if(! ($s && $s['mime'])){
1171
+ return false;
1172
+ }
1173
+ header ('Content-Type: ' . $s['mime']);
1174
+ header ('Content-Length: ' . filesize($file) );
1175
+ header ('Cache-Control: no-store, no-cache, must-revalidate, max-age=0');
1176
+ header ("Pragma: no-cache");
1177
+ $bytes = @readfile($file);
1178
+ if($bytes > 0){
1179
+ return true;
1180
+ }
1181
+ $content = @file_get_contents ($file);
1182
+ if ($content != FALSE){
1183
+ echo $content;
1184
+ return true;
1185
+ }
1186
+ return false;
1187
+
1188
+ }
1189
+ protected function set404(){
1190
+ $this->is404 = true;
1191
+ }
1192
+ protected function is404(){
1193
+ return $this->is404;
1194
+ }
1195
+ }
readme.txt CHANGED
@@ -3,7 +3,7 @@ Contributors: Gallery-Bank
3
  Tags: gallery, image, gallery image, album, foto, fotoalbum, website gallery, multiple pictures, pictures, photo, photoalbum, photogallery, photo gallery, lightbox
4
  Requires at least: 3.0
5
  Tested up to: 3.6 Beta
6
- Stable tag: 1.8.2
7
  License: GPLv3 or later
8
  License URI: http://www.gnu.org/licenses/gpl-3.0.html
9
 
@@ -104,6 +104,12 @@ Visit [here](http://gallery-bank.com) to upgrade to Pro Version now.
104
 
105
  == Changelog ==
106
 
 
 
 
 
 
 
107
  = 1.8.2 =
108
 
109
  * Title Name on Front View & Albums were incorrect - Fixed.
3
  Tags: gallery, image, gallery image, album, foto, fotoalbum, website gallery, multiple pictures, pictures, photo, photoalbum, photogallery, photo gallery, lightbox
4
  Requires at least: 3.0
5
  Tested up to: 3.6 Beta
6
+ Stable tag: 1.8.3
7
  License: GPLv3 or later
8
  License URI: http://www.gnu.org/licenses/gpl-3.0.html
9
 
104
 
105
  == Changelog ==
106
 
107
+ = 1.8.3 =
108
+
109
+ * Introduced Timthumb for Thumbnails
110
+ * Title Alignment - Fixed.
111
+ * Thumbnails were disorted - Fixed.
112
+
113
  = 1.8.2 =
114
 
115
  * Title Name on Front View & Albums were incorrect - Fixed.
views/add-album.php CHANGED
@@ -62,7 +62,9 @@
62
  ?>
63
  </div>
64
  </div>
65
-
 
 
66
  <div class="row" >
67
  <label>
68
  <?php _e( "Upload Images :", gallery_bank ); ?>
@@ -135,12 +137,7 @@ var thumb_array = [];
135
  ({
136
  rules:
137
  {
138
- ux_album_name: "required",
139
- ux_description:
140
- {
141
- required: true
142
-
143
- }
144
  },
145
  submitHandler: function(form)
146
  {
62
  ?>
63
  </div>
64
  </div>
65
+ <div class="row" >
66
+ <img src="<?php echo GALLERY_BK_PLUGIN_URL."/images/screenshot.png";?>"/>
67
+ </div>
68
  <div class="row" >
69
  <label>
70
  <?php _e( "Upload Images :", gallery_bank ); ?>
137
  ({
138
  rules:
139
  {
140
+ ux_album_name: "required"
 
 
 
 
 
141
  },
142
  submitHandler: function(form)
143
  {
views/album.php CHANGED
@@ -76,8 +76,8 @@ $url = plugins_url('', __FILE__);
76
  ?>
77
  <tr>
78
  <td><a href="admin.php?page=view_album&album_id=<?php echo $album[$flag]->album_id;?>" title="<?php _e( "View Album", gallery_bank);?>" style="text-decoration: none;"><?php echo $album[$flag] -> album_name;?></a></td>
79
- <td id="view_bank_album">[gallery_bank album_id=<?php echo $album[$flag]->album_id;?>][/gallery_bank]</td>
80
- <td id="view_bank_album">[gallery_bank_album_cover album_id=<?php echo $album[$flag]->album_id;?>][/gallery_bank_album_cover]</td>
81
  <td><?php echo $count_pic;?></td>
82
  <td><?php echo $album[$flag] -> author;?></td>
83
  <td><?php echo $album[$flag] -> album_date;?></td>
76
  ?>
77
  <tr>
78
  <td><a href="admin.php?page=view_album&album_id=<?php echo $album[$flag]->album_id;?>" title="<?php _e( "View Album", gallery_bank);?>" style="text-decoration: none;"><?php echo $album[$flag] -> album_name;?></a></td>
79
+ <td id="view_bank_album">[gallery_bank album_id=<?php echo $album[$flag]->album_id;?>]</td>
80
+ <td id="view_bank_album">[gallery_bank_album_cover album_id=<?php echo $album[$flag]->album_id;?>]</td>
81
  <td><?php echo $count_pic;?></td>
82
  <td><?php echo $album[$flag] -> author;?></td>
83
  <td><?php echo $album[$flag] -> album_date;?></td>
views/edit-album.php CHANGED
@@ -74,6 +74,9 @@
74
  ?>
75
  </div>
76
  </div>
 
 
 
77
  <div class="row">
78
  <label>
79
  <?php _e( "Upload Images :", gallery_bank ); ?>
@@ -193,10 +196,6 @@ jQuery("#gallery_bank").addClass("current");
193
  rules:
194
  {
195
  ux_edit_album_name: "required",
196
- ux_edit_description:
197
- {
198
- required: true
199
- },
200
  ux_edit_image_width:
201
  {
202
  required: true,
74
  ?>
75
  </div>
76
  </div>
77
+ <div class="row" >
78
+ <img src="<?php echo GALLERY_BK_PLUGIN_URL."/images/screenshot.png";?>"/>
79
+ </div>
80
  <div class="row">
81
  <label>
82
  <?php _e( "Upload Images :", gallery_bank ); ?>
196
  rules:
197
  {
198
  ux_edit_album_name: "required",
 
 
 
 
199
  ux_edit_image_width:
200
  {
201
  required: true,
views/front-view-albums.php CHANGED
@@ -62,7 +62,7 @@ else
62
  {
63
  ?>
64
  <div id="main_div<?php echo $unique_id;?>" style="display: block;" class="album-cover">
65
- <img class="imgHolder" src="<?php echo stripcslashes($album_cover->pic_path); ?>" onclick="view_images(<?php echo $album_id;?>);" style="display:inline-block;border:5px solid #000; cursor:pointer;" width="150px" />
66
  <div style="text-align: justify;display:inline-block;vertical-align:top;margin-left:20px;">
67
  <h3><?php echo stripcslashes($album->album_name); ?>&nbsp;</h3>
68
  <span><?php echo stripcslashes($album->description);?>&nbsp;</span><br/>
@@ -92,21 +92,7 @@ else
92
  jQuery.post(ajaxurl, "album_id="+album_id+"&param=show_images&action=front_albums_gallery_library", function(data)
93
  {
94
  jQuery("#back_button<?php echo $unique_id;?>").css('display','block');
95
-
96
  jQuery('#show_images_<?php echo $unique_id;?>').html(data);
97
- var $container_<?php echo $unique_id;?> = jQuery('#show_images_<?php echo $unique_id;?>');
98
- $container_<?php echo $unique_id;?>.imagesLoaded( function(){
99
- $container_<?php echo $unique_id;?>.masonry({
100
- itemSelector : '.imgContainerSingle',
101
- isAnimated: true,
102
- animationOptions: {
103
- duration: 750,
104
- easing: 'linear',
105
- queue: false
106
- }
107
- });
108
- });
109
- $container_<?php echo $unique_id;?>.masonry('reload');
110
  });
111
  jQuery.post(ajaxurl, "album_id="+album_id+"&param=get_album_name&action=front_albums_gallery_library", function(data)
112
  {
62
  {
63
  ?>
64
  <div id="main_div<?php echo $unique_id;?>" style="display: block;" class="album-cover">
65
+ <img onclick="view_images(<?php echo $album_id;?>);" style="display:inline-block;border:5px solid #000; cursor:pointer;" src="<?php echo stripcslashes(GALLERY_BK_PLUGIN_URL).'/lib/timthumb.php?src='.stripcslashes($album_cover->pic_path).'&h=150&w=150&zc=1&q=100';?>"/></a>
66
  <div style="text-align: justify;display:inline-block;vertical-align:top;margin-left:20px;">
67
  <h3><?php echo stripcslashes($album->album_name); ?>&nbsp;</h3>
68
  <span><?php echo stripcslashes($album->description);?>&nbsp;</span><br/>
92
  jQuery.post(ajaxurl, "album_id="+album_id+"&param=show_images&action=front_albums_gallery_library", function(data)
93
  {
94
  jQuery("#back_button<?php echo $unique_id;?>").css('display','block');
 
95
  jQuery('#show_images_<?php echo $unique_id;?>').html(data);
 
 
 
 
 
 
 
 
 
 
 
 
 
96
  });
97
  jQuery.post(ajaxurl, "album_id="+album_id+"&param=get_album_name&action=front_albums_gallery_library", function(data)
98
  {
views/front_view.php CHANGED
@@ -22,25 +22,44 @@
22
  <h3><?php echo $album->album_name;?></h3>
23
  <div id="view_bank_album_<?php echo $unique_id;?>">
24
  <?php
 
25
  for ($flag = 0; $flag <count($pic_detail); $flag++)
26
  {
27
  if($pic_detail[$flag]->description == "")
28
  {
29
- ?><div class="imgContainerSingle">
 
 
 
30
  <a class="vlightbox1<?php echo $unique_id;?>" id="<?php echo $pic_detail[$flag]->pic_id; ?>" href="<?php echo $pic_detail[$flag]->pic_path; ?>" title="<?php echo $pic_detail[$flag]->title; ?>">
31
- <img src="<?php echo stripcslashes($pic_detail[$flag]->pic_path); ?>" width="150px" /></a>
32
- </div>
33
  <?php
34
-
35
- }
 
 
 
 
 
 
 
36
  else
37
  {
38
- ?>
39
- <div class="imgContainerSingle">
 
 
40
  <a class="vlightbox1<?php echo $unique_id;?>" id="<?php echo $pic_detail[$flag]->pic_id; ?>" href="<?php echo $pic_detail[$flag]->pic_path; ?>" title="<?php echo $pic_detail[$flag]->title; ?> (<?php echo $pic_detail[$flag]->description; ?>)">
41
- <img src="<?php echo stripcslashes($pic_detail[$flag]->pic_path); ?>" width="150px" /></a>
42
- </div>
43
- <?php
 
 
 
 
 
 
 
44
  }
45
  }
46
  ?>
@@ -69,18 +88,4 @@
69
  enableSlideshow:false,
70
  startZoom:true
71
  });
72
- var $container_<?php echo $unique_id;?> = jQuery('#view_bank_album_<?php echo $unique_id;?>');
73
- $container_<?php echo $unique_id;?>.imagesLoaded( function(){
74
- $container_<?php echo $unique_id;?>.masonry({
75
- itemSelector : '.imgContainerSingle',
76
- isAnimated: true,
77
- animationOptions: {
78
- duration: 750,
79
- easing: 'linear',
80
- queue: false
81
- }
82
- });
83
-
84
- });
85
-
86
  </script>
22
  <h3><?php echo $album->album_name;?></h3>
23
  <div id="view_bank_album_<?php echo $unique_id;?>">
24
  <?php
25
+ $row = $album ->images_in_row;
26
  for ($flag = 0; $flag <count($pic_detail); $flag++)
27
  {
28
  if($pic_detail[$flag]->description == "")
29
  {
30
+ if(($flag % $row ==0) && $flag != 0)
31
+ {
32
+ ?>
33
+ <br/>
34
  <a class="vlightbox1<?php echo $unique_id;?>" id="<?php echo $pic_detail[$flag]->pic_id; ?>" href="<?php echo $pic_detail[$flag]->pic_path; ?>" title="<?php echo $pic_detail[$flag]->title; ?>">
35
+ <img style="margin:5px;" src="<?php echo stripcslashes(GALLERY_BK_PLUGIN_URL).'/lib/timthumb.php?src='.stripcslashes($pic_detail[$flag]->pic_path).'&h=150&w=150&zc=1&q=100';?>"/></a>
 
36
  <?php
37
+ }
38
+ else
39
+ {
40
+ ?>
41
+ <a class="vlightbox1<?php echo $unique_id;?>" id="<?php echo $pic_detail[$flag]->pic_id; ?>" href="<?php echo $pic_detail[$flag]->pic_path; ?>" title="<?php echo $pic_detail[$flag]->title; ?>">
42
+ <img style="margin:5px;" src="<?php echo stripcslashes(GALLERY_BK_PLUGIN_URL).'/lib/timthumb.php?src='.stripcslashes($pic_detail[$flag]->pic_path).'&h=150&w=150&zc=1&q=100';?>"/></a>
43
+ <?php
44
+ }
45
+ }
46
  else
47
  {
48
+ if(($flag % $row ==0) && $flag != 0)
49
+ {
50
+ ?>
51
+ <br/>
52
  <a class="vlightbox1<?php echo $unique_id;?>" id="<?php echo $pic_detail[$flag]->pic_id; ?>" href="<?php echo $pic_detail[$flag]->pic_path; ?>" title="<?php echo $pic_detail[$flag]->title; ?> (<?php echo $pic_detail[$flag]->description; ?>)">
53
+ <img style="margin:5px;" src="<?php echo stripcslashes(GALLERY_BK_PLUGIN_URL).'/lib/timthumb.php?src='.stripcslashes($pic_detail[$flag]->pic_path).'&h=150&w=150&zc=1&q=100';?>"/></a>
54
+ <?php
55
+ }
56
+ else
57
+ {
58
+ ?>
59
+ <a class="vlightbox1<?php echo $unique_id;?>" id="<?php echo $pic_detail[$flag]->pic_id; ?>" href="<?php echo $pic_detail[$flag]->pic_path; ?>" title="<?php echo $pic_detail[$flag]->title; ?> (<?php echo $pic_detail[$flag]->description; ?>)">
60
+ <img style="margin:5px;" src="<?php echo GALLERY_BK_PLUGIN_URL.'/lib/timthumb.php?src='.stripcslashes($pic_detail[$flag]->pic_path).'&h=150&w=150&zc=1&q=100';?>"/></a>
61
+ <?php
62
+ }
63
  }
64
  }
65
  ?>
88
  enableSlideshow:false,
89
  startZoom:true
90
  });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
91
  </script>