From 7c161d7229cde7a50d133ea523b8b1fe714bb478 Mon Sep 17 00:00:00 2001 From: Rodolfo Berrios Date: Sat, 3 Sep 2016 15:35:50 -0300 Subject: [PATCH] - Added check for updates (GitHub) - Added one-click update system (GitHub) --- README.md | 6 +- app/app.php | 4 +- app/install/installer.php | 9 +- app/install/update/template/update.js | 2 +- app/install/update/updater.php | 178 +++++++++++++++++++++- app/lib/chevereto.js | 6 +- app/lib/chevereto.min.js | 4 +- app/lib/functions.php | 15 +- app/loader.php | 3 + app/routes/route.dashboard.php | 4 +- app/routes/route.image.php | 33 +--- app/routes/route.update.php | 4 + app/themes/Peafowl/footer.php | 2 +- app/themes/Peafowl/snippets/footer.js.php | 1 + 14 files changed, 219 insertions(+), 52 deletions(-) diff --git a/README.md b/README.md index 7994d92..438f62c 100644 --- a/README.md +++ b/README.md @@ -20,8 +20,12 @@ Chevereto Free includes all the basic image hosting stuff but it comes without d | Item | Free | Paid | |---------------------------------------------- |----------------- |------------------------ | | Contribution to Chevereto | ☆ | ★★★★ | +<<<<<<< HEAD +| Access to latest features | Delayed | Always | +| One click system update | Yes | Yes | +======= +>>>>>>> 0cba3b880f6c7de8489399f73159b78e3699160a | Tech support | No | Direct from developers | -| One click system update | No | Yes | | External storage support | No | Yes | | Manage banners | No | Yes | | Likes + Followers | No | Yes | diff --git a/app/app.php b/app/app.php index e4c4927..aa32607 100644 --- a/app/app.php +++ b/app/app.php @@ -1,3 +1,5 @@ 'album', 'enable_duplicate_uploads' => 0, 'update_check_datetimegmt' => NULL, - 'update_check_notified_release' => NULL, + 'update_check_notified_release' => G_APP_VERSION, 'update_check_display_notification' => 1, ], '1.0.1' => NULL, + '1.0.2' => NULL, ]; // Settings that must be renamed from NAME to NEW NAME and DELETE old NAME - $settings_rename = [ - ]; + $settings_rename = []; // Settings that must be renamed from NAME to NEW NAME and doesn't delete old NAME - $settings_switch = [ - ]; + $settings_switch = []; $chv_initial_settings = []; foreach($settings_updates as $k => $v) { diff --git a/app/install/update/template/update.js b/app/install/update/template/update.js index 363f2a6..b81eb32 100644 --- a/app/install/update/template/update.js +++ b/app/install/update/template/update.js @@ -16,7 +16,7 @@ var update = { vars: {}, process: function(callback) { // S0: Check if update is needed var _this = this; - _this.addLog(PF.fn._s("Installed version is v%s", vars.current_version)); + _this.addLog(PF.fn._s("Installed version is v%s", vars.current_version) + " (Chevereto Free)"); $.ajax({ url: vars.url, data: {action: "ask"} diff --git a/app/install/update/updater.php b/app/install/update/updater.php index 7116cb3..13254d6 100644 --- a/app/install/update/updater.php +++ b/app/install/update/updater.php @@ -20,16 +20,188 @@ use G, Exception; if(!defined('access') or !access) die('This file cannot be directly accessed.'); try { - if(is_null(getSetting('chevereto_version_installed'))) { + if(!is_null(getSetting('chevereto_version_installed')) and !Login::getUser()['is_admin']) { G\set_status_header(403); - die('403'); + die('Request denied. You must be an admin to be here.'); } + if(!class_exists('ZipArchive')) { + throw new Exception("PHP ZipArchive class is not enabled in this server"); + } + if(!is_writable(G_ROOT_PATH)) { + throw new Exception(sprintf("Can't write into root %s path", G\absolute_to_relative(G_ROOT_PATH))); + } + $update_temp_dir = CHV_APP_PATH_INSTALL . 'update/temp/'; + if(!is_writable($update_temp_dir)) { + throw new Exception(sprintf("Can't write into %s path", G\absolute_to_relative($update_temp_dir))); + } if(!isset($_REQUEST['action'])) { - Render\chevereto_die(['Download the latest release from our GitHub repo', 'Upload this files to your server website folder', 'Go to /install to proceed with the installation of the update package'], strtr('This website is ready to update to Chevereto v%s but to get this update and all future updates of our main releases channel, please consider upgrading to our paid version. This paid version has more functionalities, updates, comes with tech support and you can update it with just one click from your dashboard panel.

