Initial release

This commit is contained in:
Rodolfo Berrios 2016-08-18 17:39:31 -03:00
commit 94dab1c4f6
369 changed files with 241392 additions and 0 deletions

30
.htaccess Normal file
View file

@ -0,0 +1,30 @@
# Disable server signature
ServerSignature Off
# Disable directory listing (-indexes), Multiviews (-MultiViews) and enable Follow system links (+FollowSymLinks)
Options -Indexes
Options -MultiViews
Options +FollowSymLinks
<IfModule mod_rewrite.c>
RewriteEngine On
# If you have problems with the rewrite rules remove the "#" from the following RewriteBase line
# You will also have to change the path to reflect the path to your Chevereto installation
# If you are using alias is most likely that you will need this.
#RewriteBase /
# 404 images
# If you want to have your own fancy "image not found" image remove the "#" from RewriteCond and RewriteRule lines
# Make sure to apply the correct paths to reflect your current installation
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule images/.+\.(gif|jpe?g|png|bmp) - [NC,L,R=404]
#RewriteRule images/.+\.(gif|jpe?g|png|bmp) content/images/system/404.gif [NC,L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !\.(css|js|html|htm|rtf|rtx|svg|svgz|txt|xsd|xsl|xml|asf|asx|wax|wmv|wmx|avi|bmp|class|divx|doc|docx|exe|gif|gz|gzip|ico|jpe?g|jpe|mdb|mid|midi|mov|qt|mp3|m4a|mp4|m4v|mpeg|mpg|mpe|mpp|odb|odc|odf|odg|odp|ods|odt|ogg|pdf|png|pot|pps|ppt|pptx|ra|ram|swf|tar|tif|tiff|wav|wma|wri|xla|xls|xlsx|xlt|xlw|zip)$ [NC]
RewriteRule . index.php [L]
</IfModule>

54
README.md Normal file
View file

@ -0,0 +1,54 @@
<p align="center"><a href="https://chevereto.com/"><img src="https://chevereto.com/app/themes/v3/img/chevereto-large.png" alt="Chevereto"></a></p>
<p align="center">Chevereto is an image hosting script that allows you to create a beautiful and full featured image hosting website in your own server. It's your hosting and your rules, say goodbye to closures and restrictions. <a href="https://chevereto.com">Chevereto.com</a></p>
<p>&nbsp;</p>
<p align="center"><a href="https://chevereto.com/"><img src="https://chevereto.com/app/themes/v3/img/devices.png" alt=""></a></p>
Chevereto Free
=
<a href="https://chevereto.com/free" title="♫♪ Ha llegado tu tiempo, es el momento de Freeeeeeeeeeeeeeee"><img src="https://chevereto.com/app/themes/v3/img/chevereto-free-cover.jpg" alt="Chevereto Sugar Free Cola"></a>
###About this repo
This is the repository of Chevereto Free which has been forked from Chevereto 3.X series. Chevereto Free has the same look, feel and taste of our [paid version](https://chevereto.com/pricing) but it comes in a free package which includes all the basic image hosting functionalities. Free to use, foverer.
###Free vs paid Chevereto
Chevereto Free includes all the basic image hosting stuff but it comes without dedicated support. Paid Chevereto comes with all features, updates and support. The following table summarizes the differences between paid vs free.
| Item | Free | Paid |
|---------------------------------------------- |----------------- |------------------------ |
| Contribution to Chevereto | ☆ | ★★★★ |
| Access to latest features | Delayed | Always |
| 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 |
| Facebook, Twitter, Google and VK signup | No | Yes |
##Minimum system requirements
Make sure your server meets the minimum system requirements which are:
- Apache / NGiNX web server
- PHP 5.5.0 (standard libraries)
- MySQL 5.0 (ALL PRIVILEGES)
In most servers that's all you need. The system has a built-in system check that it will tell you right away when you have to fix some stuff in your server.
##Install
1. Download the [latest release](https://github.com/Chevereto/Chevereto-Free/releases/latest) of Chevereto Free
2. Upload the contents of your download to your server (usually the `public_html` folder)
3. Go to your website and follow the instructions
For additional install instructions refer to our [official documentation](https://chevereto.com/docs/install).
##Support
Chevereto Free doesn't include dedicated support. However, feel free to browse current and previous solved [support topics](https://chevereto.com/community/forums/tech-support.16/?prefix_id=2). If you need more help please consider to purchase a Chevereto license.
##License
Copyright 2016 [Rodolfo Berríos](http://rodolfoberrios.com), Chevereto Software E.I.R.L.
Permission is granted to anyone to use this software for **any purpose** except for distribution or re-distribution in its original and/or modified form. Any third-party distribution or re-distribution including but not limited to hosted applications based on the software must be approved by the copyright owner. The software is offered on an “as-is” basis and no warranty, either expressed or implied, is given.

11
app/.htaccess Normal file
View file

@ -0,0 +1,11 @@
<FilesMatch "\.php$">
# Apache 2.2
<IfModule !mod_authz_core.c>
Order Allow,Deny
Deny from all
</IfModule>
# Apache 2.4
<IfModule mod_authz_core.c>
Require all denied
</IfModule>
</FilesMatch>

3
app/app.php Normal file
View file

@ -0,0 +1,3 @@
<?php
define('G_APP_NAME', 'Chevereto Free');
define('G_APP_VERSION', '1.0.0');

View file

@ -0,0 +1,25 @@
<?php
/* --------------------------------------------------------------------
G\ library
http://gbackslash.com
@author Rodolfo Berrios A. <http://rodolfoberrios.com/>
Copyright (c) Rodolfo Berrios <inbox@rodolfoberrios.com> All rights reserved.
Licensed under the MIT license
http://opensource.org/licenses/MIT
--------------------------------------------------------------------- */
# Use this file to include / hook anything you want
# Any code in this file will be added just before the G\Handler
# NOTE: To use it in production you will need to rename this file to chevereto-hook.php
namespace CHV;
use G, Exception;
if(!defined('access') or !access) die('This file cannot be directly accessed.');

4868
app/content/languages/ar.po Normal file

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,28 @@
<?php
$translation_header = array (
'Project-Id-Version' => 'Chevereto V3',
'POT-Creation-Date' => '2016-08-12 17:45-0400',
'PO-Revision-Date' => '2016-08-12 17:45-0400',
'Last-Translator' => 'Rodolfo Berríos <inbox@rodolfoberrios.com>',
'Language-Team' => '',
'Language' => 'e',
'MIME-Version' => '1.0',
'Content-Type' => 'text/plain; charset=UTF-8',
'Content-Transfer-Encoding' => '8bit',
'X-Generator' => 'Poedit 1.8.8',
'X-Poedit-Basepath' => '.',
'Plural-Forms' => 'nplurals=2; plural=(n != 1);',
'X-Poedit-KeywordsList' => '_s;_se;_n:1,2;_ne:1,2;PF.fn._s;PF.fn._n:1,2',
'X-Poedit-SourceCharset' => 'UTF-8',
'X-Poedit-SearchPath-0' => '../../..',
'X-Poedit-SearchPathExcluded-0' => '../../../app/vendor',
);
$translation_plural = array (
'nplurals' => 2,
'plural' => '(n != 1)',
'formula' => '($n != 1)',
'function' => '$index = (int)(($n != 1)); return ($index < 2) ? $index : 2 - 1;',
);
$translation_table = [
];
?>

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

4625
app/content/languages/cs.po Normal file

File diff suppressed because it is too large Load diff

2219
app/content/languages/da.po Normal file

File diff suppressed because it is too large Load diff

4804
app/content/languages/de.po Normal file

File diff suppressed because it is too large Load diff

2882
app/content/languages/el.po Normal file

File diff suppressed because it is too large Load diff

5448
app/content/languages/en.po Normal file

File diff suppressed because it is too large Load diff

4804
app/content/languages/es.po Normal file

File diff suppressed because it is too large Load diff

2813
app/content/languages/fa.po Normal file

File diff suppressed because it is too large Load diff

4804
app/content/languages/fi.po Normal file

File diff suppressed because it is too large Load diff

4804
app/content/languages/fr.po Normal file

File diff suppressed because it is too large Load diff

4528
app/content/languages/hu.po Normal file

File diff suppressed because it is too large Load diff

3491
app/content/languages/id.po Normal file

File diff suppressed because it is too large Load diff

4768
app/content/languages/it.po Normal file

File diff suppressed because it is too large Load diff

4782
app/content/languages/ja.po Normal file

File diff suppressed because it is too large Load diff

3240
app/content/languages/ko.po Normal file

File diff suppressed because it is too large Load diff

4804
app/content/languages/nb.po Normal file

File diff suppressed because it is too large Load diff

4117
app/content/languages/nl.po Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,9 @@
You can quick and easy override any language string by putting lang_code.po files here.
For example, en.po file whit this contents:
#: START EXAMPLE
msgid "Upload and share your images."
msgstr "Upload and share your photos."
#: END EXAMPLE
Will replace the original msgid with the new msgstr.

3270
app/content/languages/pl.po Normal file

File diff suppressed because it is too large Load diff

3531
app/content/languages/pt.po Normal file

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

4820
app/content/languages/ru.po Normal file

File diff suppressed because it is too large Load diff

4038
app/content/languages/sk.po Normal file

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

2594
app/content/languages/sv.po Normal file

File diff suppressed because it is too large Load diff

3159
app/content/languages/tr.po Normal file

File diff suppressed because it is too large Load diff

4641
app/content/languages/uk.po Normal file

File diff suppressed because it is too large Load diff

3104
app/content/languages/vi.po Normal file

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

View file

@ -0,0 +1,72 @@
html, body {
height: 100%;
}
body {
background: #F4F4F4;
color: #333;
}
p, h1, h2, h3, ul {
margin: 20px 0;
}
a {
color: #00A7DA;
text-decoration: none;
}
a img { border: 0; }
#header {
position: relative;
height: 60px;
}
#logo {
position: absolute;
left: 30px;
bottom: -20px;
z-index: 100;
display: block;
}
#logo img {
width: 297px;
height: 55px;
display: inherit;
}
#content {
background: #FFF;
border: 1px solid #DDD;
border-radius: 10px;
padding: 20px 30px 30px 30px;
position: relative;
z-index: 1;
}
ul.errors {
margin: 20px;
}
ul.errors li {
margin: 10px;
list-style: disc;
}
#powered {
font-size: 0.93em;
color: #BBB;
text-shadow: 0 1px 0 #FFF;
text-align: center;
margin: 10px;
}
#powered a {
color: #BBB;
}
code {
background: #f5f2f0;
padding: 2px;
font-family: monospace;
border: 1px solid #DDD;
}

View file

