Version 4.5.0

This commit is contained in:
Neo committed 2025-12-19 05:51:58 -08:00
1 parent 1a0c7fd3c2
commit f79dcf067a
3791 files changed
+248032 -76372

No files matched your search

+1 -17
View File
@@ -11,27 +11,19 @@
padding: 10px 20px;
border-radius: 3px;
border: 1px solid rgba(0,0,0,0.1);
{prefix="transition" value="0.1s all linear"}
transition: 0.1s all linear;
{prefix="user-select" value="none"}
-webkit-font-smoothing: antialiased;
}
.ipsApp .ipsButton:not( .ipsButton_noHover ):hover {
cursor: pointer;
background-image: -moz-linear-gradient(top, rgba(255,255,255,0.08) 0%, rgba(255,255,255,0.08) 100%);
background-image: -webkit-linear-gradient(top, rgba(255,255,255,0.08) 0%,rgba(255,255,255,0.08) 100%);
background-image: -o-linear-gradient(top, rgba(255,255,255,0.08) 0%,rgba(255,255,255,0.08) 100%);
background-image: -ms-linear-gradient(top, rgba(255,255,255,0.08) 0%,rgba(255,255,255,0.08) 100%);
background-image: linear-gradient(to bottom, rgba(255,255,255,0.08) 0%,rgba(255,255,255,0.08) 100%);
}
.ipsApp .ipsButton:active {
box-shadow: 1px 1px 4px rgba(0,0,0,0.3) inset;
border: 1px solid rgba(0,0,0,0.4);
background-image: -moz-linear-gradient(top, rgba(0,0,0,0.2) 0%, rgba(0,0,0,0.2) 100%);
background-image: -webkit-linear-gradient(top, rgba(0,0,0,0.2) 0%,rgba(0,0,0,0.2) 100%);
background-image: -o-linear-gradient(top, rgba(0,0,0,0.2) 0%,rgba(0,0,0,0.2) 100%);
background-image: -ms-linear-gradient(top, rgba(0,0,0,0.2) 0%,rgba(0,0,0,0.2) 100%);
background-image: linear-gradient(to bottom, rgba(0,0,0,0.2) 0%,rgba(0,0,0,0.2) 100%);
}
@@ -75,20 +67,12 @@
}
.ipsApp .ipsButton_light:hover {
background-image: -moz-linear-gradient(top, rgba(255,255,255,0.3) 0%, rgba(255,255,255,0.3) 100%);
background-image: -webkit-linear-gradient(top, rgba(255,255,255,0.3) 0%,rgba(255,255,255,0.3) 100%);
background-image: -o-linear-gradient(top, rgba(255,255,255,0.3) 0%,rgba(255,255,255,0.3) 100%);
background-image: -ms-linear-gradient(top, rgba(255,255,255,0.3) 0%,rgba(255,255,255,0.3) 100%);
background-image: linear-gradient(to bottom, rgba(255,255,255,0.3) 0%,rgba(255,255,255,0.3) 100%);
}
.ipsApp .ipsButton:active {
box-shadow: 1px 1px 4px rgba(0,0,0,0.1) inset;
border: 1px solid rgba(0,0,0,0.1);
background-image: -moz-linear-gradient(top, rgba(0,0,0,0.02) 0%, rgba(0,0,0,0.02) 100%);
background-image: -webkit-linear-gradient(top, rgba(0,0,0,0.02) 0%,rgba(0,0,0,0.02) 100%);
background-image: -o-linear-gradient(top, rgba(0,0,0,0.02) 0%,rgba(0,0,0,0.02) 100%);
background-image: -ms-linear-gradient(top, rgba(0,0,0,0.02) 0%,rgba(0,0,0,0.02) 100%);
background-image: linear-gradient(to bottom, rgba(0,0,0,0.02) 0%,rgba(0,0,0,0.02) 100%);
}
-56
View File
@@ -29,7 +29,6 @@
.icon-spinner2:before,
.icon-spinner3:before,
.icon-spinner9:before {
-webkit-animation: spinner 0.75s infinite linear;
animation: spinner 0.75s infinite linear;
}
@@ -125,43 +124,8 @@
margin-left: .3em;
}
.fa-spin {
-webkit-animation: spin 2s infinite linear;
-moz-animation: spin 2s infinite linear;
-o-animation: spin 2s infinite linear;
animation: spin 2s infinite linear;
}
@-moz-keyframes spin {
0% {
-moz-transform: rotate(0deg);
}
100% {
-moz-transform: rotate(359deg);
}
}
@-webkit-keyframes spin {
0% {
-webkit-transform: rotate(0deg);
}
100% {
-webkit-transform: rotate(359deg);
}
}
@-o-keyframes spin {
0% {
-o-transform: rotate(0deg);
}
100% {
-o-transform: rotate(359deg);
}
}
@-ms-keyframes spin {
0% {
-ms-transform: rotate(0deg);
}
100% {
-ms-transform: rotate(359deg);
}
}
@keyframes spin {
0% {
transform: rotate(0deg);
@@ -172,42 +136,22 @@
}
.fa-rotate-90 {
filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=1);
-webkit-transform: rotate(90deg);
-moz-transform: rotate(90deg);
-ms-transform: rotate(90deg);
-o-transform: rotate(90deg);
transform: rotate(90deg);
}
.fa-rotate-180 {
filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=2);
-webkit-transform: rotate(180deg);
-moz-transform: rotate(180deg);
-ms-transform: rotate(180deg);
-o-transform: rotate(180deg);
transform: rotate(180deg);
}
.fa-rotate-270 {
filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=3);
-webkit-transform: rotate(270deg);
-moz-transform: rotate(270deg);
-ms-transform: rotate(270deg);
-o-transform: rotate(270deg);
transform: rotate(270deg);
}
.fa-flip-horizontal {
filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1);
-webkit-transform: scale(-1, 1);
-moz-transform: scale(-1, 1);
-ms-transform: scale(-1, 1);
-o-transform: scale(-1, 1);
transform: scale(-1, 1);
}
.fa-flip-vertical {
filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1);
-webkit-transform: scale(1, -1);
-moz-transform: scale(1, -1);
-ms-transform: scale(1, -1);
-o-transform: scale(1, -1);
transform: scale(1, -1);
}
.fa-stack {
+5 -21
View File
@@ -322,12 +322,11 @@ input[type="checkbox"]:disabled + .ipsToggle {
line-height: 22px;
border-radius: 2px;
position: relative;
box-shadow: 0px 0px 1px rgba(0,0,0,0.2) inset;
border: 1px solid rgba(0,0,0,0.3);
border: 1px solid rgba(0,0,0,0.1);
overflow: hidden;
vertical-align: middle;
cursor: pointer;
-webkit-transition: all 0.3s linear;
transition: all 0.3s linear;
}
.ipsToggle.ipsToggle_off {
@@ -353,7 +352,7 @@ input[type="checkbox"]:disabled + .ipsToggle {
box-shadow: 0px 0px 1px rgba(0,0,0,0.5);
display: block;
position: absolute;
-webkit-transition: all 0.2s linear;
transition: all 0.2s linear;
pointer-events: none;
}
@@ -367,20 +366,6 @@ input[type="checkbox"]:disabled + .ipsToggle {
right: 29px;
}
.ipsToggle span:before {
content: '\\f0c9';
font-family: 'FontAwesome';
font-size: 10px;
line-height: 20px;
display: block;
position: absolute;
width: 18px;
height: 18px;
top: 0;
left: -14px;
color: rgba(0,0,0,0.2);
}
.ipsToggle span:after {
content: '\\f00c';
font-family: 'FontAwesome';
@@ -392,7 +377,6 @@ input[type="checkbox"]:disabled + .ipsToggle {
right: 27px;
top: 0px;
line-height: 18px;
text-shadow: 0px 0px 1px rgba(0,0,0,0.5);
}
.ipsToggle.ipsToggle_off span:after {
@@ -423,9 +407,9 @@ input[type="checkbox"]:disabled + .ipsToggle {
background: #f2f2f2;
overflow: hidden;
text-indent: 100%;
whitespace: no-wrap;
whitespace: nowrap;
cursor: pointer;
-webkit-transition: 0.2s all linear;
transition: 0.2s all linear;
position: relative;
}
+15 -61
View File
@@ -102,47 +102,14 @@ a {
text-align: center;
}
@-webkit-keyframes progress-bar-stripes {
from {
background-position: 40px 0;
}
to {
background-position: 0 0;
}
}
@-moz-keyframes progress-bar-stripes {
from {
background-position: 40px 0;
}
to {
background-position: 0 0;
}
}
@-ms-keyframes progress-bar-stripes {
from {
background-position: 40px 0;
}
to {
background-position: 0 0;
}
}
@-o-keyframes progress-bar-stripes {
from {
background-position: 0 0;
}
to {
background-position: 40px 0;
}
}
@keyframes progress-bar-stripes {
from {
background-position: 40px 0;
}
to {
background-position: 0 0;
}
}
@keyframes progress-bar-stripes {
from {
background-position: 40px 0;
}
to {
background-position: 0 0;
}
}
.ipsProgressBar {
width: 50%;
@@ -150,30 +117,17 @@ a {
height: 20px;
overflow: hidden;
background: rgb(156,156,156);
background: -moz-linear-gradient(top, rgba(156,156,156,1) 0%, rgba(180,180,180,1) 100%);
background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,rgba(156,156,156,1)), color-stop(100%,rgba(180,180,180,1)));
background: -webkit-linear-gradient(top, rgba(156,156,156,1) 0%,rgba(180,180,180,1) 100%);
background: -o-linear-gradient(top, rgba(156,156,156,1) 0%,rgba(180,180,180,1) 100%);
background: -ms-linear-gradient(top, rgba(156,156,156,1) 0%,rgba(180,180,180,1) 100%);
background: linear-gradient(to bottom, rgba(156,156,156,1) 0%,rgba(180,180,180,1) 100%);
border-radius: 4px;
box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);
}
.ipsProgressBar_animated .ipsProgressBar_progress {
background-color: #5490c0;
background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));
background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
background-size: 40px 40px;
-webkit-animation: progress-bar-stripes 2s linear infinite;
-moz-animation: progress-bar-stripes 2s linear infinite;
-ms-animation: progress-bar-stripes 2s linear infinite;
-o-animation: progress-bar-stripes 2s linear infinite;
animation: progress-bar-stripes 2s linear infinite;
}
.ipsProgressBar_animated .ipsProgressBar_progress {
background-color: #5490c0;
background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
background-size: 40px 40px;
animation: progress-bar-stripes 2s linear infinite;
}
.ipsProgressBar_progress {
float: left;
@@ -185,7 +139,7 @@ a {
text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
background: #5490c0;
position: relative;
padding-left: 6px;
padding-left: 6px;
}
.ipsProgressBar_progress[data-progress]:after {
+2 -7
View File
@@ -63,13 +63,9 @@ hr.ipsHr {
border-color: #f0f0f0;
}
@-webkit-keyframes spinner {
0% { -webkit-transform: rotate(0deg); transform: rotate(0deg); }
100% { -webkit-transform: rotate(359deg); transform: rotate(359deg); }
}
@keyframes spinner {
0% { -webkit-transform: rotate(0deg); transform: rotate(0deg); }
100% { -webkit-transform: rotate(359deg); transform: rotate(359deg); }
0% { transform: rotate(0deg); }
100% { transform: rotate(359deg); }
}
.ipsLoading {
@@ -88,7 +84,6 @@ hr.ipsHr {
margin-left: -25px;
font-size: 50px;
line-height: 1 !important;
-webkit-animation: spinner 0.75s infinite linear;
animation: spinner 0.75s infinite linear;
}
+117 -22
View File
@@ -26,11 +26,11 @@ if ( file_exists( "../../constants.php" ) )
{
require "../../constants.php";
}
foreach ( array( 'FOLDER_PERMISSION_NO_WRITE' => 0755, 'FILE_PERMISSION_NO_WRITE' => 0644, 'TEMP_DIRECTORY' => sys_get_temp_dir() ) as $k => $v )
foreach ( array( 'FOLDER_PERMISSION_NO_WRITE' => 0755, 'FILE_PERMISSION_NO_WRITE' => 0644, 'IPS_FILE_PERMISSION' => 0666, 'TEMP_DIRECTORY' => sys_get_temp_dir() ) as $k => $v )
{
if ( !defined( $k ) )
if ( !\defined( $k ) )
{
define( $k, $v );
\define( $k, $v );
}
}
@@ -92,7 +92,7 @@ class Extractor
{
if ( !$file or !$container )
{
throw new Exception;
throw new Exception( "Zip file or directory to extract to was not supplied" );
}
$this->file = $file;
@@ -108,7 +108,28 @@ class Extractor
public function securityCheck( $key )
{
require "../../conf_global.php";
return $key === md5( $INFO['board_start'] . $_GET['file'] . $INFO['sql_pass'] );
$db = new mysqli( $INFO['sql_host'], $INFO['sql_user'], $INFO['sql_pass'], $INFO['sql_database'], !empty( $INFO['sql_port'] ) ? $INFO['sql_port'] : null, !empty( $INFO['sql_socket'] ) ? $INFO['sql_socket'] : null );
/* If the connection failed, do not continue */
if( $error = mysqli_connect_error() )
{
return FALSE;
}
/* Check that there is an upgrade in progress */
$query = $db->query( "SELECT conf_value FROM {$INFO['sql_tbl_prefix']}core_sys_conf_settings WHERE conf_key='setup_in_progress'" );
if( !$query )
{
return FALSE;
}
if( (bool) $query->fetch_assoc()['conf_value'] === FALSE )
{
return FALSE;
}
return $this->_compareHashes( md5( $INFO['board_start'] . $_GET['file'] . $INFO['sql_pass'] ), $key );
}
/**
@@ -124,21 +145,21 @@ class Extractor
$this->ssh = ssh2_connect( $value['server'], $value['port'] );
if ( $this->ssh === FALSE )
{
throw new Exception;
throw new Exception( "Could not connect to SCP" );
}
if ( !@ssh2_auth_password( $this->ssh, $value['un'], $value['pw'] ) )
{
throw new Exception;
throw new Exception( "Could not login to SCP" );
}
$this->sftp = @ssh2_sftp( $this->ssh );
if ( $this->sftp === FALSE )
{
throw new Exception;
throw new Exception( "Could not initiate SFTP connection" );
}
if ( $value['path'] and !@ssh2_sftp_stat( $this->sftp, $value['path'] ) )
{
throw new Exception;
throw new Exception( "Could not locate path via SFTP" );
}
$this->sftpDir = ssh2_sftp_realpath( $this->sftp, $value['path'] ) . '/';
@@ -155,11 +176,11 @@ class Extractor
}
if ( $this->ftp === FALSE )
{
throw new Exception;
throw new Exception( "Could not connect to FTP" );
}
if ( !@ftp_login( $this->ftp, $value['un'], $value['pw'] ) )
{
throw new Exception;
throw new Exception( "Could not login to FTP" );
}
if( ftp_nlist( $this->ftp, '.' ) === FALSE )
{
@@ -168,7 +189,7 @@ class Extractor
if ( !@ftp_chdir( $this->ftp, $value['path'] ) )
{
throw new Exception;
throw new Exception( "Could not change directory to {$value['path']}" );
}
}
}
@@ -196,7 +217,7 @@ class Extractor
$this->contents = $this->zip->listContent();
if ( !$this->contents )
{
throw new Exception;
throw new Exception( "Could not list the files in the zip" );
}
$done = 0;
@@ -234,11 +255,11 @@ class Extractor
}
/* Create a directory if needed */
$dir = dirname( $path );
$dir = \dirname( $path );
$directories = array( $dir );
while ( $dir != '.' )
{
$dir = dirname( $dir );
$dir = \dirname( $dir );
if ( $dir != '.' )
{
$directories[] = $dir;
@@ -273,16 +294,16 @@ class Extractor
if ( $this->sftp )
{
if ( @ssh2_scp_send( $this->ssh, $tmpFile, $this->sftpDir . $path ) === FALSE )
if ( @ssh2_scp_send( $this->ssh, $tmpFile, $this->sftpDir . $path, FILE_PERMISSION_NO_WRITE ) === FALSE )
{
throw new \Exception;
throw new \Exception( "Could not transfer file to server via SFTP" );
}
}
else
{
if ( @ftp_put( $this->ftp, $path, $tmpFile, FTP_BINARY ) === FALSE )
{
throw new \Exception;
throw new \Exception( "Could not transfer file to server via FTP" );
}
}
@@ -309,7 +330,7 @@ class Extractor
/* If the file existed before we started, we should clear it from opcache if opcache is enabled */
if( $fileExists )
{
if ( function_exists( 'opcache_invalidate' ) )
if ( \function_exists( 'opcache_invalidate' ) )
{
@opcache_invalidate( "../../{$path}" );
}
@@ -323,6 +344,78 @@ class Extractor
@\fclose( $fh );
}
}
/* !Misc Utility Methods */
/**
* Compare hashes in fixed length, time constant manner.
* This is replicated from \IPS\Login::compareHashes(), however we don't want to include framework code here.
*
* @param string $expected The expected hash
* @param string $provided The provided input
* @return boolean
*/
private function _compareHashes( $expected, $provided )
{
if ( !\is_string( $expected ) || !\is_string( $provided ) || $expected === '*0' || $expected === '*1' || $provided === '*0' || $provided === '*1' ) // *0 and *1 are failures from crypt() - if we have ended up with an invalid hash anywhere, we will reject it to prevent a possible vulnerability from deliberately generating invalid hashes
{
return FALSE;
}
$len = \strlen( $expected );
if ( $len !== \strlen( $provided ) )
{
return FALSE;
}
$status = 0;
for ( $i = 0; $i < $len; $i++ )
{
$status |= \ord( $expected[ $i ] ) ^ \ord( $provided[ $i ] );
}
return $status === 0;
}
}
/**
* Function to write a log file to disk
*
* @param mixed $message Exception or message to log
* @return void
*/
function writeLogFile( $message )
{
/* What are we writing? */
$date = date('r');
if ( $message instanceof \Exception )
{
$messageToLog = $date . "\n" . \get_class( $message ) . '::' . $message->getCode() . "\n" . $message->getMessage() . "\n" . $message->getTraceAsString();
}
else
{
if ( \is_array( $message ) )
{
$message = var_export( $message, TRUE );
}
$messageToLog = $date . "\n" . $message . "\n" . ( new \Exception )->getTraceAsString();
}
/* Where are we writing it? */
$dir = rtrim( __DIR__, '/' ) . '/../../uploads/logs';
/* Write it */
$header = "<?php exit; ?>\n\n";
$file = $dir . '/' . date( 'Y' ) . '_' . date( 'm' ) . '_' . date('d') . '_' . ( 'extractfailure' ) . '.php';
if ( file_exists( $file ) )
{
@\file_put_contents( $file, "\n\n-------------\n\n" . $messageToLog, FILE_APPEND );
}
else
{
@\file_put_contents( $file, $header . $messageToLog );
}
@chmod( $file, IPS_FILE_PERMISSION );
}
/* ! Controller */
@@ -333,7 +426,7 @@ try
/* Check this request came from the ACP */
if ( !$extractor->securityCheck( $_GET['key'] ) )
{
throw new Exception;
throw new Exception( "Security check failed" );
}
/* Establish an FTP connection if necessary */
@@ -351,7 +444,7 @@ try
{
@unlink( $_GET['file'] );
if ( function_exists( 'opcache_reset' ) )
if ( \function_exists( 'opcache_reset' ) )
{
@opcache_reset();
}
@@ -387,8 +480,10 @@ HTML;
HTML;
}
}
catch ( Exception $e )
catch ( Throwable $e )
{
writeLogFile( $e );
echo "<script type='text/javascript'>parent.location = parent.location + '&fail=1';</script><noscript>An error occurred. Please visit the <a href='https://remoteservices.invisionpower.com/docs/client_area' target='_blank' rel='noopener'>client area</a> to manually download the latest version. After uploading the files, <a href='index.php' target='_parent'>continue to the upgrader</a>.</noscript>";
exit;
}
+214
View File
@@ -0,0 +1,214 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>Invision Community Update Extractor</title>
<style type='text/css'>.ipsType_text{text-align:center;font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;font-size: 13px;line-height: 18px;}.ipsLoader_container{ position: absolute; top:0;left:0;right:0;bottom:0;display: flex;flex-direction:column;justify-content:center;align-items:center;}.ipsLoader {display: inline-block; width: 48px;height: 48px;background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAAE70lEQVR4Xu2bjZHUMAyFdRUAFQAVwFUAVwFQAVwFQAVwFQAVABUAFcBVAFQAHXBUAPPtWDuO1n9xnKwT0MzO7u0ljvUkPcm29kT+cTlZSP+7InJHRG6JyH33TL67bp7/U0R4fXPvl+7zbNOcE4AHIvLQKYziU+SjiPD6JCJXUway97YGAIs+FZEnztot56pjvRORN608oxUAqvizgFvPAQJjfhGRC/de/YwWAGDxlwsqbpXFIwAC7hgtUwCAxN6KCO/HFnjh3PHEqLnUAgC5obxl8dDDfzs3hdlxWybLZ18YByAhS16MT9YYK3jD8zFEWQPAKxEh1lOC0srcvNcIoAAEhHpvxACAe1YKwlgAsDoTigmKv3avlukKr4BnHhcCAQiEhPW0g9vHAJBTHiJC+ZaK2wkDBG5e4hHM43ZuPqUAgP6LCPrfnVdk0S60XsllhCBzupa5OBsOJQDg8lg/JO8dH8xp9ZiOkCb8crMAhNPYNTkAeMjnCNvj8ljhmAJRkllyGYPKMUjcOQC+RvI8BEMs9iClIDwK1QkpAGJx34PlLfCAQLynwiFIijEAYFusbwsdVmPk5h6FcCUcUsR4EAoxAHBvm3Nhe9byxyC8UsCJcwq1lJAa9+uGEABY/0dgBKorEO5dmGOqTiBz7Yu5EAAUM6zwfImyaIdoxAzoT3XvBSEAfpnYp7xl0J5d39ohFML+NXsvsABAcB/MaD2yfs7xcl6AMW8wiAUghBwXrsn6Cg5VIvuSMdnVMhYA6/4DwsjB3tn/UyU8U93p5gNAHiX3+xKsnjpTNDYdahgMGpNdGPgAhHJorlTuHYtcSjz1FbTpj0MJPcToXdHY/FLLeO459wGwaK2R/S0QoazmX3PhA2BXfmuOf1USD2Y5H5NLH4A/5qq1lL658LR6+dcnAVhr/reApAC4SnnA2jOAApECYFAJ2gv/OQAoDPzNhK0AkKoFBhxgL9wKAKlMcJaqA9hKXnKvP8fmU/7PuoBCTz2cJT6V72AxZKumraRBHziU1kPa3fe+B9jVE6esoLYlIRwG23o+AHYToecd4FqjUBoPTqst0bFbqnvr+12T2qd1dh/LfXQadJJYAOyKcEtESPwfhLQFwG6KrGk3OOdwkPzBWWYo128xDIh9bcAcABUCwO4M9XQQmrNyamMkeJIdAoC9NNDSooHPHCSsVUh92llyoEOs3LVF0Zq9gLwf3dpL1fuWC7L9Nh26CIak8ot2qqUAsIsIBmGbbC1CRiPtJTd2cys+WxesJRS0a0TZP2q0HADciAtpDw6VFIuk3leJnG9y8pNt0iwBAAZFYc0KvYNARxt6pRo69x5RAgAX2/aTXkFAeTZzi9t4SgHoHQRiHrdH+VFtPGMACIHAd8cmRm3b147VUVlqLAAMDidALn5zIn8DxNJ9BLTykKmqF201AAACLkeR4fcSoTzfMZm5BTenG4ziDLLLsn1sQrUA6HiQDRbwGxSpIAGi+S+8XMcHizUAYHw+V/1URhWYCoCOg8JMxj9XwCOwDG03HLXXCjFOzyJgE37EOs9q0rLXCgANC9yRyYVaVgGDeoIX4KCI5QyUBUQszGf9GQ3jAyJgNu1RbgmAb2Gspa9cT3/KMwAJSxNmk1x9Lg4ocWu1pL5DoLa9nYMK9Qz1Ev2BVckzqq+ZywOqJ7T0jf8BWBrx3p73Fz7CAs0clL73AAAAAElFTkSuQmCC);background-size:48px 48px; background-position: center; background-repeat:no-repeat;animation: spinner 0.75s infinite linear;}@keyframes spinner { 0% { transform: rotate(0deg); } 100% { transform: rotate(359deg); }}#ipsLoader_text { margin: 15px 0 0 0; padding: 0; font-size: 14px;text-align:center;}
</style>
</head>
<body style="margin:0">
<?php
/**
* @brief Update Extractor
* @author <a href='https://www.invisioncommunity.com'>Invision Power Services, Inc.</a>
* @copyright (c) Invision Power Services, Inc.
* @license https://www.invisioncommunity.com/legal/standards/
* @package Invision Community
* @since 31 Jul 2017
*/
// This file deliberately exists outside of the framework
// and MUST NOT call init.php
@ini_set('display_errors', 'off');
if ( file_exists( "../../constants.php" ) )
{
require "../../constants.php";
}
if ( !defined( 'CP_DIRECTORY' ) )
{
define( 'CP_DIRECTORY', 'admin' );
}
if ( !defined( 'ROOT_PATH' ) )
{
define( 'ROOT_PATH', str_replace( CP_DIRECTORY . '/upgrade', '', __DIR__ ) );
}
require "../../conf_global.php";
/**
* Compare hashes in fixed length, time constant manner.
*
* @param string $expected The expected hash
* @param string $provided The provided input
* @return boolean
*/
function compareHashes( $expected, $provided )
{
if ( !\is_string( $expected ) || !\is_string( $provided ) || $expected === '*0' || $expected === '*1' || $provided === '*0' || $provided === '*1' ) // *0 and *1 are failures from crypt() - if we have ended up with an invalid hash anywhere, we will reject it to prevent a possible vulnerability from deliberately generating invalid hashes
{
return FALSE;
}
$len = \strlen( $expected );
if ( $len !== \strlen( $provided ) )
{
return FALSE;
}
$status = 0;
for ( $i = 0; $i < $len; $i++ )
{
$status |= \ord( $expected[ $i ] ) ^ \ord( $provided[ $i ] );
}
return $status === 0;
}
/**
* Get CiCloud User
*
* @return string|NULL
*/
function getCicUsername(): ?string
{
if ( preg_match( '/^\/var\/www\/html\/(.+?)(?:\/|$)/i', ROOT_PATH, $matches ) )
{
return $matches[1];
}
return NULL;
}
/**
* Function to write a log file to disk
*
* @param mixed $message Exception or message to log
* @return void
*/
function writeLogFile( $message )
{
/* What are we writing? */
$date = date('r');
if ( $message instanceof \Exception )
{
$messageToLog = $date . "\n" . \get_class( $message ) . '::' . $message->getCode() . "\n" . $message->getMessage() . "\n" . $message->getTraceAsString();
}
else
{
if ( \is_array( $message ) )
{
$message = var_export( $message, TRUE );
}
$messageToLog = $date . "\n" . $message . "\n" . ( new \Exception )->getTraceAsString();
}
/* Where are we writing it? */
$dir = rtrim( __DIR__, '/' ) . '/../../uploads/logs';
/* Write it */
$header = "<?php exit; ?>\n\n";
$file = $dir . '/' . date( 'Y' ) . '_' . date( 'm' ) . '_' . date('d') . '_' . ( 'extractfailure' ) . '.php';
if ( file_exists( $file ) )
{
@\file_put_contents( $file, "\n\n-------------\n\n" . $messageToLog, FILE_APPEND );
}
else
{
@\file_put_contents( $file, $header . $messageToLog );
}
@chmod( $file, IPS_FILE_PERMISSION );
}
/* ! Controller */
try
{
/* Check this request came from the ACP */
if ( !getCicUsername() OR compareHashes( md5( getCicUsername() . $INFO['sql_pass'] ), $_GET['key'] ) === FALSE )
{
throw new Exception( "Security check failed" );
}
/* We are done if last_auto_upgrade exists and is both older than the current time but updated less than ten minutes ago. */
$done = ( isset( $INFO['last_auto_upgrade'] ) AND $INFO['last_auto_upgrade'] < time() AND ( $INFO['last_auto_upgrade'] > time() - ( 10 * 60 ) ) );
$adsess = $_GET['adsess'] ?? '';
if ( $done )
{
if ( \function_exists( 'opcache_reset' ) )
{
@opcache_reset();
}
$siteurl = $INFO['base_url'] ?? $INFO['board_url'];
$upgradeUrl = rtrim( $siteurl, '/' ) . '/' . CP_DIRECTORY . "/upgrade/";
echo <<<HTML
<div class='ipsLoader_container'>
<div class="ipsLoader"></div>
<p id='ipsLoader_text' class='ipsType_text'>&nbsp;&nbsp;</p>
</div>
<script type='text/javascript'>window.onload = function(){setTimeout(function(){window.skipConfirm = true;parent.location = parent.location + '&done=1';}, 10000);};</script><noscript><a href='../?app=core&module=system&controller=upgrade&done=1' target='_parent'>Click here to continue</a></noscript>
HTML;
}
/* Nope, redirect to the next batch */
else
{
if ( !isset( $_GET['counter'] ) )
{
$_GET['counter'] = 0;
}
$i = 1 + $_GET['counter'];
$url = "extractCic.php?counter={$i}&key={$_GET['key']}&adsess={$adsess}";
echo <<<HTML
<div class='ipsLoader_container'>
<div class="ipsLoader"></div>
<p id='ipsLoader_text' class='ipsType_text' data-counter='{$i}'>&nbsp;&nbsp;</p>
</div>
<noscript><a href='{$url}' target='_parent'>Click here to continue</a></noscript>
<script type='text/javascript'>window.onload = function(){setTimeout(function(){window.skipConfirm = true;window.location = '{$url}';}, 10000);};</script>
HTML;
}
}
catch ( Throwable $e )
{
writeLogFile( $e );
echo "<script type='text/javascript'>parent.location = parent.location + '&fail=1';</script><noscript><a href='../?app=core&module=system&controller=upgrade&fail=1' target='_parent'>Click to continue</a>.</noscript>";
exit;
}
?>
<script type='text/javascript'>
window.addEventListener('beforeunload', function (event) {
if( !window.skipConfirm ){
event.preventDefault();
event.returnValue = '';
}
});
var phrases = [
"Files are still being applied, please wait...",
"Sit tight, we're still working on applying those latest files...",
"We'll get this finished up as quickly as possible...",
"Your upgrade is important to us caller, please stay on the line...",
"Fetching awesome new features, fresh from the Invision Community kitchen...",
"We promise we won't keep you much longer...",
"A wise man once said, 'Please be patient while we apply new files'...",
"This would be a good time to check out what's new in <a href='https://invisioncommunity.com/news' target='_blank'>our blog</a>...",
"Know what's better than Invision Community? A newer version of Invision Community!",
"🎵 If you're happy and you know it, please wait some more... 🎵",
"While you're waiting, we'd like to take a moment to thank you for using Invision Community."
];
var selected = phrases[Math.floor(Math.random()*phrases.length)];
var element = document.getElementById('ipsLoader_text');
if( element.hasAttribute('data-counter') && parseInt( element.getAttribute('data-counter') ) > 1 ){
element.innerHTML = selected;
}
</script>
</body>
</html>
+1 -1
View File
@@ -2,7 +2,7 @@
<ul class='ipsField_fieldList'>
{{foreach $apps as $key => $data}}
<li>
<input type="checkbox" id='app_{$key}' name="apps[{$key}]" {{if $data['force'] or in_array( $key, $selected )}}checked{{endif}} {{if $data['force'] or $data['disabled']}}disabled{{endif}} value='1'>
<input type="checkbox" id='app_{$key}' name="apps[{$key}]" {{if $data['force'] or \in_array( $key, $selected )}}checked{{endif}} {{if $data['force'] or $data['disabled']}}disabled{{endif}} value='1'>
<div class='ipsField_fieldList_content'>
<label for='app_{$key}' class='ipsFieldRow_label'>{$data['name']}</label>
<dl class='ipsVersions{{if $data['disabled']}} disabled{{endif}}'>
@@ -0,0 +1,52 @@
<ips:template parameters="$name, $value, $required, $options, $multiple=FALSE, $class='', $disabled=FALSE, $toggles=array(), $id=NULL, $unlimited=NULL, $unlimitedLang='all', $unlimitedToggles=array(), $toggleOn=TRUE, $descriptions=array()" />
{{if $multiple}}
<input type="hidden" name="{$name}[__EMPTY]" value="__EMPTY">
{{endif}}
{{if $unlimited !== NULL}}
<div data-control="granularCheckboxset">
<div data-role="checkboxsetUnlimited" class="{{if !\is_array( $value )}}ipsJS_show{{else}}ipsHide{{endif}}">
<input
type='checkbox'
name="{expression="trim( $name, '[]' )"}_unlimited"
value='{$unlimited}'
id="{expression="trim( $id ?: $name, '[]' )"}_unlimited"
{{if $unlimited === $value}}checked aria-checked='true'{{else}}aria-checked='false'{{endif}}
{{if $disabled}}disabled aria-disabled='true'{{endif}}
data-ipsToggle
data-role="checkboxsetUnlimitedToggle"
>
&nbsp;
{lang="or"}
&nbsp;
<a class="ipsCursor_pointer" data-action="checkboxsetCustomize">{lang="customize"}</a>
</div>
{{endif}}
<div data-role="checkboxsetGranular" class="{{if $unlimited !== NULL and !\is_array( $value )}}ipsJS_hide{{endif}}">
<ul class="ipsField_fieldList">
{{foreach $options as $k => $v}}
<li>
<span class='ipsCustomInput'>
<input type="checkbox" {{if $class}}class="{$class}"{{endif}} name="{$name}[{$k}]" value="1" {{if ( $unlimited !== NULL AND $unlimited === $value ) or ( \is_array( $value ) AND \in_array( $k, $value ) )}}checked{{endif}} {{if $disabled === TRUE or ( \is_array( $disabled ) and \in_array( $k, $disabled ) )}}disabled{{endif}} {{if isset( $toggles[ $k ] ) and !empty( $toggles[ $k ] )}}data-control="toggle" {{if $toggleOn === FALSE}}data-togglesOff{{else}}data-togglesOn{{endif}}="{expression="implode( ',', $toggles[ $k ] )"}"{{endif}} id="elCheckbox_{$name}_{$k}">
<span></span>
</span>
<div class='ipsField_fieldList_content'>
<label for='elCheckbox_{$name}_{$k}' id='elField_{$name}_label'>{$v|raw}</label>
{{if isset( $descriptions[ $k ] )}}
<br>
<span class='ipsFieldRow_desc'>
{$descriptions[ $k ]|raw}
</span>
{{endif}}
</div>
</li>
{{endforeach}}
</ul>
{{if $unlimited !== NULL}}
<div class="ipsSpacer_top ipsSpacer_half">
{lang="or"}
&nbsp;
<a class="ipsCursor_pointer" data-action="checkboxsetAll">{lang="all"}</a> / <a class="ipsCursor_pointer" data-action="checkboxsetNone">{lang="none"}</a>
</div>
</div>
{{endif}}
</div>
+1 -1
View File
@@ -7,7 +7,7 @@
{{endif}}
<form method="post">
<input type="hidden" name="{$id}_submitted" value="1">
<input type="hidden" name="login_submitted" value="1">
<ul class='ipsForm ipsForm_vertical'>
<li class="ipsFieldRow ipsClearfix">
<label class="ipsFieldRow_label" for="auth">
+4 -10
View File
@@ -14,23 +14,17 @@
<ul class="ipsField_fieldList" role="radiogroup" id="elRadio_{$name}">
{{foreach $options as $k => $v}}
<li>
<input type="radio" name="{$name}" value="{$k}" {{if (string) $value == (string) $k or ( isset( $userSuppliedInput ) and !in_array( $value, array_keys( $options ) ) and $k == $userSuppliedInput )}}checked{{endif}} {{if $required === TRUE}}required{{endif}} {{if $disabled === TRUE or ( is_array( $disabled ) and in_array( $k, $disabled ) )}}disabled{{endif}} {{if isset( $toggles[ $k ] ) and !empty( $toggles[ $k ] )}}data-control="toggle" data-toggles="{expression="implode( ',', $toggles[ $k ] )"}"{{endif}} id="elRadio_{$name}_{$k}" />
<input type="radio" name="{$name}" value="{$k}" {{if (string) $value == (string) $k or ( isset( $userSuppliedInput ) and !\in_array( $value, array_keys( $options ) ) and $k == $userSuppliedInput )}}checked{{endif}} {{if $required === TRUE}}required{{endif}} {{if $disabled === TRUE or ( \is_array( $disabled ) and \in_array( $k, $disabled ) )}}disabled{{endif}} {{if isset( $toggles[ $k ] ) and !empty( $toggles[ $k ] )}}data-control="toggle" data-toggles="{expression="implode( ',', $toggles[ $k ] )"}"{{endif}} id="elRadio_{$name}_{$k}" />
<div class='ipsField_fieldList_content'>
<label for='elRadio_{$name}_{$k}' id='elField_{$name}_label'>{$v|raw}</label>
{{if !empty( $userSuppliedInput ) AND $userSuppliedInput == $k}}
<input type='text' name='{$userSuppliedInput}_{$name}' value="{{if !in_array( $value, array_keys( $options ) )}}{$value}{{endif}}" id='{$userSuppliedInput}_{expression="preg_replace('/[^a-zA-Z0-9\-_]/', '_', $name)"}'>
<input type='text' name='{$userSuppliedInput}_{$name}' value="{{if !\in_array( $value, array_keys( $options ) )}}{$value}{{endif}}" id='{$userSuppliedInput}_{expression="preg_replace('/[^a-zA-Z0-9\-_]/', '_', $name)"}'>
{{endif}}
{{if isset( $descriptions[ $k ] )}}
<br>
<span class='ipsFieldRow_desc'>
{$descriptions[ $k ]|raw}
</span>
{$descriptions[ $k ]|raw}
{{endif}}
{{if isset( $warnings[ $k ] )}}
<div id="{$name}_{$k}_warning">
<br>
<p class='ipsMessage ipsMessage_warning'>{$warnings[ $k ]|raw}</p>
</div>
{$warnings[ $k ]|raw}
{{endif}}
</div>
</li>
+1 -1
View File
@@ -2,7 +2,7 @@
<form action="{$action}" method="post" {{if $uploadField}}enctype="multipart/form-data"{{endif}}>
<input type="hidden" name="{$id}_submitted" value="1">
{{foreach $hiddenValues as $k => $v}}
{{if is_array( $v )}}
{{if \is_array( $v )}}
{{foreach $v as $_k => $_v}}
<input type="hidden" name="{$k}[{$_k}]" value="{$_v}">
{{endforeach}}
+2 -2
View File
@@ -16,7 +16,7 @@
{{if $autoComplete['unique']}}
data-ipsAutocomplete-unique
{{endif}}
{{if is_array( $autoComplete['source'] )}}
{{if \is_array( $autoComplete['source'] )}}
list='{$name}_datalist'
{{elseif $autoComplete['source']}}
data-ipsAutocomplete-dataSource="{url="{$autoComplete['source']}"}"
@@ -28,7 +28,7 @@
{{endif}}
{{if $placeholder !== NULL}}placeholder='{$placeholder}'{{endif}}
/>
{{if is_array( $autoComplete )}}
{{if \is_array( $autoComplete )}}
<datalist id="{$name}_datalist">
{{foreach $autoComplete as $v}}
<option value="$v">{$v}</option>
+1 -1
View File
@@ -2,7 +2,7 @@
<div class='ipsPad_double ipsType_center'>
<a href='{url="controller=upgrade&key={$_SESSION['uniqueKey']}"}' class='ipsButton ipsButton_large ipsButton_primary'>{lang="start_upgrade"}</a>
</div>
<div class='ipsType_large'>
<div class='ipsType_large ipsType_center'>
{{if \IPS\CIC}}
{lang="upgrade_confirm_cic"}
{{else}}
@@ -1,7 +1,7 @@
<ips:template parameters="$disabledApps, $disabledPlugins" />
<div class="ipsPad">
<p class="ipsType_normal">{lang="third_party_stuff_disabled"}</p>
{{if count( $disabledApps )}}
{{if \count( $disabledApps )}}
<p class="ipsType_normal">{lang="third_party_stuff_disabled_apps"}</p>
<ul class='ipsList_bullets'>
{{foreach $disabledApps as $app}}
@@ -9,7 +9,7 @@
{{endforeach}}
</ul>
{{endif}}
{{if count( $disabledPlugins )}}
{{if \count( $disabledPlugins )}}
<p class="ipsType_normal">{lang="third_party_stuff_disabled_plugins"}</p>
<ul class='ipsList_bullets'>
{{foreach $disabledPlugins as $plugin}}
+1 -1
View File
@@ -4,7 +4,7 @@
<span class="ipsMessage_code">{$code}</span>
{lang="$message"}
<br />
{{if is_array($mr) and count($mr)}}
{{if \is_array($mr) and \count($mr)}}
<small>{lang="location"}: {lang="step" sprintf="\IPS\Dispatcher::i()->step ?: 1"} {$mr[0]}. {lang="application"}: {expression="ucfirst($mr[1])"}</small>
{{endif}}
</div>
+1 -1
View File
@@ -45,7 +45,7 @@
{{endforeach}}
</ul>
{{endforeach}}
{{if isset( $requirements['advice'] ) and count( $requirements['advice'] )}}
{{if isset( $requirements['advice'] ) and \count( $requirements['advice'] )}}
<h2 class="ipsType_sectionHead">{lang="hc_recommendations"}</h2>
<br><br>
<p class="ipsType_normal">{lang="hc_recommendations_info"}</p>
Binary file not shown.

Before

Width:  |  Height:  |  Size: 729 B

After

Width:  |  Height:  |  Size: 585 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 161 B

After

Width:  |  Height:  |  Size: 120 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 744 B

After

Width:  |  Height:  |  Size: 626 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 500 B

After

Width:  |  Height:  |  Size: 361 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 953 B

After

Width:  |  Height:  |  Size: 662 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 724 B

After

Width:  |  Height:  |  Size: 605 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 665 B

After

Width:  |  Height:  |  Size: 577 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.0 KiB

+3 -3
View File
@@ -8,11 +8,11 @@
* @since 20 May 2014
*/
define('READ_WRITE_SEPARATION', FALSE);
define('REPORT_EXCEPTIONS', TRUE);
\define('READ_WRITE_SEPARATION', FALSE);
\define('REPORT_EXCEPTIONS', TRUE);
/* Prevent hooks from running during the upgrade */
define('RECOVERY_MODE', TRUE);
\define('RECOVERY_MODE', TRUE);
require_once '../../init.php';
+71 -3
View File
@@ -83,6 +83,7 @@ $lang = array(
'requirements_php_version_advice' => "You are running PHP version %s. While this version is compatible, we recommend version %s or above.",
'requirements_curl_success' => "cURL extension loaded.",
'requirements_curl_fopen' => "fsockopen function available",
'requirements_file_uploads' => "File uploads are currently disabled in your PHP configuration, which will prevent many features from working correctly. You should contact your host to have the option `file_uploads` enabled.",
'requirements_curl_advice' => "You do not have the cURL PHP extension loaded or it is running a version less than 7.36. While this is not required, it is recommended.",
'requirements_curl_fail' => "You do not have the cURL PHP extension loaded (or it is running a version less than 7.36) and the fsockopen function is disabled. You should contact your hosting provider or system administrator to ask either for cURL version 7.36 or greater to be installed, or the fsockopen function to be enabled. cURL is recommended.",
'requirements_mb_success' => "Multibyte String extension loaded",
@@ -123,6 +124,7 @@ $lang = array(
'dir_does_not_exist' => "%s does not exist.",
'dir_is_not_writable' => "%s cannot be written to. Please adjust the permissions on it or contact your hosting provider for assistance.",
'file_storage_test_error_amazon' => "There appears to be a problem with your Amazon (%s) file storage settings which can cause problems with uploads.<br> After attempting to upload a file to the directory, the URL to the file is returning a HTTP %s error. Update your settings and then check and see if the problem has been resolved",
'filehandler__Database' => "Database",
'ftp_err_no_ext' => "Your server does not support using FTP storage. Please contact your hosting provider to ask for PHP FTP extension to be enabled.",
'ftp_err_no_ssl' => "Your server does not support using SSL-FTP storage. Please contact your hosting provider to ask for PHP OpenSSL extension to be enabled or use a different protocol.",
'ftp_err_no_sftp' => "Your server does not support using SFTP storage. Please contact your hosting provider to ask for PHP SSH2 extension to be enabled or use a different protocol.",
@@ -167,6 +169,9 @@ $lang = array(
'installer' => "Invision Community Installer - %s",
'default_menu_item_1' => "Browse",
'default_menu_item_2' => "Activity",
'error' => "Error",
'page_doesnt_exist' => "That page doesn't exist.",
'upgrade_session_error' => "The security token used to validate your session is missing or invalid. This can happen if you have been inactive for a long time or followed an incorrect link to the upgrader. Please restart the upgrader to resolve this issue.",
@@ -538,6 +543,9 @@ $lang = array(
'101079_diagnostics_reporting' => "Send diagnostics data to IPS?",
'101079_diagnostics_reporting_desc' => "This distribution is nulled and this setting does not work. Help Invision Community improve by automatically sending diagnostic information. The data sent does not contain any private information about your users or your community.",
'104000_es_version' => "Elasticsearch version in use is no longer supported",
'104000_paypal_warning' => "PayPal Functionality",
/* ! Core 102000 Letter photo option */
'options_letter_photos' => "Enable letter photos?",
'options_letter_photos_desc' => "Do you wish to start using automatic letter photos instead of the default theme profile photo for users who have not uploaded a profile photo?",
@@ -560,7 +568,7 @@ $lang = array(
'hc_designers_dis_info' => "Disabling Designers' Mode now will <strong>not</strong> synchronize your templates.<br>If you need to save your edited files, please synchronize them via the ACP &gt; Customization &gt; Themes before disabling Designer's Mode.",
'hc_requirements' => "%s Requirements",
'hc_recommendations' => "Recommendations",
'hc_recommendations_info' => "None of these items are required in order to continue with the upgrade right now. However, they will be required in a future version of Invision Community. You should make a note of them and contact your hosting provider or system administrator after the upgrade to address them. You can re-run these checks later from the <em>Support</em> section of the Administrator Control Panel.",
'hc_recommendations_info' => "None of these items are required in order to continue with the upgrade right now. However, they may affect how your community works or be required in future upgrades. You should make a note of them and contact your hosting provider or system administrator after the upgrade to address them. You can re-run these checks later from the <em>Support</em> section of the Administrator Control Panel.",
'hc_no_continue' => "You must correct any issues listed above before you can proceed",
'upgrader_banner' => "Upgrade Invision Community 4",
'upgradeoptions' => 'Upgrade Options',
@@ -573,10 +581,14 @@ $lang = array(
'install_docs' => "Install Guide",
'js_confirm_mrerror' => 'The server encountered multiple instances where it has stopped responding.\nPress \'OK\' to reload this page and re-run this installation step.',
'hc_files' => "File Check",
'hc_files_ok' => "Source files are correct for the latest version",
'hc_files_fail' => "Some source files are not correct for the latest version. If you uploaded the files to your server manually, the process may have failed or not completed yet, or a new version may have been released since you downloaded. Download latest version from your client area and upload the files again in order to continue.",
'hc_files_ok' => "Source files are correct for the current version",
'hc_files_fail' => "Some source files are not correct for the current version. If you uploaded the files to your server manually, the process may have failed or not completed yet. Download the latest version from your client area and upload the files again in order to continue.",
'hc_files_fail2' => "Go To Client Area",
'hc_files_fail3' => "If you are sure the files have been uploaded correctly, make sure the permissions are set correctly on them.",
'filehandler__Amazon' => "Amazon S3",
'filehandler_display_name' => "%s: %s",
'file_storage_test_chunk_mismatch' => "Uploads to '%s' will be limited to %s. To increase this, contact your hosting provider or system administrator and ask for the following PHP settings to be increased to above %s (they do not need to be higher than this as above this size files can be uploaded in chunks): %s.",
'file_storage_test_chunk_mismatch_value' => "%s (currently %s)",
/* ! Core - 4.3 - Removing HTTPS settings */
'https_settings_changes' => "HTTPS Settings Changes",
@@ -587,6 +599,10 @@ $lang = array(
'103000_ipsconnect_url' => "IPS Connect Master Site URL",
'103000_ipsconnect_client_id' => "IPS Connect Client Identifier",
'103000_ipsconnect_client_secret' => "IPS Connect Client Secret",
/* ! LinkedIn v2 API */
'104020_linkedin' => "LinkedIn Login Method API Update",
'files-1' => "File could not be opened: %s",
'files-2' => "File does not exist: %s",
@@ -596,4 +612,56 @@ $lang = array(
'files-6' => "Folder could not be created: %s",
'files-7' => "Response returned a 400 response code but no Amazon region was returned: %s",
/* ! Core - 4.5 - Elastic search version */
'105000_es_version' => "Elasticsearch version in use is no longer supported",
/* ! Core - 4.5 - BBCode enable/disable */
'105000_enable_bbcode' => "BBCode Processing",
'105000_enable_bbcode_desc' => "BBCode is a lightweight markup language that was originally designed to allow users to submit rich content prior to the advancement of WYSIWYG editors by using special tags within square brackets (for instance, to bold content you would manually type out [b]bolded text[/b]). This version of Invision Community deprecates BBCode support. This functionality will continue if enabled, but may be completely removed in a future version. What does this mean for you? If your community does not rely on legacy BBCode support, we recommend you opt to disable it now for greater posting performance and reliability. If you do rely on BBCode, you may choose to keep it enabled at this time, however we encourage you to explore ways to transition to the preferred, native editor.",
'105000_bbcode_disable' => "Disable BBCode support",
'105000_bbcode_enable' => "Enable BBCode support",
/* ! Core - 4.5 - New pruning enable/disable */
'105000_prune' => "Pruning Defaults",
'105000_prune_desc' => "New pruning options have been introduced in this release which will remove old item markers, follow records, member IP addresses and known member devices. Pruning this data can reduce the size of your database, improving your site's performance and potentially saving you money, however it will mean that unread markers will be reset and follow records will be removed for members who have not visited for a long period of time, and IP addresses and devices will be removed after a year. The time periods to retain this data can be configured in the AdminCP after upgrading. Do you wish to use the new pruning default values?",
'105000_prune_disable' => "I will configure this later",
'105000_prune_enable' => "Use new pruning defaults",
/* !Core - 4.5 - Notification Settings */
'105000_notifications' => "Notification Options",
'notification_method_inline' => "Notification List",
'notification_method_email' => "Email",
'notification_editable_yes' => "Yes, members can choose how they want to receive these notifications",
'notification_editable_no' => "No",
'105000_notifications_editable' => "%s: Should this option be EDITABLE?",
'105000_notifications_default' => "%s: What should the DEFAULT options be?",
'105000_notifications_disabled' => "%s: What should the DISABLED options be?",
'notifications__content' => "Followed Content",
'notifications__content_desc'=> "These notifications will be sent whenever there is new activity on things you are following and have opted to receive immediate notifications for.",
'notifications__members' => "Followed Members",
'notifications__members_desc' => "These notifications will be sent whenever a member you are following makes a post.",
'notifications__core_MyStuff' => "Mentions &amp; My Content",
'notifications__core_MyStuff_desc' => "These notifications will be sent whenever someone mentions you or interacts with content you have posted.",
'notifications__core_Messenger' => "Messenger",
'notifications__core_Messenger_desc' => "These notifications will be sent whenever you receive a personal message.",
'notifications__core_Clubs_invites' => "Club Invitations",
'notifications__core_Clubs_invites_desc' => "These notifications will be sent whenever you are invited to join a club or your request to join a club is responded to.",
'notifications__core_Clubs_leader' => "Clubs I Lead",
'notifications__core_Clubs_leader_desc' => "These notifications will be sent whenever a member joins, or requests to join, a club that you are the leader of.",
'notifications__core_Profile_status' => "Status Updates &amp; Profile Comments",
'notifications__core_Profile_status_desc' => "These notifications will be sent whenever someone posts on your profile or replies to a status update that you posted, is on your profile, or that you replied to.",
'notifications__core_Profile_follow' => "New Followers",
'notifications__core_Profile_follow_desc' => "These notifications will be sent whenever someone follows you.",
'notifications__report_center' => "Reports",
'notifications__report_center_desc' => "These notifications will be sent whenever a user reports content that you are able to moderate.",
'notifications__unapproved_content' => "Moderator Approval",
'notifications__unapproved_content_desc' => "These notifications are sent whenever content is posted that requires a moderator to manually approve it and you are able to do so.",
'notifications__automatic_moderation' => "Automatic moderation",
'notifications__automatic_moderation_desc' => "These notifications will be sent when something has been reported enough times that it is automatically hidden.",
'notifications__warning_mods' => "Warnings",
'notifications__warning_mods_desc' => "These notifications will be sent whenever another moderator issues a warning.",
'notifications__new_file_version' => "File Updates",
'notifications__event_reminder' => "Event Reminders",
);
File renamed without changes.
+76
View File
@@ -0,0 +1,76 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>An update is available</title>
<style type='text/css'>
body {
background: #f9f9f9;
margin: 0;
padding: 30px 20px;
font-family: "Helvetica Neue", helvetica, arial, sans-serif;
}
#error {
max-width: 800px;
background: #fff;
margin: 0 auto;
}
h1 {
background: #151515;
color: #fff;
font-size: 22px;
font-weight: 500;
padding: 10px;
}
h1 span {
color: #7a7a7a;
font-size: 14px;
font-weight: normal;
}
#content {
padding: 20px;
line-height: 1.6;
}
.buttonsRow {
text-align: center;
margin-top: 50px;
}
.button {
background: #151515;
color: #fff;
border: 0;
line-height: 34px;
padding: 0 15px;
font-family: "Helvetica Neue", helvetica, arial, sans-serif;
font-size: 14px;
border-radius: 3px;
cursor: pointer;
}
.nodontdoit {
background: #e0e0e0;
color: #222;
margin-left: 50px;
}
</style>
</head>
<body>
<div id='error'>
<h1>Your site is ready to upgrade</h1>
<div id='content'>
<p>A new version is available to install and it is strongly recommended that you complete the upgrade process for this new version before continuing to the AdminCP. Sometimes changes in new versions will result in errors until the upgrade process has been completed.</p>
<p>The new version is ready to be applied to your site.</p>
<p>Just click Complete Upgrade below and login with your AdminCP credentials. Your total downtime will be less than 5 minutes.</p>
<div class='buttonsRow'>
<button onclick="window.location='upgrade/'" class='button'>Complete Upgrade</button>
<button onclick="window.location=window.location + '&noWarning=1'" class='button nodontdoit'>Continue to AdminCP</button>
</div>
</div>
</div>
</body>
</html>
+75
View File
@@ -0,0 +1,75 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>An upgrade has been started</title>
<style type='text/css'>
body {
background: #f9f9f9;
margin: 0;
padding: 30px 20px;
font-family: "Helvetica Neue", helvetica, arial, sans-serif;
}
#error {
max-width: 800px;
background: #fff;
margin: 0 auto;
}
h1 {
background: #151515;
color: #fff;
font-size: 22px;
font-weight: 500;
padding: 10px;
}
h1 span {
color: #7a7a7a;
font-size: 14px;
font-weight: normal;
}
#content {
padding: 20px;
line-height: 1.6;
}
.buttonsRow {
text-align: center;
margin-top: 50px;
}
.button {
background: #151515;
color: #fff;
border: 0;
line-height: 34px;
padding: 0 15px;
font-family: "Helvetica Neue", helvetica, arial, sans-serif;
font-size: 14px;
border-radius: 3px;
cursor: pointer;
}
.nodontdoit {
background: #e0e0e0;
color: #222;
margin-left: 50px;
}
</style>
</head>
<body>
<div id='error'>
<h1>You have started an upgrade</h1>
<div id='content'>
A new version has been uploaded and the upgrade process has been started. You must complete the upgrade before you will be able to access the AdminCP.
<div class='buttonsRow'>
<button onclick="window.location='upgrade/'" class='button'>Complete Upgrade</button>
<?php if( \IPS\RECOVERY_MODE === TRUE ): ?><button onclick="window.location=window.location + '&noWarning=1'" class='button nodontdoit'>Continue to AdminCP</button><?php endif; ?>
</div>
</div>
</div>
</body>
</html>