You can manually update this website to the latest available Chevereto Free release by doing the following:', ['%s' => getSetting('update_check_notified_release')]), "Upgrade for one-click updates"); + $doctitle = 'Update in progress'; + $system_template = CHV_APP_PATH_SYSTEM . 'template.php'; + $update_template = dirname($update_temp_dir) . '/template/update.php'; + if(file_exists($update_template)) { + ob_start(); + require_once($update_template); + $html = ob_get_contents(); + ob_end_clean(); + } else { + throw new Exception("Can't find " . G\absolute_to_relative($update_template)); + } + if(!@require_once($system_template)) { + throw new Exception("Can't find " . G\absolute_to_relative($system_template)); + } + } else { + + set_time_limit(300); // Allow up to five minutes... + + switch($_REQUEST['action']) { + case 'ask': + try { + $json_array = json_decode(G\fetch_url('https://chevereto.com/api/get/info/free'), TRUE); + $json_array['success'] = ['message' => 'OK']; // "success" is a Chevereto internal thing + } catch(Exception $e) { + throw new Exception(_s("An error occurred. Please try again later."), 400); + } + break; + case 'download': + try { + $version = $_REQUEST['version']; + $context = stream_context_create([ + 'http'=> [ + 'method' => 'GET', + 'header' => "User-agent: " . G_APP_GITHUB_REPO . "\r\n" + ] + ]); + $download = @file_get_contents('https://api.github.com/repos/' . G_APP_GITHUB_OWNER . '/' . G_APP_GITHUB_REPO . '/zipball/'.$version, FALSE, $context); + if($download === FALSE) { + throw new Exception(sprintf("Can't fetch " . G_APP_NAME . " v%s from GitHub", $version), 400); + } + $github_json = json_decode($download, TRUE); + if(json_last_error() == JSON_ERROR_NONE) { + throw new Exception("Can't proceed with update procedure"); + } else { + // Get Content-Disposition header from GitHub + foreach($http_response_header as $header) { + if(preg_match('/^Content-Disposition:.*filename=(.*)$/i', $header, $matches)) { + $zip_local_filename = G\str_replace_last('.zip', '_' . G\random_string(24) . '.zip', $matches[1]); + break; + } + } + if(!isset($zip_local_filename)) { + throw new Exception("Can't grab content-disposition header from GitHub"); + } + if(file_put_contents($update_temp_dir . $zip_local_filename, $download) === FALSE) { + throw new Exception(_s("Can't save file")); + } + $json_array = [ + 'success' => [ + 'message' => 'Download completed', + 'code' => 200 + ], + 'download' => [ + 'filename' => $zip_local_filename + ] + ]; + } + } catch (Exception $e) { + throw new Exception(_s("Can't download %s", 'v' . $version) . ' (' . $e->getMessage() . ')'); + } + break; + case 'extract': + + $zip_file = $update_temp_dir . $_REQUEST['file']; + + if(FALSE === preg_match('/^Chevereto-Chevereto-Free-([\d.]+)-\d+-g(.*)_.*$/', $_REQUEST['file'], $matches)) { + throw new Exception("Can't detect target zip file version"); + } + + $version = $matches[1]; + $etag_short = $matches[2]; + + // Test .zip + if(!is_readable($zip_file)) { + throw new Exception('Missing '.$zip_file.' file', 400); + } + // Unzip .zip + $zip = new \ZipArchive; + if ($zip->open($zip_file) === TRUE) { + // At this point we will enter the website in maintenance mode (if needed) + try { + $toggle_maintenance = !getSetting('maintenance'); + if($toggle_maintenance) { + DB::update('settings', ['value' => $toggle_maintenance], ['name' => 'maintenance']); + } + } catch (Exception $e) {} + $zip->extractTo($update_temp_dir); + $zip->close(); + @unlink($zip_file); + } else { + throw new Exception(_s("Can't extract %s", G\absolute_to_relative($zip_file)), 401); + } + + // Recursive copy UPDATE -> CURRENT + $source = $update_temp_dir . G_APP_GITHUB_OWNER . '-' . G_APP_GITHUB_REPO . '-' . $etag_short . '/'; + $dest = G_ROOT_PATH; + + foreach ($iterator = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($source, \RecursiveDirectoryIterator::SKIP_DOTS), \RecursiveIteratorIterator::SELF_FIRST) as $item) { + + $target = $dest . $iterator->getSubPathName(); + $target_visible = G\absolute_to_relative($target); + + if ($item->isDir()) { + if(!file_exists($target) and !@mkdir($target)) { + $error = error_get_last(); + throw new Exception(_s("Can't create %s directory - %e", [ + '%s' => $target_visible, + '%e' => $error['message'] + ]), 402); + } + } else { + // Touch anything but .htaccess files + if(!preg_match('/\.htaccess$/', $item)) { + if(!@copy($item, $target)) { + $error = error_get_last(); + throw new Exception(_s("Can't update %s file - %e", [ + '%s' => $target_visible, + '%e' => $error['message'] + ]), 403); + } + } + unlink($item); // Save some valuable seconds... + } + + } + + // Remove working copy (UPDATE) + $tmp = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($update_temp_dir, \RecursiveDirectoryIterator::SKIP_DOTS), \RecursiveIteratorIterator::CHILD_FIRST); + foreach ($tmp as $fileinfo) { + $todo = ($fileinfo->isDir() ? 'rmdir' : 'unlink'); + $todo($fileinfo->getRealPath()); + } + + // Turn off maintenance mode (if needed) + try { + if($toggle_maintenance) { + DB::update('settings', ['value' => 0], ['name' => 'maintenance']); + } + } catch (Exception $e) {} + + $json_array['success'] = ['message' => 'OK', 'code' => 200]; + break; + } + // Inject any missing status_code + if(isset($json_array['success']) and !isset($json_array['status_code'])) { + $json_array['status_code'] = 200; + } + $json_array['request'] = $_REQUEST; + G\Render\json_output($json_array); } die(); // Terminate any remaining execution (if any) } catch (Exception $e) { if(!isset($_REQUEST['action'])) { Render\chevereto_die($e->getMessage(), "This installation can't use the automatic update functionality because this server is missing some crucial elements to allow Chevereto to perform the automatic update:", "Can't perform automatic update"); + } else { + $json_array = G\json_error($e); + $json_array['request'] = $_REQUEST; + G\Render\json_output($json_array); } } \ No newline at end of file diff --git a/app/lib/chevereto.js b/app/lib/chevereto.js index 1948508..65519fe 100644 --- a/app/lib/chevereto.js +++ b/app/lib/chevereto.js @@ -1578,11 +1578,11 @@ $(function(){ if(PF.fn.versionCompare(CHV.obj.system_info.version, data.current_version) == -1) { PF.fn.modal.simple({ title: PF.fn._s("Update available v%s", data.current_version), - message: '