@ -0,0 +1,52 @@
<?php
/* --------------------------------------------------------------------
Chevereto
http://chevereto.com/
@author Rodolfo Berrios A. <http://rodolfoberrios.com/>
<inbox@rodolfoberrios.com>
Copyright (C) Rodolfo Berrios A. All rights reserved.
BY USING THIS SOFTWARE YOU DECLARE TO ACCEPT THE CHEVERETO EULA
http://chevereto.com/license
--------------------------------------------------------------------- */
if(!defined('access') or !access) die('This file cannot be directly accessed.'); ?>
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title><?php echo $doctitle; ?></title>
<link rel="stylesheet" href="<?php echo G\absolute_to_url(CHV_PATH_PEAFOWL . 'peafowl.css'); ?>">
<link rel="stylesheet" href="<?php echo G\absolute_to_url(CHV_APP_PATH_SYSTEM . 'style.css'); ?>">
<link rel="stylesheet" href="//fonts.googleapis.com/css?family=Open+Sans:400,300,300italic,400italic,600,600italic,700,700italic,800,800italic&subset=latin,greek,cyrillic">
<link rel="shortcut icon" href="<?php echo G\absolute_to_url(CHV_APP_PATH_SYSTEM . 'favicon.png'); ?>">
<script>(function(w,d,u){w.readyQ=[];w.bindReadyQ=[];function p(x,y){if(x=="ready"){w.bindReadyQ.push(y);}else{w.readyQ.push(x);}};var a={ready:p,bind:p};w.$=w.jQuery=function(f){if(f===d||f===u){return a}else{p(f)}}})(window,document);</script>
</head>
<body>
<div class="c20 center-box">
<header id="header">
<div id="logo"><img src="<?php echo G\absolute_to_url(CHV_APP_PATH_SYSTEM . 'chevereto.png'); ?>" alt=""></div>
</header>
<div id="content">
<?php echo $html; ?>
</div>
<div id="powered">&copy; <a href="http://chevereto.com">Chevereto image hosting script</a></div>
</div>
</body>
<script src="<?php echo G\absolute_to_url(CHV_PATH_PEAFOWL . 'js/jquery.min.js'); ?>"></script>
<script src="<?php echo G\absolute_to_url(CHV_PATH_PEAFOWL . 'js/scripts.js'); ?>"></script>
<script>(function($,d){$.each(readyQ,function(i,f){$(f)});$.each(bindReadyQ,function(i,f){$(d).bind("ready",f)})})(jQuery,document)</script>
<script src="<?php echo G\absolute_to_url(CHV_PATH_PEAFOWL . 'peafowl.js'); ?>"></script>
<script>
PF.obj.config.base_url = "<?php echo G\get_base_url(); ?>";
PF.obj.l10n = <?php echo json_encode(CHV\get_translation_table()) ;?>;
</script>
<script src="<?php echo CHV\Render\versionize_src(G\Render\get_app_lib_file_url('chevereto.js')); ?>"></script>
</html>

878
app/install/installer.php Normal file
View file

