00001 <?php
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 @require_once('config.inc.php');
00013 require_once('html.inc.php');
00014 require_once('modules.inc.php');
00015
00016 require_once('util.inc.php');
00017
00018
00019
00020
00021
00022
00023
00024 function _gd_available()
00025 {
00026 return function_exists('gd_info');
00027 }
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037 function _gd_get_imagesize($f)
00038 {
00039 $ret = @getimagesize($f);
00040 if ($ret === false) {
00041 return array(0, 0);
00042 } else {
00043 return array($ret[0], $ret[1]);
00044 }
00045 }
00046
00047
00048
00049
00050
00051
00052
00053 function image_alter_render_early($args)
00054 {
00055 $elem = &$args['elem'];
00056 $obj = $args['obj'];
00057 if (!elem_has_class($elem, 'image')) {
00058 return false;
00059 }
00060
00061
00062 if (!empty($obj['image-file']) && (empty($obj['image-file-width']) || intval($obj['image-file-width']) == 0)) {
00063 if (_gd_available()) {
00064 $a = expl('.', $obj['name']);
00065 $fn = CONTENT_DIR.'/'.$a[0].'/shared/'.$obj['image-file'];
00066
00067 if (@is_link($fn)) {
00068 $target = @readlink($fn);
00069 if (substr($target, 0, 1) == '/') {
00070 $fn = $target;
00071 } else {
00072 $fn = dirname($fn).'/'.$target;
00073 }
00074 }
00075 $size = _gd_get_imagesize($fn);
00076 $obj['image-file-width'] = $size[0];
00077
00078 if (empty($obj['object-width']) || intval($obj['object-width']) == 0) {
00079 $obj['object-width'] = $size[0].'px';
00080 }
00081 $obj['image-file-height'] = $size[1];
00082 if (empty($obj['object-height']) || intval($obj['object-height']) == 0) {
00083 $obj['object-height'] = $size[1].'px';
00084 }
00085 }
00086 save_object($obj);
00087 }
00088
00089
00090
00091
00092
00093
00094 if (SHORT_URLS) {
00095 $url = base_url().urlencode($obj['name']);
00096 } else {
00097 $url = base_url().'?'.urlencode($obj['name']);
00098 }
00099
00100
00101
00102 if (empty($obj['image-file-width']) || intval($obj['image-file-width']) == 0) {
00103
00104 $i = elem('img');
00105 elem_attr($i, 'src', $url);
00106 if (!empty($obj['image-title'])) {
00107 elem_attr($i, 'alt', $obj['image-title']);
00108 } else {
00109 elem_attr($i, 'alt', '');
00110 }
00111
00112
00113 elem_append($elem, $i);
00114 } else {
00115 if (!$args['edit'] && IE8_COMPAT && (empty($obj['image-background-repeat']) || $obj['image-background-repeat'] == 'no-repeat')) {
00116
00117 $i = elem('img');
00118 elem_attr($i, 'src', $url);
00119 if (!empty($obj['image-title'])) {
00120 elem_attr($i, 'alt', $obj['image-title']);
00121 } else {
00122 elem_attr($i, 'alt', '');
00123 }
00124 elem_css($i, 'width', '100%');
00125 elem_css($i, 'height', '100%');
00126 elem_css($i, 'padding', '0px');
00127 elem_css($i, 'border', '0px');
00128 if (!empty($obj['image-background-position']) && $obj['image-background-position'] != '0px 0px' && $obj['image-background-position'] != '0% 0%') {
00129 elem_css($elem, 'max-width', $obj['object-width']);
00130 elem_css($elem, 'max-height', $obj['object-height']);
00131 elem_css($elem, 'overflow', 'hidden');
00132
00133 $a = expl(' ', $obj['image-background-position']);
00134 elem_css($i, 'margin-left', @intval($a[0]).'px');
00135 elem_css($i, 'margin-top', @intval($a[1]).'px');
00136 elem_css($i, 'margin-right', '0px');
00137 elem_css($i, 'margin-bottom', '0px');
00138 } else {
00139 elem_css($i, 'margin', '0px');
00140 }
00141 elem_append($elem, $i);
00142 } else {
00143
00144
00145 elem_css($elem, 'background-image', 'url('.$url.')');
00146
00147 if (empty($obj['image-background-repeat']) || $obj['image-background-repeat'] == 'no-repeat') {
00148 elem_css($elem, 'background-repeat', 'no-repeat');
00149
00150 elem_css($elem, 'background-size', '100% 100%');
00151
00152 elem_css($elem, '-moz-background-size', '100% 100%');
00153 } else {
00154 elem_css($elem, 'background-repeat', $obj['image-background-repeat']);
00155 }
00156 if (!empty($obj['image-background-position'])) {
00157 elem_css($elem, 'background-position', $obj['image-background-position']);
00158 }
00159 }
00160 }
00161
00162
00163 if (!empty($obj['image-title'])) {
00164 elem_attr($elem, 'title', $obj['image-title']);
00165 }
00166
00167 return true;
00168 }
00169
00170
00171
00172
00173
00174
00175
00176 function image_alter_save($args)
00177 {
00178 $elem = $args['elem'];
00179
00180 $obj = &$args['obj'];
00181
00182
00183 if (!elem_has_class($elem, 'image')) {
00184 return false;
00185 }
00186
00187
00188
00189
00190 if (elem_css($elem, 'background-repeat') !== NULL) {
00191 $val = elem_css($elem, 'background-repeat');
00192
00193 if ($val == 'no-repeat no-repeat') {
00194 $val = 'no-repeat';
00195 }
00196 $obj['image-background-repeat'] = $val;
00197 } else {
00198 unset($obj['image-background-repeat']);
00199 }
00200 if (elem_css($elem, 'background-position') !== NULL) {
00201 $obj['image-background-position'] = elem_css($elem, 'background-position');
00202 } else {
00203 unset($obj['image-background-position']);
00204 }
00205
00206
00207 return true;
00208 }
00209
00210
00211
00212
00213
00214 function image_delete_object($args)
00215 {
00216 $obj = $args['obj'];
00217 if (!isset($obj['type']) || $obj['type'] != 'image') {
00218 return false;
00219 }
00220
00221
00222
00223 load_modules('glue');
00224
00225 if (!empty($obj['image-file'])) {
00226 $a = expl('.', $obj['name']);
00227 delete_upload(array('pagename'=>$a[0], 'file'=>$obj['image-file'], 'max_cnt'=>1));
00228 }
00229
00230 if (!empty($obj['image-resized-file'])) {
00231 $a = expl('.', $obj['name']);
00232 delete_upload(array('pagename'=>$a[0], 'file'=>$obj['image-resized-file'], 'max_cnt'=>1));
00233 }
00234 }
00235
00236
00237
00238
00239
00240 function image_has_reference($args)
00241 {
00242 $obj = $args['obj'];
00243 if (!isset($obj['type']) || $obj['type'] != 'image') {
00244 return false;
00245 }
00246
00247
00248 if (@is_link(CONTENT_DIR.'/'.str_replace('.', '/', $obj['name']))) {
00249 return false;
00250 }
00251
00252 if (!empty($obj['image-file']) && $obj['image-file'] == $args['file']) {
00253 return true;
00254 }
00255 if (!empty($obj['image-resized-file']) && $obj['image-resized-file'] == $args['file']) {
00256 return true;
00257 }
00258
00259 return false;
00260 }
00261
00262
00263
00264
00265
00266 function image_render_object($args)
00267 {
00268 $obj = $args['obj'];
00269 if (!isset($obj['type']) || $obj['type'] != 'image') {
00270 return false;
00271 }
00272
00273
00274
00275
00276
00277
00278
00279 $e = elem('div');
00280 elem_attr($e, 'id', $obj['name']);
00281 elem_add_class($e, 'image');
00282 elem_add_class($e, 'resizable');
00283 elem_add_class($e, 'object');
00284
00285
00286
00287
00288
00289 invoke_hook_first('alter_render_early', 'image', array('obj'=>$obj, 'elem'=>&$e, 'edit'=>$args['edit']));
00290 $html = elem_finalize($e);
00291
00292
00293 invoke_hook_last('alter_render_late', 'image', array('obj'=>$obj, 'html'=>&$html, 'elem'=>$e, 'edit'=>$args['edit']));
00294
00295 return $html;
00296 }
00297
00298 register_hook('alter_render_early', 'invoked early in the object rendering process (possible to change array representation)');
00299 register_hook('alter_render_late', 'invoked late in the object rendering process (possible to change html string)');
00300
00301
00302
00303
00304
00305 function image_render_page_early($args)
00306 {
00307 if ($args['edit']) {
00308 if (USE_MIN_FILES) {
00309 html_add_js(base_url().'modules/image/image-edit.min.js');
00310 } else {
00311 html_add_js(base_url().'modules/image/image-edit.js');
00312 }
00313 if (!_gd_available()) {
00314 html_add_js_var('$.glue.conf.image.resizing', false);
00315 log_msg('debug', 'image: disabling image resizing as gd is not available');
00316 } else {
00317 html_add_js_var('$.glue.conf.image.resizing', IMAGE_RESIZING);
00318 }
00319 html_add_js_var('$.glue.conf.image.upload_resize_larger', IMAGE_UPLOAD_RESIZE_LARGER);
00320 html_add_js_var('$.glue.conf.image.upload_resize_to', IMAGE_UPLOAD_RESIZE_TO);
00321 }
00322 }
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335 function is_ani($filename) {
00336 if(!($fh = @fopen($filename, 'rb')))
00337 return false;
00338 $count = 0;
00339 while(!feof($fh) && $count < 2) {
00340 $chunk = fread($fh, 1024 * 100);
00341 $count += preg_match_all('#\x00\x21\xF9\x04.{4}\x00(\x2C|\x21)#s', $chunk, $matches);
00342 }
00343 fclose($fh);
00344 return $count > 1;
00345 }
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360 function image_resize($args)
00361 {
00362
00363 if (!_gd_available()) {
00364 return response('Host does not have gd', 500);
00365 }
00366
00367 if (($width = @intval($args['width'])) == 0) {
00368 return response('Required argument "width" is zero or does not exist', 400);
00369 }
00370 if (($height = @intval($args['height'])) == 0) {
00371 return response('Required argument "height" is zero or does not exist', 400);
00372 }
00373 load_modules('glue');
00374
00375 $ret = object_get_symlink($args);
00376 if ($ret['#error']) {
00377 return $ret;
00378 } elseif ($ret['#data'] !== false) {
00379 log_msg('debug', 'image_resize: resolved object '.quot($args['name']).' into '.quot($ret['#data']));
00380 $args['name'] = $ret['#data'];
00381 }
00382
00383 $obj = load_object($args);
00384 if ($obj['#error']) {
00385 return $obj;
00386 } else {
00387 $obj = $obj['#data'];
00388 }
00389 if (@intval($obj['image-file-width']) == 0 || @intval($obj['image-file-height']) == 0) {
00390 return response('Original dimensions are not available', 500);
00391 }
00392
00393 $pn = array_shift(expl('.', $obj['name']));
00394
00395
00396 if (!empty($obj['image-resized-file']) && @intval($obj['image-resized-width']) == $width && @intval($obj['image-resized-height'] == $height)) {
00397 log_msg('debug', 'image_resize: width and height match the current resized file, no resize necessary');
00398 return response(false);
00399 }
00400
00401
00402 if (!empty($obj['image-resized-file'])) {
00403 log_msg('info', 'image_resize: dropping reference to previous resized file '.quot($obj['image-resized-file']));
00404 delete_upload(array('pagename'=>$pn, 'file'=>$obj['image-resized-file'], 'max_cnt'=>1));
00405 unset($obj['image-resized-file']);
00406 unset($obj['image-resized-width']);
00407 unset($obj['image-resized-height']);
00408
00409 $ret = object_remove_attr(array('name'=>$obj['name'], 'attr'=>array('image-resized-file', 'image-resized-width', 'image-resized-height')));
00410 if ($ret['#error']) {
00411 return $ret;
00412 }
00413 $was_resized = true;
00414 } else {
00415 $was_resized = false;
00416 }
00417
00418
00419 if (@intval($obj['image-file-width']) <= $width || @intval($obj['image-file-height']) <= $height) {
00420 log_msg('debug', 'image_resize: dimensions requested are larger or equal than the original file is, no resize necessary');
00421
00422
00423 if (!$was_resized) {
00424 return response(false);
00425 } else {
00426 return response(true);
00427 }
00428 }
00429
00430
00431 if (empty($obj['image-file-mime']) && empty($obj['image-file'])) {
00432 return response(false);
00433 }
00434
00435
00436
00437 $ext = filext($obj['image-file']);
00438 $fn = CONTENT_DIR.'/'.$pn.'/shared/'.$obj['image-file'];
00439 if ($obj['image-file-mime'] == 'image/jpeg' || in_array($ext, array('jpg', 'jpeg'))) {
00440 $orig = @imagecreatefromjpeg($fn);
00441 $dest_ext = 'jpg';
00442 } elseif ($obj['image-file-mime'] == 'image/png' || $ext == 'png') {
00443 $orig = @imagecreatefrompng($fn);
00444 $dest_ext = 'png';
00445 } elseif (is_ani($fn)) {
00446
00447 log_msg('debug', 'image_resize: animated image, not resizing');
00448 return response(true);
00449 } elseif ($obj['image-file-mime'] == 'image/gif' || $ext == 'gif') {
00450 $orig = @imagecreatefromgif($fn);
00451
00452
00453 $dest_ext = 'png';
00454 } else {
00455 return response('Unsupported source file format '.quot($obj['image-file']), 500);
00456 }
00457 if ($orig === false) {
00458 return response('Error loading source file '.quot($obj['image-file']), 500);
00459 }
00460
00461 $orig_size = @getimagesize($fn);
00462
00463 if (($resized = @imagecreatetruecolor($width, $height)) === false) {
00464 @imagedestroy($orig);
00465 return response('Error creating the resized image', 500);
00466 }
00467
00468 @imagealphablending($resized, false);
00469 @imagesavealpha($resized, true);
00470
00471 if (!@imagecopyresampled($resized, $orig, 0, 0, 0, 0, $width, $height, $orig_size[0], $orig_size[1])) {
00472 @imagedestroy($resized);
00473 @imagedestroy($orig);
00474 return response('Error resizing the source image', 500);
00475 }
00476
00477 $a = expl('.', $obj['image-file']);
00478 if (1 < count($a)) {
00479
00480 $fn = CONTENT_DIR.'/'.$pn.'/shared/'.implode('.', array_slice($a, 0, -1)).'-'.$width.'x'.$height.'.'.$dest_ext;
00481 } else {
00482 $fn = CONTENT_DIR.'/'.$pn.'/shared/'.$a[0].'-'.$width.'x'.$height.'.'.$dest_ext;
00483 }
00484 $m = umask(0111);
00485 if ($dest_ext == 'jpg') {
00486 $ret = @imagejpeg($resized, $fn, IMAGE_JPEG_QUAL);
00487 } else if ($dest_ext == 'png') {
00488
00489 @imagealphablending($resized, false);
00490 @imagesavealpha($resized, true);
00491 $ret = @imagepng($resized, $fn, IMAGE_PNG_QUAL);
00492 }
00493 umask($m);
00494
00495 @imagedestroy($resized);
00496 @imagedestroy($orig);
00497 if (!$ret) {
00498 return response('Error saving the resized image', 500);
00499 } else {
00500 log_msg('info', 'image_resize: created a resized image of '.quot($obj['name']).' -> '.quot(basename($fn)));
00501 }
00502
00503
00504
00505 $update = array();
00506 $update['name'] = $obj['name'];
00507 $update['image-resized-file'] = basename($fn);
00508 $update['image-resized-width'] = $width;
00509 $update['image-resized-height'] = $height;
00510
00511
00512 $update['object-width'] = $width.'px';
00513 $update['object-height'] = $height.'px';
00514
00515 return update_object($update);
00516 }
00517
00518 register_service('image.resize', 'image_resize', array('auth'=>true));
00519
00520
00521
00522
00523
00524 function image_save_state($args)
00525 {
00526 $elem = $args['elem'];
00527 $obj = $args['obj'];
00528
00529 if (array_shift(elem_classes($elem)) != 'image') {
00530 return false;
00531 }
00532
00533
00534 $obj['type'] = 'image';
00535 $obj['module'] = 'image';
00536
00537
00538
00539
00540
00541
00542
00543
00544 invoke_hook('alter_save', array('obj'=>&$obj, 'elem'=>$elem));
00545
00546
00547
00548
00549
00550 load_modules('glue');
00551 $ret = save_object($obj);
00552 if ($ret['#error']) {
00553 log_msg('error', 'image_save_state: save_object returned '.quot($ret['#data']));
00554 return false;
00555 } else {
00556 return true;
00557 }
00558 }
00559
00560 register_hook('alter_save', 'invoked in the object saving process (possible to augment the object to be saved)');
00561
00562
00563
00564
00565
00566 function image_serve_resource($args)
00567 {
00568 $obj = $args['obj'];
00569 if (!isset($obj['type']) || $obj['type'] != 'image') {
00570 return false;
00571 }
00572
00573
00574 $pn = array_shift(expl('.', $obj['name']));
00575
00576 if (!empty($obj['image-resized-file']) && !$args['dl']) {
00577
00578 $fn = CONTENT_DIR.'/'.$pn.'/shared/'.$obj['image-resized-file'];
00579 $ext = filext($fn);
00580 if ($ext == 'jpg' || $ext == 'jpeg') {
00581 serve_file($fn, false, 'image/jpeg');
00582 } else if ($ext == 'png') {
00583 serve_file($fn, false, 'image/png');
00584 } else {
00585 log_msg('warn', 'image_serve_resource: unsupported image-resized-file '.quot($fn));
00586 }
00587
00588
00589 log_msg('warn', 'image_serve_resource: could not serve image-resized-file '.quot($fn).', falling back to original');
00590 $need_auth = false;
00591 } elseif (empty($obj['image-resized-file'])) {
00592
00593 $need_auth = false;
00594 } else {
00595
00596 $need_auth = true;
00597 }
00598
00599 if (!empty($obj['image-file'])) {
00600
00601 if ($need_auth && !is_auth()) {
00602
00603 prompt_auth(true);
00604 }
00605 if (empty($obj['image-file-mime'])) {
00606 $obj['image-file-mime'] = '';
00607 }
00608 serve_file(CONTENT_DIR.'/'.$pn.'/shared/'.$obj['image-file'], $args['dl'], $obj['image-file-mime']);
00609 }
00610
00611
00612 return false;
00613 }
00614
00615
00616
00617
00618
00619
00620
00621 function image_snapshot_symlink($args)
00622 {
00623 $obj = $args['obj'];
00624 if (!isset($obj['type']) || $obj['type'] != 'image') {
00625 return false;
00626 }
00627
00628
00629
00630
00631
00632
00633
00634
00635
00636
00637
00638
00639
00640
00641 $dest_dir = CONTENT_DIR.'/'.array_shift(expl('.', $obj['name'])).'/shared';
00642 $src_dir = CONTENT_DIR.'/'.array_shift(expl('.', $args['origin'])).'/shared';
00643
00644
00645
00646 foreach (array('image-file', 'image-resized-file') as $field) {
00647 if (empty($obj[$field])) {
00648 continue;
00649 } else {
00650 $src_file = $src_dir.'/'.$obj[$field];
00651 }
00652 if (($f = dir_has_same_file($dest_dir, $src_file)) !== false) {
00653 $obj[$field] = $f;
00654 } else {
00655
00656 $dest_file = $dest_dir.'/'.unique_filename($dest_dir, $src_file);
00657 $m = umask(0111);
00658 if (!(@copy($src_file, $dest_file))) {
00659 umask($m);
00660 log_msg('error', 'image_snapshot_symlink: error copying referenced file '.quot($src_file).' to '.quot($dest_file));
00661 return false;
00662 }
00663 umask($m);
00664 $obj[$field] = basename($dest_file);
00665 log_msg('info', 'image_snapshot_symlink: copied referenced file to '.quot($dest_file));
00666 }
00667 }
00668
00669
00670 $ret = save_object($obj);
00671 if ($ret['#error']) {
00672 log_msg('error', 'image_snapshot_symlink: error saving object '.quot($obj['name']));
00673 return false;
00674 } else {
00675 return true;
00676 }
00677 }
00678
00679
00680
00681
00682
00683 function image_upload($args)
00684 {
00685
00686 if (!in_array($args['mime'], array('image/jpeg', 'image/png', 'image/gif')) || ($args['mime'] == '' && !in_array(filext($args['file']), array('jpg', 'jpeg', 'png', 'gif')))) {
00687 return false;
00688 }
00689
00690 load_modules('glue');
00691
00692 $obj = create_object($args);
00693 if ($obj['#error']) {
00694 return false;
00695 } else {
00696 $obj = $obj['#data'];
00697 }
00698 $obj['type'] = 'image';
00699
00700 $obj['module'] = 'image';
00701 $obj['image-file'] = $args['file'];
00702 $obj['image-file-mime'] = $args['mime'];
00703
00704 if (_gd_available()) {
00705 $a = expl('.', $args['page']);
00706 $size = _gd_get_imagesize(CONTENT_DIR.'/'.$a[0].'/shared/'.$obj['image-file']);
00707 $obj['image-file-width'] = $size[0];
00708 $obj['object-width'] = $size[0].'px';
00709 $obj['image-file-height'] = $size[1];
00710 $obj['object-height'] = $size[1].'px';
00711 }
00712 save_object($obj);
00713
00714
00715 $ret = render_object(array('name'=>$obj['name'], 'edit'=>true));
00716 if ($ret['#error']) {
00717 return false;
00718 } else {
00719 return $ret['#data'];
00720 }
00721 }