' + PF.fn._s('There is an update available for your system. You can automatic download and install this update or go to %s to proceed to download the file.', 'chevereto.com') + '

' + PF.fn._s('The release notes for this update are:') + '

' + '' + '
' + PF.fn._s('Update now') + ' ' + PF.fn._s('or') + ' ' + PF.fn._s('cancel') + '
', + message: '

' + PF.fn._s('There is an update available for your system. You can automatic download and install this update or go to %s to proceed to download the file.', 'GitHub') + '

' + PF.fn._s('The release notes for this update are:') + '

' + '' + '
' + PF.fn._s('Update now') + ' ' + PF.fn._s('or') + ' ' + PF.fn._s('cancel') + '
', html: true }); } else { - PF.fn.growl.call(PF.fn._s("Your website is running the latest version of Chevereto.")); + PF.fn.growl.call(PF.fn._s("Your website is running the latest version of Chevereto.").replace("Chevereto", "Chevereto Free")); } }); @@ -1853,7 +1853,7 @@ CHV.obj.image_viewer.$loading = $(CHV.obj.image_viewer.loading); CHV.fn.system = { checkUpdates: function(callback) { $.ajax({ - url: "https://chevereto.com/api/get/info/", + url: "https://chevereto.com/api/get/info/free/", data: null, cache: false }) diff --git a/app/lib/chevereto.min.js b/app/lib/chevereto.min.js index 9fb8630..4a2ad71 100644 --- a/app/lib/chevereto.min.js +++ b/app/lib/chevereto.min.js @@ -75,7 +75,7 @@ $loading.removeClass("hidden");PF.fn.loading.inline($loading,{center:true,size:' $this.data("uploading",false);}}});CHV.fn.user_background={delete:{submit:function(){PF.obj.modal.form_data={action:"delete",delete:"background",owner:CHV.obj.resource.user.id};return true;},deferred:{success:{before:function(XHR){$("[data-content=user-background-cover-src]").css("background-image","none");$("[data-content=user-background-cover]").addClass("no-background").height("");$("[data-content=user-upload-background]").removeClass("hidden").show();$("[data-content=user-change-background]").hide();$("#top-bar").removeClass("transparent background-transparent");$("#top-bar-shade").remove();},done:function(XHR){PF.fn.modal.close(function(){PF.fn.growl.expirable(PF.fn._s("Profile background image deleted."));});}},error:function(XHR){PF.fn.growl.expirable(PF.fn._s("Error deleting profile background image."));}}}};CHV.str.mainform="[data-content=main-form]";CHV.obj.timezone={'selector':"[data-content=timezone]",'input':"#timezone-region"};$(document).on("keyup change",CHV.str.mainform+" :input",function(){if($(this).is("[name=username]")){$("[data-text=username]").text($(this).val());}});$(document).on("change",CHV.obj.timezone.input,function(){var value=$(this).val(),$timezone_combo=$("#timezone-combo-"+value);$timezone_combo.find("option:first").prop("selected",true);$(CHV.obj.timezone.selector).val($timezone_combo.val()).change();});$(document).on("change","[id^=timezone-combo-]",function(){var value=$(this).val();$(CHV.obj.timezone.selector).val(value).change();});$(document).on("keyup change blur","[name^=new-password]",function(){var $new_password=$("[name=new-password]"),$new_password_confirm=$("[name=new-password-confirm]"),hide=$new_password.val()==$new_password_confirm.val(),$warning=$new_password_confirm.closest(".input-password").find(".input-warning");if($(this).is($new_password_confirm)){$new_password_confirm.data("touched",true);} if($new_password_confirm.data("touched")){$warning.text(!hide?$warning.data("text"):"")[!hide?'removeClass':'addClass']('hidden-visibility');}});$(document).on("submit",CHV.obj.mainform,function(){switch($(this).data("type")){case"password":var $p1=$("[name=new-password]",this),$p2=$("[name=new-password-confirm]",this);if($p1.val()!==""||$p2.val()!==""){if($p1.val()!==$p2.val()){$p1.highlight();$p2.highlight();PF.fn.growl.expirable(PF.fn._s("Passwords don't match"));return false;}} break;}});$(document).on("change","[name=theme_tone]",function(){$("html")[0].className=$("html")[0].className.replace(/\btone-[\w-]+\b/g,'');$("html").addClass("tone-"+$(this).val());});$(document).on("change","[name=theme_top_bar_color]",function(){$("#top-bar, .top-bar").removeClass("black white").addClass($(this).val());});$(document).on("click","[data-action=check-for-updates]",function(){PF.fn.loading.fullscreen();CHV.fn.system.checkUpdates(function(XHR){PF.fn.loading.destroy("fullscreen");if(XHR.status!==200){PF.fn.growl.call(PF.fn._s("An error occurred. Please try again later."));return;} -var data=XHR.responseJSON.software;if(PF.fn.versionCompare(CHV.obj.system_info.version,data.current_version)==-1){PF.fn.modal.simple({title:PF.fn._s("Update available v%s",data.current_version),message:'

'+PF.fn._s('There is an update available for your system. You can automatic download and install this update or go to %s to proceed to download the file.','chevereto.com')+'

'+PF.fn._s('The release notes for this update are:')+'

'+''+'
'+PF.fn._s('Update now')+' '+PF.fn._s('or')+' '+PF.fn._s('cancel')+'
',html:true});}else{PF.fn.growl.call(PF.fn._s("Your website is running the latest version of Chevereto."));}});});if(typeof PF.fn.get_url_var("checkUpdates")!==typeof undefined){$("[data-action=check-for-updates]").click();} +var data=XHR.responseJSON.software;if(PF.fn.versionCompare(CHV.obj.system_info.version,data.current_version)==-1){PF.fn.modal.simple({title:PF.fn._s("Update available v%s",data.current_version),message:'

'+PF.fn._s('There is an update available for your system. You can automatic download and install this update or go to %s to proceed to download the file.','GitHub')+'

'+PF.fn._s('The release notes for this update are:')+'

'+''+'
'+PF.fn._s('Update now')+' '+PF.fn._s('or')+' '+PF.fn._s('cancel')+'
',html:true});}else{PF.fn.growl.call(PF.fn._s("Your website is running the latest version of Chevereto.").replace("Chevereto","Chevereto Free"));}});});if(typeof PF.fn.get_url_var("checkUpdates")!==typeof undefined){$("[data-action=check-for-updates]").click();} if($("body#image").exists()&&window.scrollY>0){$("#top-bar").removeClass("transparent");} $(document).on("click","[data-action=toggle-storage-https]",function(){CHV.fn.storage.toggleHttps($(this).closest("[data-content=storage]").data('storage-id'));});$(document).on("click","[data-action=toggle-storage-active]",function(){CHV.fn.storage.toggleActive($(this).closest("[data-content=storage]").data('storage-id'));});if($(CHV.fn.uploader.selectors.root).exists()){CHV.fn.uploader.$pasteCatcher=$("
",{contenteditable:"true",id:CHV.fn.uploader.selectors.paste.replace(/#/,"")});$("body").append(CHV.fn.uploader.$pasteCatcher);$(document).keydown(function(e){var key=e.keyCode;var ctrlDown=e.ctrlKey||e.metaKey;if(ctrlDown&&key==86&&!$(e.target).is(":input")){CHV.fn.uploader.$pasteCatcher.focus();}});window.addEventListener("paste",CHV.fn.uploader.pasteImageHandler);} $(document).on("click","[data-action=like]",function(){if(!PF.fn.is_user_logged()){PF.fn.modal.call({type:"login"});return;} @@ -95,7 +95,7 @@ e.preventDefault();} return;});$(document).on("click",".list-item [data-action=load-image]",function(e){loadImageListing($(this));e.preventDefault();e.stopPropagation();return;});function loadImageListing($this){console.log("a") $this.addClass("list-item-play-gif--loading");var $parent=$this.closest(".list-item");var $imageContainer=$(".image-container",$parent);console.log($imageContainer) var $image=$("img",$imageContainer);var md=".md";var imageSrc=$image.attr("src");var mdIndex=imageSrc.lastIndexOf(md);var loadSrc=imageSrc.substr(0,mdIndex)+imageSrc.substr(mdIndex+md.length,imageSrc.length);$imageContainer.append($imageContainer.html());$load=$parent.find(".image-container img").eq(1).attr("src",loadSrc).addClass("hidden");$load.imagesLoaded(function(){$this.remove();$image.remove();$(this.elements).removeClass("hidden");});}});if(typeof CHV=="undefined"){CHV={obj:{},fn:{},str:{}};} -CHV.obj.image_viewer={selector:"#image-viewer",container:"#image-viewer-container",navigation:".image-viewer-navigation",loading:"#image-viewer-loading",loader:"#image-viewer-loader",};CHV.obj.image_viewer.$container=$(CHV.obj.image_viewer.container);CHV.obj.image_viewer.$navigation=$(CHV.obj.image_viewer.navigation);CHV.obj.image_viewer.$loading=$(CHV.obj.image_viewer.loading);CHV.fn.system={checkUpdates:function(callback){$.ajax({url:"https://chevereto.com/api/get/info/",data:null,cache:false}).always(function(data,status,XHR){if(typeof callback=="function"){callback(XHR);}});}};CHV.fn.bindSelectableItems=function(){var el='content-listing-wrapper';if(!$("#"+el).exists()){$("[data-content=list-selection]").closest(".content-width").wrap("
");} +CHV.obj.image_viewer={selector:"#image-viewer",container:"#image-viewer-container",navigation:".image-viewer-navigation",loading:"#image-viewer-loading",loader:"#image-viewer-loader",};CHV.obj.image_viewer.$container=$(CHV.obj.image_viewer.container);CHV.obj.image_viewer.$navigation=$(CHV.obj.image_viewer.navigation);CHV.obj.image_viewer.$loading=$(CHV.obj.image_viewer.loading);CHV.fn.system={checkUpdates:function(callback){$.ajax({url:"https://chevereto.com/api/get/info/free/",data:null,cache:false}).always(function(data,status,XHR){if(typeof callback=="function"){callback(XHR);}});}};CHV.fn.bindSelectableItems=function(){var el='content-listing-wrapper';if(!$("#"+el).exists()){$("[data-content=list-selection]").closest(".content-width").wrap("
");} if(!$("[data-content=list-selection]").exists()||PF.fn.isDevice(["phone","phablet"])){return;} $("#content-listing-wrapper").selectable({filter:PF.obj.listing.selectors.list_item,cancel:".content-empty, .header, #tab-share, #tab-full-info, .viewer-title, .header-link, .top-bar, .content-listing-pagination *, #fullscreen-modal, #top-user, #background-cover, .list-item-desc, .list-item-image-tools, [data-action=load-image]",delay:5,selecting:function(event,ui){var $this=$(ui.selecting);var unselect=$this.hasClass("selected");CHV.fn.list_editor[(unselect?"unselect":"select")+"Item"]($this);},unselecting:function(event,ui){CHV.fn.list_editor.unselectItem($(ui.unselecting));}});};CHV.fn.isCachedImage=function(src){var image=new Image();image.src=src;return image.complete||image.width+image.height>0;};CHV.fn.viewerImageZoomClass=function(){if(CHV.obj.image_viewer.$container.hasClass("jscursor-zoom-in")){CHV.obj.image_viewer.$container.addClass("cursor-zoom-in").removeClass("jscursor-zoom-in");}};CHV.fn.viewerLoadImage=function(){if(CHV.obj.image_viewer.$loading.exists()){CHV.obj.image_viewer.$loading.removeClass("soft-hidden").css({zIndex:2});PF.fn.loading.inline(CHV.obj.image_viewer.$loading,{color:"white",size:"small",center:true,valign:true});CHV.obj.image_viewer.$loading.hide().fadeIn("slow");} $(CHV.obj.image_viewer.loader).remove();CHV.obj.image_viewer.image.html=CHV.obj.image_viewer.$container.html();CHV.obj.image_viewer.$container.prepend($(CHV.obj.image_viewer.image.html).css({top:0,zIndex:0}));CHV.obj.image_viewer.$container.find("img").eq(0).css("zIndex",1);CHV.obj.image_viewer.$container.find("img").eq(1).attr("src",CHV.obj.image_viewer.image.url).css({width:"100%",height:"auto"});CHV.obj.image_viewer.$container.find("img").eq(1).imagesLoaded(function(){CHV.obj.image_viewer.$container.find("img").eq(1).css({width:"",height:""});CHV.obj.image_viewer.$container.find("img").eq(0).remove();PF.fn.loading.destroy(CHV.obj.image_viewer.$loading);});};CHV.obj.embed_tpl={};CHV.obj.topBar={transparencyScrollToggle:function(){var Y=$(window).scrollTop();$("#top-bar")[(Y>0?"remove":"add")+"Class"]("transparent");}};CHV.fn.uploader={options:{image_types:["png","jpg","jpeg","gif","bmp"],max_filesize:"2 MB"},selectors:{root:"#anywhere-upload",queue:"#anywhere-upload-queue",queue_complete:".queue-complete",queue_item:".queue-item",close_cancel:"[data-button=close-cancel]",file:"#anywhere-upload-input",camera:"#anywhere-upload-input-camera",upload_item_template:"#anywhere-upload-item-template",item_progress_bar:"[data-content=progress-bar]",item_progress_percent:"[data-text=progress-percent]",failed_result:"[data-content=failed-upload-result]",fullscreen_mask:"#fullscreen-uploader-mask",dropzone:"#uploader-dropzone",paste:"#anywhere-upload-paste",},is_uploading:false,can_add:true,queue_status:"ready",files:{},results:{success:[],error:[]},toggleWorking:0,toggle:function(options,args){var $switch=$("[data-action=top-bar-upload]",".top-bar");var show=!$(CHV.fn.uploader.selectors.root).data("shown");var options=$.extend({callback:null,reset:true},options);PF.fn.growl.close(true);PF.fn.close_pops();if(this.toggleWorking==1||$(CHV.fn.uploader.selectors.root).is(":animated")||CHV.fn.uploader.is_uploading||($switch.data('login-needed')&&!PF.fn.is_user_logged()))return;this.toggleWorking=1;var uploadBoxHeight=$(CHV.fn.uploader.selectors.root).outerHeight()+"px";var uploadBoxTop=$(CHV.fn.uploader.selectors.root).css("top");var uploadBoxPush=(parseInt(uploadBoxHeight)+parseInt(uploadBoxTop))+"px";var animation={core:!show?("-"+uploadBoxPush):uploadBoxPush,time:500,},callbacks=function(){if(options.reset){CHV.fn.uploader.reset();} diff --git a/app/lib/functions.php b/app/lib/functions.php index dececd8..69f5796 100644 --- a/app/lib/functions.php +++ b/app/lib/functions.php @@ -682,25 +682,24 @@ function checkUpdates() { @set_time_limit(180); // Don't run forever $safe_time = 5; $max_execution_time = ini_get('max_execution_time'); // Store the limit - $update = G\fetch_url('http://chevereto.com/api/get/info'); + $update = G\fetch_url('http://chevereto.com/api/get/info/free'); if(isSafeToExecute() && $update) { $json = json_decode($update); - $release_notes = $json->software->release_notes; - $pos = strpos($release_notes, 'Affected files and folders'); - $release_notes = trim(substr($release_notes, 0, $pos)); + $release_notes = trim($json->software->release_notes); $latest_release = $json->software->current_version; // Notify only if not notified and if latest release is newer if(is_null(getSetting('update_check_notified_release')) || version_compare($latest_release, getSetting('update_check_notified_release'), '>')) { // Email notify $message = _s('There is an update available for your Chevereto based website.') . ' ' . _s('The release notes for this update are:') ; $message .= "\n\n"; - $firstBreak = strpos($release_notes, "\n"); - $release_notes = '' . rtrim(substr($release_notes, 0, $firstBreak)) . '' . substr($release_notes, $firstBreak); $message .= $release_notes . "\n\n"; - $message .= _s('You can apply this update directly from your %a or download it from %s and then manually install it.', ['%a' => ''._s('admin dashboard').'', '%s' => 'chevereto.com']) . "\n\n"; + $message .= _s('You can apply this update directly from your %a or download it from %s and then manually install it.', ['%a' => ''._s('admin dashboard').'', '%s' => 'GitHub']) . "\n\n"; $message .= '--' . "\n" . 'Chevereto' . "\n" . G\get_base_url(); $message = nl2br($message); - system_notification_email(['subject' => _s('Chevereto update available (v%s)', $latest_release), $latest_release, 'message' => $message]); + system_notification_email([ + 'subject' => str_replace('Chevereto', G_APP_NAME, _s('Chevereto update available (v%s)', $latest_release)), + 'message' => $message + ]); $settings_update = [ 'update_check_notified_release' => $latest_release, 'update_check_datetimegmt' => G\datetimegmt(), diff --git a/app/loader.php b/app/loader.php index 2c9d2a3..2ae25ca 100644 --- a/app/loader.php +++ b/app/loader.php @@ -74,6 +74,9 @@ if(Settings::get('cdn')) { } define('CHV_ROOT_URL_STATIC', defined('CHV_ROOT_CDN_URL') ? CHV_ROOT_CDN_URL : G_ROOT_URL); +// Define app repo URL +define('G_APP_GITHUB_REPO_URL', 'https://github.com/' . G_APP_GITHUB_OWNER . '/' . G_APP_GITHUB_REPO); + // Define the app theme if(!defined('G_APP_PATH_THEME')) { $theme_path = G_APP_PATH_THEMES . Settings::get('theme') . '/'; diff --git a/app/routes/route.dashboard.php b/app/routes/route.dashboard.php index 940108c..3b22d4b 100644 --- a/app/routes/route.dashboard.php +++ b/app/routes/route.dashboard.php @@ -122,8 +122,8 @@ $route = function($handler) { 'content' => (version_compare($chv_version['files'], $chv_version['db'], '<=') ? $chv_version['files'] : $chv_version['files'] . ' ('.$chv_version['db'].' DB) '._s('install update').'') . ' – ' . _s("check for updates") . '' ], 'chv_free' => [ - 'label' => 'Upgrade to paid', - 'content' => 'Upgrade to paid version to contribute with Chevereto development and to get tech support plus all features.', + 'label' => 'Get more', + 'content' => 'Upgrade to contribute with Chevereto development and to get more features', ], 'g_version' => [ 'label' => 'G\\', diff --git a/app/routes/route.image.php b/app/routes/route.image.php index 94f08e9..a54ac39 100644 --- a/app/routes/route.image.php +++ b/app/routes/route.image.php @@ -57,31 +57,14 @@ $route = function($handler) { } // Test remote image - if($image['file_resource']['type'] == 'url') { - $url = preg_replace('/^https:/i', 'http:', $image['file_resource']['chain']['image']); - $headers = G\getUrlHeaders($url, [CURLOPT_REFERER => G\get_current_url()]); // Add referrer for some CDN restrictions - $error_tpl = "Can't fetch file header from external storage server: %url (%e)"; - if($headers['http_code'] == 500) { // Internal (curl) error - $error_e = $headers['error']; - } else if($headers['http_code'] !== 200) { - $error_e = $headers['http_code']; - } - if($error_e) { - error_log(strtr($error_tpl, ['%url' => $url, '%e' => $error_e])); - if($headers['http_code'] !== 200) { - return $handler->issue404(); - } - } - } else { - if(!$image['file_resource']['chain']['image'] || !file_exists($image['file_resource']['chain']['image'])) { - //CHV\Image::delete($id); - return $handler->issue404(); - } - // Update is_animated flag - if($image['extension'] == 'gif' && !$image['is_animated'] && G\is_animated_image($image['file_resource']['chain']['image'])) { - CHV\Image::update($id, ['is_animated' => 1]); - $image['is_animated'] = 1; - } + if(!$image['file_resource']['chain']['image'] || !file_exists($image['file_resource']['chain']['image'])) { + //CHV\Image::delete($id); + return $handler->issue404(); + } + // Update is_animated flag + if($image['extension'] == 'gif' && !$image['is_animated'] && G\is_animated_image($image['file_resource']['chain']['image'])) { + CHV\Image::update($id, ['is_animated' => 1]); + $image['is_animated'] = 1; } $is_owner = $image['user']['id'] !== NULL ? ($image['user']['id'] == $logged_user['id']) : false; diff --git a/app/routes/route.update.php b/app/routes/route.update.php index 35cfc6f..68d5e51 100644 --- a/app/routes/route.update.php +++ b/app/routes/route.update.php @@ -3,6 +3,10 @@ $route = function($handler) { try { // Detect if Chevereto is installed if(CHV\Settings::get('chevereto_version_installed')) { + // Must be an admin + if(!CHV\Login::getUser()['is_admin']) { + G\redirect(); + } $update_script = CHV_APP_PATH_INSTALL . 'update/updater.php'; if(!file_exists($update_script)) { throw new Exception('Missing ' . G\absolute_to_relative($update_script), 100); diff --git a/app/themes/Peafowl/footer.php b/app/themes/Peafowl/footer.php index 8333eb4..9596a5f 100644 --- a/app/themes/Peafowl/footer.php +++ b/app/themes/Peafowl/footer.php @@ -1,5 +1,5 @@ - + diff --git a/app/themes/Peafowl/snippets/footer.js.php b/app/themes/Peafowl/snippets/footer.js.php index 26f0cea..3189dfa 100644 --- a/app/themes/Peafowl/snippets/footer.js.php +++ b/app/themes/Peafowl/snippets/footer.js.php @@ -21,6 +21,7 @@ PF.obj.config.json_api = ""; PF.obj.config.listing.items_per_page = ""; PF.obj.config.listing.device_to_columns = ; PF.obj.config.auth_token = ""; +PF.obj.config.github_url = ""; PF.obj.l10n = ;