@ -0,0 +1,878 @@
<?php
/* --------------------------------------------------------------------
Chevereto
http://chevereto.com/
@author Rodolfo Berrios A. <http://rodolfoberrios.com/>
<inbox@rodolfoberrios.com>
Copyright (C) Rodolfo Berrios A. All rights reserved.
BY USING THIS SOFTWARE YOU DECLARE TO ACCEPT THE CHEVERETO EULA
http://chevereto.com/license
--------------------------------------------------------------------- */
namespace CHV;
use G, Exception;
if(!defined('access') or !access) die('This file cannot be directly accessed.');
try {
if(!is_null(getSetting('chevereto_version_installed')) and !Login::getUser()['is_admin']) {
G\set_status_header(403);
die('Request denied. You must be an admin to be here.');
}
set_time_limit(600); // This could take up to 10 minutes...
$doctitles = [
'connect' => 'Connect to the database',
'ready' => 'Ready to install',
'finished' => 'Installation complete',
'settings' => 'Update settings.php',
'already' => 'Already installed',
'update' => 'Update needed',
'updated' => 'Update complete',
'update_failed' => 'Update failed'
];
$doing = 'connect'; // default initial state
$db_array = [
'db_host' => true,
'db_name' => true,
'db_user' => true,
'db_pass' => false,
'db_table_prefix' => false
];
$error = false;
$db_conn_error = "Can't connect to the target database. The server replied with this:<br>%s<br><br>Please fix your MySQL info.";
$settings_updates = [
'1.0.0' => [
'analytics_code' => NULL,
'auto_language' => 1,
'chevereto_version_installed' => G_APP_VERSION,
'cloudflare' => NULL,
'comment_code' => NULL,
'crypt_salt' => G\random_string(8),
'default_language' => 'en',
'default_timezone' => 'America/Santiago',
'email_from_email' => '', // no-reply@chevereto.com
'email_from_name' => 'Chevereto',
'email_incoming_email' => '', // inbox@chevereto.com
'email_mode' => 'mail',
'email_smtp_server' => NULL,
'email_smtp_server_password' => NULL,
'email_smtp_server_port' => NULL,
'email_smtp_server_security' => NULL,
'email_smtp_server_username' => NULL,
'enable_uploads' => 1,
'error_reporting' => 0,
'facebook' => 0,
'facebook_app_id' => NULL,
'facebook_app_secret' => NULL,
'flood_uploads_day' => '1000',
'flood_uploads_hour' => '500',
'flood_uploads_minute' => '50',
'flood_uploads_month' => '10000',
'flood_uploads_notify' => 0,
'flood_uploads_protection' => 1,
'flood_uploads_week' => '5000',
'google' => 0,
'google_client_id' => NULL,
'google_client_secret' => NULL,
'guest_uploads' => 1,
'listing_items_per_page' => 24,
'maintenance' => 0,
'recaptcha' => 0,
'recaptcha_private_key' => NULL,
'recaptcha_public_key' => NULL,
'recaptcha_threshold' => 5,
'theme' => 'Peafowl',
'twitter' => 0,
'twitter_api_key' => NULL,
'twitter_api_secret' => NULL,
'upload_filenaming' => 'original',
'upload_image_path' => 'images',
'upload_max_filesize_mb' => min(10, G\bytes_to_mb(G\get_ini_bytes(ini_get('upload_max_filesize')))),
'upload_storage_mode' => 'datefolder',
'upload_thumb_height' => '160',
'upload_thumb_width' => '160',
'website_description' => 'A free image hosting service powered by Chevereto',
'website_doctitle' => 'Chevereto image hosting',
'website_name' => 'Chevereto',
'website_explore_page' => 1,
'twitter_account' => 'chevereto',
'enable_signups' => 1,
'favicon_image' => 'favicon.png',
'logo_image' => 'logo.png',
'logo_vector' => 'logo.svg',
'theme_custom_css_code' => NULL,
'theme_custom_js_code' => NULL,
'website_keywords' => 'image sharing, image hosting, chevereto',
'logo_vector_enable' => 0,
'watermark_enable' => 0,
'watermark_image' => 'watermark.png',
'watermark_position' => 'center center',
'watermark_margin' => '10',
'watermark_opacity' => '50',
'api_v1_key' => G\random_string(32),
'listing_pagination_mode' => 'classic',
'show_nsfw_in_listings' => 0,
'show_banners_in_nsfw' => 0,
'website_privacy_mode' => 'public',
'website_content_privacy_mode' => 'default',
'show_nsfw_in_random_mode' => 0,
'cdn' => 0,
'cdn_url' => NULL,
'website_search' => 1,
'website_random' => 1,
'theme_logo_height' => NULL,
'theme_show_social_share' => 1,
'theme_show_embed_content' => 1,
'theme_show_embed_uploader' => 1,
'user_routing' => 1,
'require_user_email_confirmation' => 1,
'require_user_email_social_signup'=> 1,
'last_used_storage' => NULL,
'vk' => 0,
'vk_client_id' => NULL,
'vk_client_secret' => NULL,
'theme_download_button' => 1,
'theme_nsfw_upload_checkbox'=> 1,
'theme_tone' => 'light',
'theme_image_listing_sizing'=> 'fixed',
'listing_columns_phone' => '1',
'listing_columns_phablet' => '3',
'listing_columns_tablet' => '4',
'listing_columns_laptop' => '5',
'listing_columns_desktop' => '6',
'homepage_style' => 'landing',
'homepage_cover_image' => NULL,
'homepage_uids' => '1',
'homepage_endless_mode' => 0,
'user_image_avatar_max_filesize_mb' => '1',
'user_image_background_max_filesize_mb' => '2',
'theme_image_right_click' => 0,
'minify_enable' => 1,
'theme_show_exif_data' => 1,
'theme_top_bar_color' => 'white',
'theme_main_color' => NULL,
'theme_top_bar_button_color'=> 'blue',
'logo_image_homepage' => NULL,
'logo_vector_homepage' => NULL,
'homepage_cta_color' => 'green',
'homepage_cta_outline' => 0,
'watermark_enable_guest' => 1,
'watermark_enable_user' => 1,
'watermark_enable_admin' => 1,
'homepage_title_html' => NULL,
'homepage_paragraph_html' => NULL,
'homepage_cta_html' => NULL,
'homepage_cta_fn' => NULL,
'homepage_cta_fn_extra' => NULL,
'language_chooser_enable' => 1,
'languages_disable' => NULL,
'website_mode' => 'community',
'website_mode_personal_routing' => NULL, //'single_user_mode_routing'
'website_mode_personal_uid' => NULL, //'single_user_mode_id'
'enable_cookie_law' => 0,
'theme_nsfw_blur' => 0,
'watermark_target_min_width' => '100',
'watermark_target_min_height' => '100',
'watermark_percentage' => '4',
'watermark_enable_file_gif' => 0,
'id_padding' => '0', // 0-> Update | 5000-> new install
'upload_image_exif' => 1,
'upload_image_exif_user_setting' => 1,
'enable_expirable_uploads' => 1,
'upload_medium_size' => '500',
'upload_medium_fixed_dimension' => 'width',
'enable_followers' => 0,
'enable_likes' => 0,
'enable_consent_screen' => 0,
'user_minimum_age' => NULL,
'consent_screen_cover_image' => NULL,
'enable_redirect_single_upload' => 1,
'route_image' => 'image',
'route_album' => 'album',
'enable_duplicate_uploads' => 0,
'update_check_datetimegmt' => NULL,
'update_check_notified_release' => NULL,
'update_check_display_notification' => 1,
],
];
// Settings that must be renamed from NAME to NEW NAME and DELETE old NAME
$settings_rename = [
];
// Settings that must be renamed from NAME to NEW NAME and doesn't delete old NAME
$settings_switch = [
];
$chv_initial_settings = [];
foreach($settings_updates as $k => $v) {
if(is_null($v)) continue;
$chv_initial_settings += $v;
}
// Detect 2.X
try {
$is_2X = DB::get('info', ['key' => 'version']) ? true : false;
} catch(Exception $e) {
$is_2X = false;
}
$stats_query = 'TRUNCATE TABLE `%table_prefix%stats`;
INSERT INTO `%table_prefix%stats` (stat_id, stat_date_gmt, stat_type) VALUES ("1", NULL, "total") ON DUPLICATE KEY UPDATE stat_type=stat_type;
UPDATE `%table_prefix%stats` SET
stat_images = (SELECT IFNULL(COUNT(*),0) FROM `%table_prefix%images`),
stat_albums = (SELECT IFNULL(COUNT(*),0) FROM `%table_prefix%albums`),
stat_users = (SELECT IFNULL(COUNT(*),0) FROM `%table_prefix%users`),
stat_image_views = (SELECT IFNULL(SUM(image_views),0) FROM `%table_prefix%images`),
stat_disk_used = (SELECT IFNULL(SUM(image_size) + SUM(image_thumb_size) + SUM(image_medium_size),0) FROM `%table_prefix%images`)
WHERE stat_type = "total";
INSERT INTO `%table_prefix%stats` (stat_type, stat_date_gmt, stat_images, stat_image_views, stat_disk_used)
SELECT "date", DATE(image_date_gmt) AS date_gmt, COUNT(*) AS images, SUM(image_views) AS image_views, SUM(image_size + image_thumb_size + image_medium_size) AS disk_used FROM `%table_prefix%images` GROUP BY DATE(image_date_gmt);
INSERT INTO `%table_prefix%stats` (stat_type, stat_date_gmt, stat_users)
SELECT sb.stat_type, sb.stat_date_gmt, sb.stat_users
FROM (SELECT "date" AS stat_type, DATE(user_date_gmt) AS stat_date_gmt, COUNT(*) AS stat_users FROM `%table_prefix%users` GROUP BY DATE(user_date_gmt)) AS sb
ON DUPLICATE KEY UPDATE stat_users = sb.stat_users;
INSERT INTO `%table_prefix%stats` (stat_type, stat_date_gmt, stat_albums)
SELECT sb.stat_type, sb.stat_date_gmt, sb.stat_albums
FROM (SELECT "date" AS stat_type, DATE(album_date_gmt) AS stat_date_gmt, COUNT(*) AS stat_albums FROM `%table_prefix%albums` GROUP BY DATE(album_date_gmt)) AS sb
ON DUPLICATE KEY UPDATE stat_albums = sb.stat_albums;
UPDATE `%table_prefix%users` SET user_content_views = COALESCE((SELECT SUM(image_views) FROM `%table_prefix%images` WHERE image_user_id = user_id GROUP BY user_id), "0");';
// Fulltext engine
if(G\settings_has_db_info()) {
$db = DB::getInstance();
$fulltext_engine = version_compare($db->getAttr(\PDO::ATTR_SERVER_VERSION), '5.6', '<') ? 'MyISAM' : 'InnoDB';
}
// settings.php contains db
if(G\settings_has_db_info() and !$_POST) {
// Chevereto already installed?
$installed_version = getSetting('chevereto_version_installed');
$maintenance = getSetting('maintenance');
// Get the setting rows from DB (to avoid overwrite)
$db_settings_keys = [];
try {
$db_settings = DB::get('settings', 'all');
foreach($db_settings as $k => $v) {
$db_settings_keys[] = $v['setting_name'];
}
} catch(Exception $e) {}
// Update procedure
if((!empty($db_settings_keys) && count($chv_initial_settings) !== count($db_settings_keys)) || (!is_null($installed_version) and version_compare(G_APP_VERSION, $installed_version, '>'))) {
if(!array_key_exists(G_APP_VERSION, $settings_updates)) {
die('Fatal error: app/install is outdated. You need to re-upload app/install folder with the one from Chevereto ' . G_APP_VERSION);
}
// Get database schema
$schema = [];
$raw_schema = DB::queryFetchAll('SELECT * FROM information_schema.COLUMNS WHERE TABLE_SCHEMA="'.G_APP_DB_NAME.'" AND TABLE_NAME LIKE "'. G\get_app_setting('db_table_prefix') .'%";');
foreach($raw_schema as $k => $v) {
$TABLE = preg_replace('#'.G\get_app_setting('db_table_prefix').'#i', '', strtolower($v['TABLE_NAME']), 1);
$COLUMN = $v['COLUMN_NAME'];
if(!array_key_exists($TABLE, $schema)) {
$schema[$TABLE] = [];
}
$schema[$TABLE][$COLUMN] = $v;
}
// Remove triggers
$triggers_to_remove = [
'album_insert',
'album_delete',
'follow_insert',
'follow_delete',
'image_insert',
'image_update',
'image_delete',
'like_insert',
'like_delete',
'notification_insert',
'notification_update',
'notification_delete',
'user_insert',
'user_delete'
];
// Get DB triggers
$db_triggers = DB::queryFetchAll('SELECT TRIGGER_NAME FROM INFORMATION_SCHEMA.TRIGGERS');
if($db_triggers) {
$drop_trigger_sql = NULL;
foreach($db_triggers as $k => $v) {
$trigger = $v['TRIGGER_NAME'];
if(in_array($v['TRIGGER_NAME'], $triggers_to_remove)) {
$drop_trigger = 'DROP TRIGGER IF EXISTS `'.$v['TRIGGER_NAME'].'`;' . "\n";
$drop_trigger_sql .= $drop_trigger;
}
}
if(!is_null($drop_trigger_sql)) {
$drop_trigger_sql = rtrim($drop_trigger_sql, "\n");
$remove_triggers = FALSE;
$remove_triggers = DB::queryExec($drop_trigger_sql);
if(!$remove_triggers) {
Render\chevereto_die(NULL, 'To procced you will need to run these queries in your database server: <br><br> <textarea class="resize-vertical highlight r5">'.$drop_trigger_sql.'</textarea>', "Can't remove table triggers");
}
}
}
// Get DB indexes
$DB_indexes = [];
$raw_indexes = DB::queryFetchAll('SELECT DISTINCT TABLE_NAME, INDEX_NAME, INDEX_TYPE FROM INFORMATION_SCHEMA.STATISTICS WHERE TABLE_SCHEMA = "'.G_APP_DB_NAME.'"');
foreach($raw_indexes as $k => $v) {
$TABLE = preg_replace('#'.G\get_app_setting('db_table_prefix').'#i', '', strtolower($v['TABLE_NAME']), 1);
$INDEX_NAME = $v['INDEX_NAME'];
if(!array_key_exists($TABLE, $DB_indexes)) {
$DB_indexes[$TABLE] = [];
}
$DB_indexes[$TABLE][$INDEX_NAME] = $v;
}
// Get needed KEY indexes (only for tables that already exists)
$CHV_indexes = [];
foreach(new \DirectoryIterator(CHV_APP_PATH_INSTALL . 'sql') as $fileInfo) {
if($fileInfo->isDot() or $fileInfo->isDir() or !array_key_exists($fileInfo->getBasename('.sql'), $schema)) continue;
$crate_table = file_get_contents(realpath($fileInfo->getPathname()));
if(preg_match_all('/KEY [`\(]+(\w+)/', $crate_table, $matches)) {
$CHV_indexes[$fileInfo->getBasename('.sql')] = $matches[1];
}
}
// Get database engines
$engines = [];
$raw_engines = DB::queryFetchAll('SELECT TABLE_NAME, ENGINE FROM information_schema.TABLES WHERE TABLE_SCHEMA = "'.G_APP_DB_NAME.'"');
foreach($raw_engines as $k => $v) {
$TABLE = preg_replace('#'.G\get_app_setting('db_table_prefix').'#i', '', strtolower($v['TABLE_NAME']), 1);
$engines[$TABLE] = $v['ENGINE'];
}
// Set the right table schema changes per release
$update_table = [];
$sql_update = [];
// Turn ON maintenance mode (if needed)
if(!$maintenance) {
$sql_update[] = "UPDATE `%table_prefix%settings` SET `setting_value` = 1 WHERE `setting_name` = 'maintenance'; \n";
}
// SQLize the $update_table
$required_sql_files = [];
foreach($update_table as $version => $changes) {
foreach($changes as $table => $columns) {
if($table == 'query') continue;
$schema_table = $schema[$table];
$create_table = false;
// Create table if it doesn't exists
if(!array_key_exists($table, $schema) and !in_array($table, $required_sql_files)) {
$create_table = true;
} else {
// Special workaround for storages table
if($table=='storages' and !array_key_exists('storage_bucket', $schema_table)) {
$create_table = true;
}
}
// Missing table
if(!in_array($table, $required_sql_files) and $create_table) {
$sql_update[] = file_get_contents(CHV_APP_PATH_INSTALL . 'sql/'.$table.'.sql');
$required_sql_files[] = $table;
}
// If the table was added from scratch then skip the rest of the columns scheme
if(in_array($table, $required_sql_files)) {
continue;
}
// Is a table op..
if($columns['op']) {
switch($columns['op']) {
case 'ALTER':
// Duplicated index
if($DB_indexes[$table]['searchindex'] and strpos($columns['prop'], 'CREATE FULLTEXT INDEX `searchindex`') !== false) {
continue;
}
$sql_update[] = strtr('ALTER TABLE `%table_prefix%'.$table.'` %prop; %tail', ['%prop' => $columns['prop'], '%tail' => $columns['tail']]);
break;
}
continue;
}
// Check the columns scheme
foreach($columns as $column => $column_meta) {
$query = NULL; // reset
$schema_column = $schema_table[$column];
switch($column_meta['op']) {
case 'MODIFY':
if(array_key_exists($column, $schema[$table]) and ($schema_column['COLUMN_TYPE'] !== $column_meta['type'] or (preg_match('/DEFAULT NULL/i', $column_meta['prop']) and $schema_column['IS_NULLABLE'] == 'NO'))) {
$query = '`%column` %type';
}
break;
case 'CHANGE':
if(array_key_exists($column, $schema[$table])) {
$query = '`%column` `%to` %type';
}
break;
case 'ADD':
if(!array_key_exists($column, $schema[$table])) {
$query = '`%column` %type';
}
break;
}
if(!is_null($query)) {
$stock_tr = ['op', 'type', 'to', 'prop', 'tail'];
$meta_tr = [];
foreach($stock_tr as $v) {
$meta_tr['%'.$v] = $column_meta[$v];
}
$sql_update[] = strtr('ALTER TABLE `%table_prefix%'.$table.'` %op ' . $query . ' %prop; %tail', array_merge(['%column' => $column], $meta_tr));
}
}
}
if($changes['query']) {
if(version_compare($version, $installed_version, '>')) {
$sql_update[] = $changes['query'];
}
}
}
// Fix the missing KEY indexes
foreach($CHV_indexes as $table => $indexes) {
$field_prefix = DB::getFieldPrefix($table);
foreach($indexes as $index) {
if($index == 'searchindex' or $index == $field_prefix . '_id' or !G\starts_with($field_prefix . '_', $index)) continue;
if(!array_key_exists($index, $DB_indexes[$table])) {
$sql_update[] = 'ALTER TABLE `%table_prefix%' . $table . '` ADD INDEX `' . $index . '` (`' . $index . '`);';
}
}
}
// Merge settings and version changes
$updates_stock = [];
foreach(array_merge($settings_updates, $update_table) as $k => $v) {
if($k == '3.0.0') continue;
$updates_stock[] = $k;
}
// Flat settings
$settings_flat = [];
// Settings workaround
foreach($updates_stock as $k) {
$sql = NULL; // reset the pointer
if(is_array($settings_updates[$k])) {
foreach($settings_updates[$k] as $k => $v) {
$settings_flat[$k] = $v;
// Wait a second... Avoid overwrites
if(in_array($k, $db_settings_keys)) {
continue;
}
$value = (is_null($v) ? "NULL" : "'".$v."'");
$sql .= "INSERT INTO `%table_prefix%settings` (setting_name, setting_value, setting_default, setting_typeset) VALUES ('".$k."', ".$value.", ".$value.", '" . Settings::getType($v) . "'); " . "\n";
}
}
if($sql) {
$sql_update[] = $sql;
}
}
// Renamed settings (actually updated values + remove old one)
$settings_get = Settings::get();
foreach($settings_rename as $k => $v) {
if(array_key_exists($k, $settings_get)) {
// Typeset is set in the INSERT statement above
$value = (is_null($settings_get[$k]) ? "NULL" : "'".$settings_get[$k]."'");
$sql_update[] = "UPDATE `%table_prefix%settings` SET `setting_value` = " . $value . " WHERE `setting_name` = '" . $v . "';" . "\n" . "DELETE FROM `%table_prefix%settings` WHERE `setting_name` = '" . $k . "';";
}
}
// Switched settings (as rename but with update of the old key)
foreach($settings_switch as $version => $keys) {
if(!version_compare($version, $installed_version, '>')) {
continue;
}
foreach($keys as $k => $v) {
if(!array_key_exists($k, $settings_get)) {
continue;
}
$value = (is_null($settings_get[$k]) ? "NULL" : "'".$settings_get[$k]."'");
$value_default = (is_null($settings_flat[$k]) ? "NULL" : "'".$settings_flat[$k]."'");
$sql_update[] = "UPDATE `%table_prefix%settings` SET `setting_value` = " . $value . ", `setting_typeset` = '" . Settings::getType($settings_flat[$k]) . "' WHERE `setting_name` = '" . $v . "';" . "\n" . "UPDATE `%table_prefix%settings` SET `setting_value` = " . $value_default . ", `setting_default` = " . $value_default . " WHERE `setting_name` = '" . $k . "';";
}
}
// Always update to the target version
$sql_update[] = 'UPDATE `%table_prefix%settings` SET `setting_value` = "' . G_APP_VERSION . '" WHERE `setting_name` = "chevereto_version_installed";';
// Revert maintenance (if needed)
if(!$maintenance) {
$sql_update[] = 'UPDATE `%table_prefix%settings` SET `setting_value` = 0 WHERE `setting_name` = "maintenance";';
}
$sql_update = join("\r\n", $sql_update);
// Replace the %table_storage% and %table_prefix% thing
$sql_update = strtr($sql_update, [
'%table_prefix%' => G\get_app_setting('db_table_prefix'),
'%table_engine%' => $fulltext_engine
]);
// Remove extra white spaces and line breaks
$sql_update = preg_replace('/[ \t]+/', ' ', preg_replace('/\s*$^\s*/m', "\n", $sql_update));
if(isset($_REQUEST['debug'])) {
G\debug($sql_update);
die();
}
try {
$db = DB::getInstance();
$db->query($sql_update);
$updated = $db->exec();
if($updated) {
$chevereto_version_installed = DB::get('settings', ['name' => 'chevereto_version_installed'])[0]['setting_value'];
if(G_APP_VERSION !== $chevereto_version_installed) {
throw new Exception(strtr('Make sure that the current database user %u has ALL PRIVILEGES granted over the %t table.', [
'%u' => G\get_app_setting('db_user'),
'%t' => G\get_app_setting('db_name'),
]));
}
}
$doing = 'updated';
} catch(Exception $e) {
$error = true;
$error_message = $e->getMessage();
$doing = 'update_failed';
}
} else {
try {
$db = DB::getInstance();
} catch(Exception $e) {
$error = true;
$error_message = sprintf($db_conn_error, $e->getMessage());
}
$doing = $error ? 'connect' : 'ready';
if(!is_null($installed_version)) {
$doing = 'already';
}
}
}
if(isset($_POST['username']) and !in_array($doing, ['already', 'update'])) {
$doing = 'ready';
}
if($_POST) {
switch($doing) {
// First case, need to connect to a working database
case 'connect':
$db_details = [];
foreach($db_array as $k => $v) {
if($v and $_POST[$k] == '') {
$error = true;
break;
}
$db_details[ltrim($k, 'db_')] = isset($_POST[$k]) ? $_POST[$k] : NULL;
}
if($error) {
$error_message = 'Please fill the database details.';
} else {
// Details are complete. Lets check if the DB
$db_details['driver'] = 'mysql';
try {
$db = new DB($db_details); // Had to initiate a new instance for the new connection params
} catch(Exception $e) {
$error = true;
$error_message = sprintf($db_conn_error, $e->getMessage());
}
if(!$error) {
// MySQL connection OK. Now, populate this values to settings.php
$settings_php = ['<?php'];
foreach($db_details as $k => $v) {
$settings_php[] = '$settings[\'db_'.$k.'\'] = \''.$v.'\';';
}
$settings_php[] = '$settings[\'debug_level\'] = 1;';
$settings_php = implode("\n", $settings_php);
$settings_file = G_APP_PATH . 'settings.php';
$fh = @fopen($settings_file, 'w');
if(!$fh or !fwrite($fh, $settings_php)) {
$doing = 'settings';
} else {
$doing = 'ready';
}
@fclose($fh);
// Reset opcache in this file
if(function_exists('opcache_invalidate')) {
@opcache_invalidate($settings_file, TRUE);
}
}
// Ready to install
if($doing == 'ready') {
/*@include(G_APP_PATH . 'settings.php');
if(!G\settings_has_db_info()) {
sleep(3); // nifty hack to prevent cache issues (if any)
}*/
G\redirect('install');
}
}
break;
// Ready to install
case 'ready':
// Input validations
if(!filter_var($_POST['email'], FILTER_VALIDATE_EMAIL)) {
$input_errors['email'] = _s('Invalid email');
}
if(!User::isValidUsername($_POST['username'])) {
$input_errors['username'] = _s('Invalid username');
}
if(!preg_match('/'.getSetting('user_password_pattern').'/', $_POST['password'])) {
$input_errors['password'] = _s('Invalid password');
}
if(!filter_var($_POST['email_from_email'], FILTER_VALIDATE_EMAIL)) {
$input_errors['email_from_email'] = _s('Invalid email');
}
if(!filter_var($_POST['email_incoming_email'], FILTER_VALIDATE_EMAIL)) {
$input_errors['email_incoming_email'] = _s('Invalid email');
}
if(!in_array($_POST['website_mode'], ['community', 'personal'])) {
$input_errors['website_mode'] = _s('Invalid website mode');
}
if(count($input_errors) > 0) {
$error = true;
$error_message = 'Please correct your data to continue.';
} else {
try {
$create_table = [];
foreach(new \DirectoryIterator(CHV_APP_PATH_INSTALL . 'sql') as $fileInfo) {
if($fileInfo->isDot() or $fileInfo->isDir()) continue;
$create_table[$fileInfo->getBasename('.sql')] = realpath($fileInfo->getPathname());
}
$install_sql = 'SET FOREIGN_KEY_CHECKS=0;' . "\n";
if($is_2X) {
// Need to sync this to avoid bad datefolder mapping due to MySQL time != PHP time
// In Chevereto v2.X date was TIMESTAMP and in v3.X is DATETIME
$DT = new \DateTime();
$offset = $DT->getOffset();
$offsetHours = round(abs($offset) / 3600);
$offsetMinutes = round((abs($offset) - $offsetHours * 3600) / 60);
$offset = ($offset < 0 ? '-' : '+').(strlen($offsetHours) < 2 ? '0' : '').$offsetHours.':'.(strlen($offsetMinutes) < 2 ? '0' : '').$offsetMinutes;
$install_sql .= "SET time_zone = '".$offset."';";
$install_sql .= "
ALTER TABLE `chv_images`
MODIFY `image_id` bigint(32) NOT NULL AUTO_INCREMENT,
MODIFY `image_name` varchar(255),
MODIFY `image_date` DATETIME,
CHANGE `image_type` `image_extension` varchar(255),
CHANGE `uploader_ip` `image_uploader_ip` varchar(255),
CHANGE `storage_id` `image_storage_id` bigint(32),
DROP `image_delete_hash`,
ADD `image_date_gmt` datetime NOT NULL AFTER `image_date`,
ADD `image_title` varchar(100) NOT NULL,
ADD `image_description` text,
ADD `image_nsfw` tinyint(1) NOT NULL DEFAULT '0',
ADD `image_user_id` bigint(32) DEFAULT NULL,
ADD `image_album_id` bigint(32) DEFAULT NULL,
ADD `image_md5` varchar(32) NOT NULL,
ADD `image_storage_mode` enum('datefolder','direct','old') NOT NULL DEFAULT 'datefolder',
ADD `image_original_filename` text NOT NULL,
ADD `image_original_exifdata` longtext,
ADD `image_views` bigint(32) NOT NULL DEFAULT '0',
ADD `image_category_id` bigint(32) DEFAULT NULL,
ADD `image_chain` tinyint(128) NOT NULL,
ADD `image_thumb_size` int(11) NOT NULL,
ADD `image_medium_size` int(11) NOT NULL DEFAULT '0',
ADD `image_expiration_date_gmt` datetime DEFAULT NULL,
ADD `image_likes` bigint(32) NOT NULL DEFAULT '0',
ADD INDEX `image_name` (`image_name`),
ADD INDEX `image_size` (`image_size`),
ADD INDEX `image_width` (`image_width`),
ADD INDEX `image_height` (`image_height`),
ADD INDEX `image_date_gmt` (`image_date_gmt`),
ADD INDEX `image_nsfw` (`image_nsfw`),
ADD INDEX `image_user_id` (`image_user_id`),
ADD INDEX `image_album_id` (`image_album_id`),
ADD INDEX `image_storage_id` (`image_storage_id`),
ADD INDEX `image_md5` (`image_md5`),
ADD INDEX `image_likes` (`image_views`),
ADD INDEX `image_views` (`image_views`),
ADD INDEX `image_category_id` (`image_category_id`),
ADD INDEX `image_expiration_date_gmt` (`image_expiration_date_gmt`),
ENGINE=".$fulltext_engine.";
UPDATE `chv_images`
SET `image_date_gmt` = `image_date`,
`image_storage_mode` = CASE
WHEN `image_storage_id` IS NULL THEN 'datefolder'
WHEN `image_storage_id` = 0 THEN 'datefolder'
WHEN `image_storage_id` = 1 THEN 'old'
WHEN `image_storage_id` = 2 THEN 'direct'
END,
`image_storage_id` = NULL;
CREATE FULLTEXT INDEX searchindex ON `chv_images`(image_name, image_title, image_description, image_original_filename);
RENAME TABLE `chv_info` to `_chv_info`;
RENAME TABLE `chv_options` to `_chv_options`;
RENAME TABLE `chv_storages` to `_chv_storages`;";
// Don't create the images table
unset($create_table['images']);
// Inject the old definitions value
$chv_initial_settings['crypt_salt'] = $_POST['crypt_salt'];
$table_prefix = 'chv_';
} else {
$table_prefix = G\get_app_setting('db_table_prefix');
}
foreach($create_table as $k => $v) {
$install_sql .= strtr(file_get_contents($v), [
'%table_prefix%' => $table_prefix,
'%table_engine%' => $fulltext_engine
]) . "\n\n";
}
// id padding for long faked public IDs
$chv_initial_settings['id_padding'] = 5000;
if($_POST['website_mode'] == 'personal') {
$chv_initial_settings['website_mode'] = 'personal';
}
// Stats (since 3.7.0)
$install_sql .= strtr($stats_query, [
'%table_prefix%' => $table_prefix,
'%table_engine%' => $fulltext_engine
]);
if(isset($_REQUEST['debug'])) {
G\debug($install_sql);
die();
}
// Do the DB magic
$db = DB::getInstance();
$db->query($install_sql);
$db->exec();
$db->closeCursor();
// Insert the default settings
$db->beginTransaction();
$db->query('INSERT INTO `'.DB::getTable('settings').'` (setting_name, setting_value, setting_default, setting_typeset) VALUES (:name, :value, :value, :typeset)');
foreach($chv_initial_settings as $k => $v) {
$db->bind(':name', $k);
$db->bind(':value', $v);
$db->bind(':typeset', ($v===0 or $v===1) ? 'bool' : 'string');
$db->exec();
}
if($db->endTransaction()) {
// Create admin and his password
$insert_admin = User::insert([
'username' => $_POST['username'],
'email' => $_POST['email'],
'is_admin' => 1,
'language' => $chv_initial_settings['default_language'],
'timezone' => $chv_initial_settings['default_timezone']
]);
Login::addPassword($insert_admin, $_POST['password']);
// Add admin user as the personal mode guy
if($_POST['website_mode'] == 'personal') {
$db->update('settings', ['setting_value' => 'me'], ['setting_name' => 'website_mode_personal_routing']);
$db->update('settings', ['setting_value' => $insert_admin], ['setting_name' => 'website_mode_personal_uid']);
}
// Insert the email settings
$db->update('settings', ['setting_value' => $_POST['email_from_email']], ['setting_name' => 'email_from_email']);
$db->update('settings', ['setting_value' => $_POST['email_incoming_email']], ['setting_name' => 'email_incoming_email']);
$doing = 'finished';
}
} catch(Exception $e) {
$error = true;
$error_message = "Can't create admin user:<br>" . $e->getMessage();
}
}
break;
}
}
$doctitle = $doctitles[$doing].' - Chevereto ' . get_chevereto_version(true);
$system_template = CHV_APP_PATH_SYSTEM . 'template.php';
$install_template = CHV_APP_PATH_INSTALL . 'template/'.$doing.'.php';
if(file_exists($install_template)) {
ob_start();
require_once($install_template);
$html = ob_get_contents();
ob_end_clean();
} else {
die("Can't find " . G\absolute_to_relative($install_template));
}
if(!@require_once($system_template)) {
die("Can't find " . G\absolute_to_relative($system_template));
}
die(); // Terminate any remaining execution
} catch (Exception $e) {
G\exception_to_error($e);
}

View file

@ -0,0 +1,22 @@
DROP TABLE IF EXISTS `%table_prefix%albums`;
CREATE TABLE `%table_prefix%albums` (
`album_id` bigint(32) NOT NULL AUTO_INCREMENT,
`album_name` varchar(100) NOT NULL,
`album_user_id` bigint(32) NOT NULL,
`album_date` datetime NOT NULL,
`album_date_gmt` datetime NOT NULL,
`album_creation_ip` varchar(255) NOT NULL,
`album_privacy` enum('public','password','private','private_but_link','custom') DEFAULT 'public',
`album_privacy_extra` text,
`album_password` text,
`album_image_count` bigint(32) NOT NULL DEFAULT '0',
`album_description` text,
`album_likes` bigint(32) NOT NULL DEFAULT '0',
PRIMARY KEY (`album_id`),
KEY `album_user_id` (`album_user_id`),
KEY `album_date_gmt` (`album_date_gmt`),
KEY `album_privacy` (`album_privacy`),
KEY `album_image_count` (`album_image_count`),
KEY `album_creation_ip` (`album_creation_ip`),
FULLTEXT KEY `searchindex` (`album_name`,`album_description`)
) ENGINE=%table_engine% DEFAULT CHARSET=utf8;

View file

@ -0,0 +1,9 @@
DROP TABLE IF EXISTS `%table_prefix%categories`;
CREATE TABLE `%table_prefix%categories` (
`category_id` bigint(32) NOT NULL AUTO_INCREMENT,
`category_name` varchar(32) NOT NULL,
`category_url_key` varchar(32) NOT NULL,
`category_description` text,
PRIMARY KEY (`category_id`),
UNIQUE KEY `url_key` (`category_url_key`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

View file

@ -0,0 +1,12 @@
DROP TABLE IF EXISTS `%table_prefix%confirmations`;
CREATE TABLE `%table_prefix%confirmations` (
`confirmation_id` bigint(32) NOT NULL AUTO_INCREMENT,
`confirmation_user_id` bigint(32) NOT NULL,
`confirmation_type` enum('account-activate','account-change-email','account-password-forgot') NOT NULL,
`confirmation_date` datetime NOT NULL,
`confirmation_date_gmt` datetime NOT NULL,
`confirmation_token_hash` varchar(255) NOT NULL,
`confirmation_status` enum('active','valid','invalid') NOT NULL,
`confirmation_extra` text,
PRIMARY KEY (`confirmation_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

View file

@ -0,0 +1,20 @@
DROP TABLE IF EXISTS `%table_prefix%deletions`;
CREATE TABLE `%table_prefix%deletions` (
`deleted_id` bigint(32) NOT NULL AUTO_INCREMENT,
`deleted_date_gmt` datetime NOT NULL,
`deleted_content_id` bigint(32) NOT NULL,
`deleted_content_date_gmt` datetime NOT NULL,
`deleted_content_user_id` bigint(32) DEFAULT NULL,
`deleted_content_ip` varchar(255) NOT NULL,
`deleted_content_md5` varchar(32) DEFAULT NULL,
`deleted_content_original_filename` varchar(255) DEFAULT NULL,
`deleted_content_views` bigint(32) NOT NULL DEFAULT '0',
`deleted_content_likes` bigint(32) NOT NULL DEFAULT '0',
PRIMARY KEY (`deleted_id`),
KEY `deleted_content_id` (`deleted_content_id`),
KEY `deleted_content_user_id` (`deleted_content_user_id`),
KEY `deleted_content_ip` (`deleted_content_ip`),
KEY `deleted_content_md5` (`deleted_content_md5`),
KEY `deleted_content_views` (`deleted_content_views`),
KEY `deleted_content_likes` (`deleted_content_likes`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

View file

@ -0,0 +1,12 @@
DROP TABLE IF EXISTS `%table_prefix%follows`;
CREATE TABLE `%table_prefix%follows` (
`follow_id` bigint(32) NOT NULL AUTO_INCREMENT,
`follow_date` datetime NOT NULL,
`follow_date_gmt` datetime NOT NULL,
`follow_user_id` bigint(32) NOT NULL,
`follow_followed_user_id` bigint(32) NOT NULL,
`follow_ip` varchar(255) NOT NULL,
PRIMARY KEY (`follow_id`),
KEY `follow_user_id` (`follow_user_id`),
KEY `follow_followed_user_id` (`follow_followed_user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

View file

@ -0,0 +1,11 @@
DROP TABLE IF EXISTS `%table_prefix%id_reservations`;
CREATE TABLE `%table_prefix%id_reservations` (
`id_reservation_id` bigint(32) NOT NULL AUTO_INCREMENT,
`id_reservation_date_gmt` datetime NOT NULL,
`id_reservation_reserved_id` bigint(32) NOT NULL,
`id_reservation_next_id` bigint(32) NOT NULL,
PRIMARY KEY (`id_reservation_id`),
KEY `id_reservation_date_gmt` (`id_reservation_date_gmt`),
KEY `id_reservation_reserved_id` (`id_reservation_reserved_id`),
KEY `id_reservation_next_id` (`id_reservation_next_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

View file

@ -0,0 +1,47 @@
DROP TABLE IF EXISTS `%table_prefix%images`;
CREATE TABLE `%table_prefix%images` (
`image_id` bigint(32) NOT NULL AUTO_INCREMENT,
`image_name` varchar(255) NOT NULL,
`image_extension` varchar(255) NOT NULL,
`image_size` int(11) NOT NULL,
`image_width` int(11) NOT NULL,
`image_height` int(11) NOT NULL,
`image_date` datetime NOT NULL,
`image_date_gmt` datetime NOT NULL,
`image_title` varchar(100) DEFAULT NULL,
`image_description` text,
`image_nsfw` tinyint(1) NOT NULL DEFAULT '0',
`image_user_id` bigint(32) DEFAULT NULL,
`image_album_id` bigint(32) DEFAULT NULL,
`image_uploader_ip` varchar(255) NOT NULL,
`image_storage_mode` enum('datefolder','direct','old') NOT NULL DEFAULT 'datefolder',
`image_storage_id` bigint(32) DEFAULT NULL,
`image_md5` varchar(32) NOT NULL,
`image_original_filename` varchar(255) NOT NULL,
`image_original_exifdata` longtext,
`image_views` bigint(32) NOT NULL DEFAULT '0',
`image_category_id` bigint(32) DEFAULT NULL,
`image_chain` tinyint(128) NOT NULL,
`image_thumb_size` int(11) NOT NULL,
`image_medium_size` int(11) NOT NULL DEFAULT '0',
`image_expiration_date_gmt` datetime DEFAULT NULL,
`image_likes` bigint(32) NOT NULL DEFAULT '0',
`image_is_animated` tinyint(1) NOT NULL DEFAULT '0',
PRIMARY KEY (`image_id`),
KEY `image_name` (`image_name`),
KEY `image_size` (`image_size`),
KEY `image_width` (`image_width`),
KEY `image_height` (`image_height`),
KEY `image_date_gmt` (`image_date_gmt`),
KEY `image_nsfw` (`image_nsfw`),
KEY `image_user_id` (`image_user_id`),
KEY `image_album_id` (`image_album_id`),
KEY `image_storage_id` (`image_storage_id`),
KEY `image_md5` (`image_md5`),
KEY `image_views` (`image_views`),
KEY `image_category_id` (`image_category_id`),
KEY `image_expiration_date_gmt` (`image_expiration_date_gmt`),
KEY `image_likes` (`image_likes`),
KEY `image_is_animated` (`image_is_animated`),
FULLTEXT KEY `searchindex` (`image_name`,`image_title`,`image_description`,`image_original_filename`)
) ENGINE=%table_engine% DEFAULT CHARSET=utf8;

View file

@ -0,0 +1,13 @@
DROP TABLE IF EXISTS `%table_prefix%ip_bans`;
CREATE TABLE `%table_prefix%ip_bans` (
`ip_ban_id` bigint(20) NOT NULL AUTO_INCREMENT,
`ip_ban_date` datetime NOT NULL,
`ip_ban_date_gmt` datetime NOT NULL,
`ip_ban_expires` datetime DEFAULT NULL,
`ip_ban_expires_gmt` datetime DEFAULT NULL,
`ip_ban_ip` varchar(255) NOT NULL,
`ip_ban_message` longtext,
PRIMARY KEY (`ip_ban_id`),
KEY `ip_ban_date_gmt` (`ip_ban_date_gmt`),
UNIQUE KEY `ip_ban_ip` (`ip_ban_ip`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

18
app/install/sql/likes.sql Normal file
View file

@ -0,0 +1,18 @@
DROP TABLE IF EXISTS `%table_prefix%likes`;
CREATE TABLE `%table_prefix%likes` (
`like_id` bigint(32) NOT NULL AUTO_INCREMENT,
`like_date` datetime NOT NULL,
`like_date_gmt` datetime NOT NULL,
`like_user_id` bigint(32) DEFAULT NULL,
`like_content_type` enum('image') DEFAULT NULL,
`like_content_id` bigint(32) NOT NULL,
`like_content_user_id` bigint(32) DEFAULT NULL,
`like_ip` varchar(255) NOT NULL,
PRIMARY KEY (`like_id`),
KEY `like_date_gmt` (`like_date_gmt`),
KEY `like_user_id` (`like_user_id`),
KEY `like_content_type` (`like_content_type`),
KEY `like_content_id` (`like_content_id`),
KEY `like_content_user_id` (`like_content_user_id`),
KEY `like_ip` (`like_ip`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

View file

@ -0,0 +1,18 @@
DROP TABLE IF EXISTS `%table_prefix%logins`;
CREATE TABLE `%table_prefix%logins` (
`login_id` bigint(32) NOT NULL AUTO_INCREMENT,
`login_user_id` bigint(32) NOT NULL,
`login_type` enum('password','session','cookie','facebook','twitter','google','vk') NOT NULL,
`login_ip` varchar(255) DEFAULT NULL,
`login_hostname` text,
`login_date` datetime NOT NULL,
`login_date_gmt` datetime NOT NULL,
`login_resource_id` varchar(255) DEFAULT NULL,
`login_resource_name` text,
`login_resource_avatar` text,
`login_resource_url` text,
`login_secret` text DEFAULT NULL COMMENT 'The secret part',
`login_token_hash` text COMMENT 'Hashed complement to secret if needed',
PRIMARY KEY (`login_id`),
KEY `login_user_id` (`login_user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

View file

@ -0,0 +1,19 @@
DROP TABLE IF EXISTS `%table_prefix%notifications`;
CREATE TABLE `%table_prefix%notifications` (
`notification_id` bigint(32) NOT NULL AUTO_INCREMENT,
`notification_date_gmt` datetime NOT NULL,
`notification_user_id` bigint(32) NOT NULL,
`notification_trigger_user_id` bigint(32) DEFAULT NULL,
`notification_type` enum('follow','like') NOT NULL,
`notification_content_type` enum('user','image') NOT NULL,
`notification_type_id` bigint(32) NOT NULL COMMENT 'type_id based on action (type) table',
`notification_is_read` tinyint(1) NOT NULL DEFAULT '0',
PRIMARY KEY (`notification_id`),
KEY `notification_date_gmt` (`notification_date_gmt`),
KEY `notification_user_id` (`notification_user_id`),
KEY `notification_trigger_user_id` (`notification_trigger_user_id`),
KEY `notification_type` (`notification_type`),
KEY `notification_content_type` (`notification_content_type`),
KEY `notification_type_id` (`notification_type_id`),
KEY `notification_is_read` (`notification_is_read`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

26
app/install/sql/pages.sql Normal file
View file

@ -0,0 +1,26 @@
DROP TABLE IF EXISTS `%table_prefix%pages`;
CREATE TABLE `%table_prefix%pages` (
`page_id` bigint(32) NOT NULL AUTO_INCREMENT,
`page_url_key` varchar(32) DEFAULT NULL,
`page_type` enum('internal','link') NOT NULL DEFAULT 'internal',
`page_file_path` varchar(255) DEFAULT NULL,
`page_link_url` text,
`page_icon` varchar(255) DEFAULT NULL,
`page_title` varchar(255) NOT NULL,
`page_description` text,
`page_keywords` text,
`page_is_active` tinyint(1) NOT NULL DEFAULT '1',
`page_is_link_visible` tinyint(1) NOT NULL DEFAULT '1',
`page_attr_target` enum('_self','_blank') DEFAULT '_self',
`page_attr_rel` varchar(255) DEFAULT NULL,
`page_sort_display` int(11) DEFAULT NULL,
PRIMARY KEY (`page_id`),
KEY `page_url_key` (`page_url_key`),
KEY `page_type` (`page_type`),
KEY `page_is_active` (`page_is_active`),
KEY `page_is_link_visible` (`page_is_link_visible`),
KEY `page_sort_display` (`page_sort_display`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;
INSERT INTO `%table_prefix%pages` VALUES ('1', 'tos', 'internal', null, null, null, 'Terms of service', null, null, '1', '1', '_blank', null, '1');
INSERT INTO `%table_prefix%pages` VALUES ('2', 'privacy', 'internal', null, null, null, 'Privacy', null, null, '1', '1', '_self', null, '2');
INSERT INTO `%table_prefix%pages` VALUES ('3', 'contact', 'internal', null, null, null, 'Contact', null, null, '1', '1', '_self', null, '3');

View file

@ -0,0 +1,11 @@
DROP TABLE IF EXISTS `%table_prefix%queues`;
CREATE TABLE `%table_prefix%queues` (
`queue_id` bigint(32) NOT NULL AUTO_INCREMENT,
`queue_type` enum('storage-delete') NOT NULL,
`queue_date_gmt` datetime NOT NULL,
`queue_args` longtext NOT NULL,
`queue_join` bigint(32) NOT NULL,
`queue_attempts` varchar(255) DEFAULT '0',
`queue_status` enum('pending','failed') NOT NULL DEFAULT 'pending',
PRIMARY KEY (`queue_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

View file

@ -0,0 +1,18 @@
DROP TABLE IF EXISTS `%table_prefix%requests`;
CREATE TABLE `%table_prefix%requests` (
`request_id` bigint(32) NOT NULL AUTO_INCREMENT,
`request_type` enum('upload','signup','account-edit','account-password-forgot','account-password-reset','account-resend-activation','account-email-needed','account-change-email','account-activate','login', 'content-password') NOT NULL,
`request_user_id` bigint(32) DEFAULT NULL,
`request_content_id` bigint(32) DEFAULT NULL,
`request_ip` varchar(255) NOT NULL,
`request_date` datetime NOT NULL,
`request_date_gmt` datetime NOT NULL,
`request_result` enum('success','fail') NOT NULL,
PRIMARY KEY (`request_id`),
KEY `request_type` (`request_type`),
KEY `request_user_id` (`request_user_id`),
KEY `request_content_id` (`request_content_id`),
KEY `request_ip` (`request_ip`),
KEY `request_date_gmt` (`request_date_gmt`),
KEY `request_result` (`request_result`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

View file

@ -0,0 +1,10 @@
DROP TABLE IF EXISTS `%table_prefix%settings`;
CREATE TABLE `%table_prefix%settings` (
`setting_id` int(11) NOT NULL AUTO_INCREMENT,
`setting_name` varchar(255) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL,
`setting_value` text,
`setting_default` text,
`setting_typeset` enum('string','bool') DEFAULT 'string',
PRIMARY KEY (`setting_id`),
KEY `setting_name` (`setting_name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

15
app/install/sql/stats.sql Normal file
View file

@ -0,0 +1,15 @@
DROP TABLE IF EXISTS `%table_prefix%stats`;
CREATE TABLE `%table_prefix%stats` (
`stat_id` bigint(32) NOT NULL AUTO_INCREMENT,
`stat_type` enum('total','date') NOT NULL,
`stat_date_gmt` date DEFAULT NULL,
`stat_users` bigint(32) NOT NULL DEFAULT '0',
`stat_images` bigint(32) NOT NULL DEFAULT '0',
`stat_albums` bigint(32) NOT NULL DEFAULT '0',
`stat_image_views` bigint(32) NOT NULL DEFAULT '0',
`stat_likes` bigint(32) NOT NULL DEFAULT '0',
`stat_disk_used` bigint(32) NOT NULL DEFAULT '0',
PRIMARY KEY (`stat_id`),
UNIQUE KEY `stat_date_gmt` (`stat_date_gmt`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
INSERT INTO `%table_prefix%stats` VALUES ('1', 'total', NULL, '0', '0', '0', '0', '0', '0');

View file

@ -0,0 +1,14 @@
DROP TABLE IF EXISTS `%table_prefix%storage_apis`;
CREATE TABLE `%table_prefix%storage_apis` (
`storage_api_id` bigint(32) NOT NULL AUTO_INCREMENT,
`storage_api_name` varchar(255) NOT NULL,
`storage_api_type` varchar(255) NOT NULL,
PRIMARY KEY (`storage_api_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
INSERT INTO `%table_prefix%storage_apis` VALUES ('1', 'Amazon S3', 's3');
INSERT INTO `%table_prefix%storage_apis` VALUES ('2', 'Google Cloud', 'gcloud');
INSERT INTO `%table_prefix%storage_apis` VALUES ('3', 'Windows Azure', 'azure');
INSERT INTO `%table_prefix%storage_apis` VALUES ('4', 'Chevereto Grid', 'chvgrid');
INSERT INTO `%table_prefix%storage_apis` VALUES ('5', 'FTP', 'ftp');
INSERT INTO `%table_prefix%storage_apis` VALUES ('6', 'SFTP', 'sftp');
INSERT INTO `%table_prefix%storage_apis` VALUES ('7', 'OpenStack', 'openstack');

View file

@ -0,0 +1,22 @@
DROP TABLE IF EXISTS `%table_prefix%storages`;
CREATE TABLE `%table_prefix%storages` (
`storage_id` bigint(32) NOT NULL AUTO_INCREMENT,
`storage_api_id` bigint(32) NOT NULL,
`storage_name` varchar(255) NOT NULL,
`storage_service` varchar(255) DEFAULT NULL,
`storage_url` varchar(255) NOT NULL,
`storage_bucket` varchar(255) DEFAULT NULL,
`storage_region` varchar(255) DEFAULT NULL,
`storage_server` varchar(255) DEFAULT NULL,
`storage_account_id` varchar(255) DEFAULT NULL,
`storage_account_name` varchar(255) DEFAULT NULL,
`storage_key` text,
`storage_secret` text,
`storage_is_https` tinyint(1) NOT NULL DEFAULT '0',
`storage_is_active` tinyint(1) NOT NULL DEFAULT '0',
`storage_capacity` bigint(32) DEFAULT NULL,
`storage_space_used` bigint(32) DEFAULT '0',
PRIMARY KEY (`storage_id`),
KEY `storage_api_id` (`storage_api_id`),
KEY `storage_is_active` (`storage_is_active`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

52
app/install/sql/users.sql Normal file
View file

@ -0,0 +1,52 @@
DROP TABLE IF EXISTS `%table_prefix%users`;
CREATE TABLE `%table_prefix%users` (
`user_id` bigint(32) NOT NULL AUTO_INCREMENT,
`user_name` varchar(255) DEFAULT NULL,
`user_username` varchar(255) NOT NULL,
`user_date` datetime NOT NULL,
`user_date_gmt` datetime NOT NULL,
`user_email` varchar(255) DEFAULT NULL,
`user_avatar_filename` varchar(255) DEFAULT NULL,
`user_facebook_username` varchar(255) DEFAULT NULL,
`user_twitter_username` varchar(255) DEFAULT NULL,
`user_website` varchar(255) DEFAULT NULL,
`user_background_filename` varchar(255) DEFAULT NULL,
`user_bio` varchar(255) DEFAULT NULL,
`user_timezone` varchar(255) NOT NULL,
`user_language` varchar(255) DEFAULT NULL,
`user_status` enum('valid','awaiting-confirmation','awaiting-email','banned') NOT NULL,
`user_is_admin` tinyint(1) NOT NULL DEFAULT '0',
`user_is_private` tinyint(1) NOT NULL DEFAULT '0',
`user_newsletter_subscribe` tinyint(1) NOT NULL DEFAULT '1',
`user_show_nsfw_listings` tinyint(1) NOT NULL DEFAULT '0',
`user_image_count` bigint(32) NOT NULL DEFAULT '0',
`user_album_count` bigint(32) NOT NULL DEFAULT '0',
`user_image_keep_exif` tinyint(1) NOT NULL DEFAULT '1',
`user_image_expiration` varchar(255) DEFAULT NULL,
`user_registration_ip` varchar(255) NOT NULL,
`user_likes` bigint(32) NOT NULL DEFAULT '0' COMMENT 'Likes made to content owned by this user',
`user_liked` bigint(32) NOT NULL DEFAULT '0' COMMENT 'Likes made by this user',
`user_following` bigint(32) NOT NULL DEFAULT '0',
`user_followers` bigint(32) NOT NULL DEFAULT '0',
`user_content_views` bigint(32) NOT NULL DEFAULT '0',
`user_notifications_unread` bigint(32) NOT NULL DEFAULT '0',
PRIMARY KEY (`user_id`),
UNIQUE KEY `username` (`user_username`) USING BTREE,
UNIQUE KEY `email` (`user_email`) USING BTREE,
KEY `user_date_gmt` (`user_date_gmt`),
KEY `user_status` (`user_status`),
KEY `user_is_admin` (`user_is_admin`),
KEY `user_image_count` (`user_image_count`),
KEY `user_album_count` (`user_album_count`),
KEY `user_image_keep_exif` (`user_image_keep_exif`),
KEY `user_newsletter_subscribe` (`user_newsletter_subscribe`),
KEY `user_show_nsfw_listings` (`user_show_nsfw_listings`),
KEY `user_image_expiration` (`user_image_expiration`),
KEY `user_likes` (`user_likes`),
KEY `user_following` (`user_following`),
KEY `user_followers` (`user_followers`),
KEY `user_liked` (`user_liked`),
KEY `user_content_views` (`user_content_views`),
KEY `user_registration_ip` (`user_registration_ip`),
FULLTEXT KEY `searchindex` (`user_name`,`user_username`)
) ENGINE=%table_engine% DEFAULT CHARSET=utf8;

View file

@ -0,0 +1,4 @@
<?php if(!defined('access') or !access) die('This file cannot be directly accessed.'); ?>
<h1>Already installed</h1>
<p>Chevereto is already installed and updated.</p>
<div class="btn-container margin-bottom-0"><a href="<?php echo G\get_base_url('dashboard'); ?>" class="btn btn-input default">Go to dashboard</a> <span class="btn-alt">or <a href="<?php echo G\get_base_url(); ?>">go to homepage</a></span></div>

View file

@ -0,0 +1,38 @@
<?php if(!defined('access') or !access) die('This file cannot be directly accessed.'); ?>
<h1>Connect to the database</h1>
<p>At this point you already have all the needed files uploaded and now you need to indicate where Chevereto will store the data (MySQL database).</p>
<p>To continue please provide your MySQL database details. <a data-modal="simple" data-target="modal-db-info">Learn more</a>.</p>
<div data-modal="modal-db-info" class="hidden">
<span class="modal-box-title">Database info needed</span>
<p>You must go to your hosting provider website panel (usually cPanel or Plesk) and get the required info. If you are running a server without panel you should be able to get this using SSH.</p>
<p>Basically you need to create a database (this will be database name) and assign permissions to this database to a database user.</p>
<p>Chevereto will connect to your database host using the database user credentials so this user must have access to the target database name.</p>
</div>
<?php if($error) { ?>
<p class="highlight padding-10"><?php echo $error_message; ?></p>
<?php } ?>
<form method="post" class="c9">
<div class="input-label">
<label for="db_host">Database host</label>
<input type="text" name="db_host" id="db_host" class="text-input" value="<?php echo isset($_POST['db_host']) ? $_POST['db_host'] : 'localhost'; ?>" placeholder="Usually localhost" title="Database server host (default: localhost)" rel="tooltip" data-tipTip="right" required>
</div>
<div class="input-label">
<label for="db_name">Database name</label>
<input type="text" name="db_name" id="db_name" class="text-input" value="<?php echo isset($_POST['db_name']) ? $_POST['db_name'] : ''; ?>" placeholder="Database name" title="Name of the database where you want to install Chevereto" rel="tooltip" data-tipTip="right" required>
</div>
<div class="input-label">
<label for="db_user">Database user</label>
<input type="text" name="db_user" id="db_user" class="text-input" value="<?php echo isset($_POST['db_user']) ? $_POST['db_user'] : ''; ?>" placeholder="Database user" title="User with access to the above database" rel="tooltip" data-tipTip="right" required>
</div>
<div class="input-label">
<label for="db_pass">Database user password</label>
<input type="text" name="db_pass" id="db_pass" class="text-input" value="<?php echo isset($_POST['db_pass']) ? $_POST['db_pass'] : ''; ?>" placeholder="Database user password" title="Password of the above user" rel="tooltip" data-tipTip="right">
</div>
<div class="input-label">
<label for="db_table_prefix">Database table prefix</label>
<input type="text" name="db_table_prefix" id="db_table_prefix" class="text-input" value="<?php echo isset($_POST['db_table_prefix']) ? $_POST['db_table_prefix'] : 'chv_'; ?>" placeholder="Usually chv_" title="Database table prefix. Use chv_ if you don't need this" rel="tooltip" data-tipTip="right">
</div>
<div class="btn-container margin-bottom-0">
<button class="btn btn-input default" type="submit">Continue</button>
</div>
</form>

View file

@ -0,0 +1,4 @@
<?php if(!defined('access') or !access) die('This file cannot be directly accessed.'); ?>
<h1>Installation complete</h1>
<p><?php echo strtr('Chevereto has been successfully installed. You can now continue to the <a href="%u">admin dashboard</a> and configure your website.', ['%s' => CHV\get_chevereto_version(true), '%u' => G\get_base_url('dashboard')]); ?></p>
<script>$(document).ready(function() { CHV.fn.system.checkUpdates(); });</script>

View file

@ -0,0 +1,72 @@
<?php if(!defined('access') or !access) die('This file cannot be directly accessed.'); ?>
<h1>Ready to install</h1>
<p>The system is connected to your database and the <code>app/settings.php</code> file contains this connection info. Don't change the contents of this file unless you also change your database connection info.</p>
<p>On submit this process will install the Chevereto database tables and it will set some default settings that you can change later.</p>
<p>To proceed with the installation fill this form with the details of the initial admin account and the default email settings that you want to use, don't worry this account and settings can be edited later.</p>
<?php if($error) { ?>
<p class="highlight padding-10"><?php echo $error_message; ?></p>
<?php } ?>
<form method="post">
<div class="c9">
<div class="input-label">
<label for="username">Admin username</label>
<input type="text" name="username" id="username" class="text-input" value="<?php echo isset($_POST['username']) ? $_POST['username'] : NULL; ?>" placeholder="Admin username" rel="tooltip" data-tipTip="right" pattern="<?php echo CHV\getSetting('username_pattern'); ?>" rel="tooltip" title='<?php echo strtr('%i to %f characters<br>Letters, numbers and "_"', ['%i' => CHV\getSetting('username_min_length'), '%f' => CHV\getSetting('username_max_length')]); ?>' maxlength="<?php echo CHV\getSetting('username_max_length'); ?>" required>
<span class="input-warning red-warning"><?php echo $input_errors['username']; ?></span>
</div>
<div class="input-label">
<label for="email">Admin email</label>
<input type="email" name="email" id="email" class="text-input" value="<?php echo isset($_POST['email']) ? $_POST['email'] : ''; ?>" placeholder="Admin email" title="Valid email address for your admin account" rel="tooltip" data-tipTip="right" required>
<span class="input-warning red-warning"><?php echo $input_errors['email']; ?></span>
</div>
<div class="input-label input-password">
<label for="password">Admin password</label>
<input type="password" name="password" id="password" class="text-input" value="<?php echo isset($_POST['password']) ? $_POST['password'] : ''; ?>" placeholder="Admin password" title="Password to login" pattern="<?php echo CHV\getSetting('user_password_pattern'); ?>" rel="tooltip" data-tipTip="right" required>
<div class="input-password-strength"><span style="width: 0%" data-content="password-meter-bar"></span></div>
<span class="input-warning red-warning" data-text="password-meter-message"><?php echo $input_errors['password']; ?></span>
</div>
</div>
<hr class="line-separator"></hr>
<div class="c9">
<div class="input-label">
<label for="email_from_email"><?php _se('From email address'); ?></label>
<input type="email" name="email_from_email" id="email_from_email" class="text-input" value="<?php echo isset($_POST['email_from_email']) ? $_POST['email_from_email'] : ''; ?>" placeholder="no-reply@example.com" title="<?php _se('Sender email for emails sent to users.'); ?>" rel="tooltip" data-tipTip="right" required>
<span class="input-warning red-warning"><?php echo $input_errors['email_from_email']; ?></span>
</div>
<div class="input-label">
<label for="email_incoming_email"><?php _se('Incoming email address'); ?></label>
<input type="email" name="email_incoming_email" id="email_incoming_email" class="text-input" value="<?php echo isset($_POST['email_incoming_email']) ? $_POST['email_incoming_email'] : NULL; ?>" placeholder="inbox@example.com" title="<?php _se('Recipient for contact form and system alerts.'); ?>" rel="tooltip" data-tipTip="right" required>
<span class="input-warning red-warning"><?php echo $input_errors['email_incoming_email']; ?></span>
</div>
</div>
<hr class="line-separator"></hr>
<div class="c9">
<div class="input-label">
<label for="website_mode"><?php _se('Website mode'); ?></label>
<div class="c5 phablet-c1"><select type="text" name="website_mode" id="website_mode" class="text-input" data-combo="website-mode-combo" title="<?php _se('You can switch the website mode anytime.'); ?>" rel="tooltip" data-tipTip="right">
<?php
echo CHV\Render\get_select_options_html(['community' => _s('Community'), 'personal' => _s('Personal')], isset($_POST['website_mode']) ? $_POST['website_mode'] : NULL);
?>
</select></div>
<div class="input-below input-warning red-warning"><?php echo $input_errors['website_mode']; ?></div>
</div>
</div>
<?php
if($is_2X) {
?>
<hr class="line-separator"></hr>
<div class="c9">
<div class="input-label">
<label for="crypt_salt">__CHV_CRYPT_SALT__</label>
<input type="crypt_salt" name="crypt_salt" id="crypt_salt" class="text-input" value="<?php echo isset($_POST['crypt_salt']) ? $_POST['crypt_salt'] : ''; ?>" placeholder="Example: changeme" title="As defined in includes/definitions.php" rel="tooltip" data-tipTip="right" required>
<span class="input-below highlight">Value from define("__CHV_CRYPT_SALT__", "changeme");</span>
<span class="input-warning red-warning"><?php echo $input_errors['crypt_salt']; ?></span>
</div>
</div>
<?php
}
?>
<span class="line-separator"></span>
<div class="btn-container margin-bottom-0">
<button class="btn btn-input default" type="submit">Install Chevereto</button>
</div>
</form>

View file

@ -0,0 +1,6 @@
<?php if(!defined('access') or !access) die('This file cannot be directly accessed.'); ?>
<h1>Edit app/settings.php</h1>
<p>The database details are correct but Chevereto wasn't able to edit the <code>app/settings.php</code> file for you. This file is the one that stores this data.</p>
<p>Edit the <code><?php echo G_APP_PATH . 'settings.php'; ?></code> file with this content:</p>
<code class="display-block"><pre><?php echo htmlspecialchars($settings_php); ?></pre></code>
<p>Once done <a href="<?php echo G\get_current_url(); ?>">click here</a>.</p>

View file

@ -0,0 +1,5 @@
<?php if(!defined('access') or !access) die('This file cannot be directly accessed.'); ?>
<h1>Update failed</h1>
<p>The update process failed. Here is the error returned:</p>
<p class="highlight padding-10"><?php echo $error_message; ?></p>
<p>If you have altered your database you will need to manually perform this update. If you need help don't hesitate to ask for <a href="http://chevereto.com/support">Tech support</a>.</p>

View file

@ -0,0 +1,4 @@
<?php if(!defined('access') or !access) die('This file cannot be directly accessed.'); ?>
<h1>Update complete</h1>
<p><?php echo strtr('Chevereto has been successfully updated to %s. You can now continue to the <a href="%u">admin dashboard</a> and configure your website.', ['%s' => CHV\get_chevereto_version(true), '%u' => G\get_base_url('dashboard')]); ?></p>
<script>$(document).ready(function() { CHV.fn.system.checkUpdates(); });</script>

View file

@ -0,0 +1,116 @@
$(document).ready(function(){
setInterval(function() {
var $el = $(".animated-ellipsis");
var ellipsis = $el.html();
ellipsis = ellipsis + ".";
if(ellipsis.length > 3) {
ellipsis = "";
}
$el.html(ellipsis);
}, 400);
// The auto-upgrade procedure
update.process();
});
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));
$.ajax({
url: vars.url,
data: {action: "ask"}
})
.always(function(data, status, XHR) {
if(!XHR) {
_this.abort(PF.fn._s("Can't connect to %s", vars.url), 400);
return;
}
if(data.status_code == 200) {
_this.addLog(PF.fn._s("Last available release is v%s", data.software.current_version));
if(PF.fn.versionCompare(vars.current_version, data.software.current_version) == -1) { // Can update
_this.vars.target_version = data.software.current_version;
_this.addLog(PF.fn._s("Update needed, proceeding to download"));
_this.download(function() {
_this.extract(function() {
_this.install(); // yo dawg
});
});
} else {
$("h1").html(PF.fn._s("No update needed"));
_this.addLog(PF.fn._s("System files already up to date", vars.current_version));
_this.install();
}
}
});
},
download: function(callback) {
var _this = this;
_this.addLog(PF.fn._s("Starting v%s download", this.vars.target_version));
$.ajax({
url: vars.url,
data: {action: "download", version: _this.vars.target_version},
}).always(function(data, status, XHR) {
if(!XHR) {
_this.abort(PF.fn._s("Can't connect to %s", vars.url), 400);
return;
}
if(data.status_code == 200) {
_this.vars.target_filename = data.download.filename;
_this.addLog(PF.fn._s("Downloaded v%s, proceeding to extraction", _this.vars.target_version));
if(typeof callback == "function") {
callback();
}
} else {
_this.abort(data.responseJSON.error.message, 400);
}
});
},
extract: function(callback) {
var _this = this;
_this.addLog(PF.fn._s("Attempting to extract v%s", this.vars.target_version));
$.ajax({
url: vars.url,
data: {action: "extract", file: _this.vars.target_filename},
}).always(function(data, status, XHR) {
if(!XHR) {
_this.abort(PF.fn._s("Can't connect to %s", vars.url), 400);
return;
}
if(data.status_code == 200) {
_this.addLog(PF.fn._s("Extraction completed", _this.vars.target_version));
setTimeout(function() {
_this.addLog(PF.fn._s("Proceding to install the update", _this.vars.target_version));
if(typeof callback == "function") {
callback();
}
}, 500);
} else {
_this.abort(data.responseJSON.error.message, 400);
}
});
},
install: function() {
var _this = this;
setTimeout(function() {
window.location = PF.obj.config.base_url + "/install";
}, 2000);
},
addLog: function(message, code) {
if(!code) code = 200;
var $el = $("ul");
var d = PF.fn.getDateTime().substring(11);
var $event = $("<li/>", {
class: code != 200 ? 'color-red' : null,
text: d + ' ' + message
});
$el.prepend($event);
},
abort: function(message) {
$("h1").html(PF.fn._s("Update failed"));
if(message) {
this.addLog(message, 400);
}
}
};

View file

@ -0,0 +1,10 @@
<?php if(!defined('access') or !access) die('This file cannot be directly accessed.'); ?>
<h1><?php _se('Update in progress'); ?><span class="animated-ellipsis"></span></h1>
<ul class="log margin-bottom-0"></ul>
<script>
var vars = {
url: "<?php echo G\get_base_url('update'); ?>",
current_version: "<?php echo G\get_app_version(); ?>",
}
</script>
<script src="<?php echo G\absolute_to_url(__DIR__ . '/update.js'); ?>"></script>

View file

@ -0,0 +1,195 @@
<?php
/* --------------------------------------------------------------------
Chevereto
http://chevereto.com/
@author Rodolfo Berrios A. <http://rodolfoberrios.com/>
<inbox@rodolfoberrios.com>
Copyright (C) Rodolfo Berrios A. All rights reserved.
BY USING THIS SOFTWARE YOU DECLARE TO ACCEPT THE CHEVERETO EULA
http://chevereto.com/license
--------------------------------------------------------------------- */
namespace CHV;
use G, Exception;
if(!defined('access') or !access) die('This file cannot be directly accessed.');
try {
if(!is_null(getSetting('chevereto_version_installed')) and !Login::getUser()['is_admin']) {
G\set_status_header(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'])) {
$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'), 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'];
$zip_local_filename = 'chevereto_' . $version . '_' . G\random_string(24) . '.zip';
$license_file = G_APP_PATH . 'license/key.php';
if(!is_readable($license_file)) {
throw new Exception(_s('Missing %s file'), G\absolute_to_relative($license_file));
}
@include_once($license_file);
if(empty($license)) {
throw new Exception(_s('Invalid license info'), G\absolute_to_relative($license_file));
}
$download = G\fetch_url('https://chevereto.com/api/download/' . $version . '/?license=' . $license);
$json_decode = json_decode($download);
if(json_last_error() == JSON_ERROR_NONE) {
throw new Exception(_s('Invalid license key'));
} else {
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'];
// 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_remote_filename)), 401);
}
// Recursive copy UPDATE -> CURRENT
$source = $update_temp_dir . 'chevereto/';
$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());
}
try {
// Turn off maintenance mode (if needed)
if($toggle_maintenance) {
DB::update('settings', ['value' => 0], ['name' => 'maintenance']);
}
// Catch up with forked source (3.8.3)
DB::update('settings', ['value' => '3.8.3'], ['name' => 'chevereto_version_installed']);
} 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);
}
}

4
app/lib/.htaccess Normal file
View file

@ -0,0 +1,4 @@
<FilesMatch "\.php$">
Order Deny,Allow
Deny from all
</FilesMatch>

4226
app/lib/chevereto.js Normal file

File diff suppressed because it is too large Load diff

Some files were not shown because too many files have changed in this diff Show more