r20150926

Signed-off-by: Flashwave <me@flash.moe>
This commit is contained in:
flash 2015-09-26 18:12:42 +02:00
parent 5a1264f329
commit ab2c8df958
26 changed files with 2705 additions and 399 deletions

227
.gitignore vendored
View file

@ -1,237 +1,14 @@
#################
## Eclipse
#################
*.pydevproject
.project
.metadata
bin/
tmp/
*.tmp
*.bak
*.swp
*~.nib
local.properties
.classpath
.settings/
.loadpath
# External tool builders
.externalToolBuilders/
# Locally stored "Eclipse launch configurations"
*.launch
# CDT-specific
.cproject
# PDT-specific
.buildpath
#################
## PHP Storm
#################
.idea/ .idea/
#################
## Sakura
#################
errors.log errors.log
_sakura/config/config.ini _sakura/config/config.ini
BingSiteAuth.xml BingSiteAuth.xml
google*.html google*.html
cache/* cache/*
!cache/.htaccess !cache/.sakura
uploads/* uploads/*
!uploads/.htaccess !uploads/.sakura
#################
## Visual Studio
#################
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
# User-specific files
*.suo
*.user
*.sln.docstates
# Build results
[Dd]ebug/
[Rr]elease/
x64/
build/
[Bb]in/
[Oo]bj/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
*_i.c
*_p.c
*.ilk
*.meta
*.obj
*.pch
*.pdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*.log
*.vspscc
*.vssscc
.builds
*.pidb
*.log
*.scc
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opensdf
*.sdf
*.cachefile
# Visual Studio profiler
*.psess
*.vsp
*.vspx
# Guidance Automation Toolkit
*.gpState
# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
# TeamCity is a build add-in
_TeamCity*
# DotCover is a Code Coverage Tool
*.dotCover
# NCrunch
*.ncrunch*
.*crunch*.local.xml
# Installshield output folder
[Ee]xpress/
# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html
# Click-Once directory
publish/
# Publish Web Output
*.Publish.xml
*.pubxml
*.publishproj
# NuGet Packages Directory
## TODO: If you have NuGet Package Restore enabled, uncomment the next line
#packages/
# Windows Azure Build Output
csx
*.build.csdef
# Windows Store app package directory
AppPackages/
# Others
sql/
*.Cache
ClientBin/
[Ss]tyle[Cc]op.*
~$*
*~
*.dbmdl
*.[Pp]ublish.xml
*.pfx
*.publishsettings
# RIA/Silverlight projects
Generated_Code/
# Backup & report files from converting an old project file to a newer
# Visual Studio version. Backup files are not needed, because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
# SQL Server files
App_Data/*.mdf
App_Data/*.ldf
#############
## Windows detritus
#############
# Windows image file caches
[Tt]humbs.db [Tt]humbs.db
ehthumbs.db ehthumbs.db
# Folder config file
Desktop.ini Desktop.ini
# Recycle Bin used on file shares
$RECYCLE.BIN/ $RECYCLE.BIN/
# Mac crap
.DS_Store .DS_Store
#############
## Python
#############
*.py[cod]
# Packages
*.egg
*.egg-info
dist/
build/
eggs/
parts/
var/
sdist/
develop-eggs/
.installed.cfg
# Installer logs
pip-log.txt
# Unit test / coverage reports
.coverage
.tox
#Translations
*.mo
#Mr Developer
.mr.developer.cfg

View file

@ -1,12 +0,0 @@
# Disallow external connections
# Apache <= 2.2
<IfModule !mod_authz_core.c>
Order deny,allow
deny from all
</IfModule>
# Apache 2.4 =>
<IfModule mod_authz_core.c>
Require all denied
</IfModule>

View file

@ -2869,7 +2869,58 @@
}, },
{ {
"type": "ADD", "type": "ADD",
"change": "Implement username changing.", "change": "Implemented username changing.",
"user": "Flashwave"
}
],
"20150926": [
"eminence",
{
"type": "UPD",
"change": "Improved the ajaxBusyView thing.",
"user": "Flashwave"
},
{
"type": "ADD",
"change": "Added AJAX methods to the friend actions in the settings panel.",
"user": "Flashwave"
},
{
"type": "REM",
"change": "Removed unneeded .htaccess files.",
"user": "Flashwave"
},
{
"type": "UPD",
"change": "Removed unneeded lines from .gitignore.",
"user": "Flashwave"
},
{
"type": "ADD",
"change": "Added userpages back in.",
"user": "Flashwave"
},
{
"type": "ADD",
"change": "Added live preview for userpages.",
"user": "Flashwave"
},
{
"type": "FIX",
"change": "Fixed sanitising in userpages code.",
"user": "Flashwave"
},
{
"type": "ADD",
"change": "Added 4 of the 5 Account section pages (all except Ranks as this system is getting a change soon probably).",
"user": "Flashwave"
},
{
"type": "ADD",
"change": "Added Deactivate Account template and <a href='http://i.flash.moe/1443283802-329-2769.png' target='_blank'>placeholder logic</a>.",
"user": "Flashwave" "user": "Flashwave"
} }

View file

@ -29,10 +29,14 @@ class Main
} }
// Parse markdown // Parse markdown
public static function mdParse($text) public static function mdParse($text, $escape = false)
{ {
return (new Parsedown())->text($text); $pd = new Parsedown();
return $escape ?
$pd->setMarkupEscaped(true)->text($text) :
$pd->text($text);
} }
@ -140,8 +144,11 @@ class Main
if ($past = Database::fetch( if ($past = Database::fetch(
'error_log', 'error_log',
false, false,
['backtrace' => [$backtrace, '=', true], [
'error_string' => [$errstr, '=']] 'backtrace' => [$backtrace, '=', true],
'error_string' => [$errstr, '='],
'error_line' => [$errstr, '='],
]
)) { )) {
// If so assign the errid // If so assign the errid
$errid = $past['id']; $errid = $past['id'];

View file

@ -337,6 +337,21 @@ class User
} }
// Get all warnings issued to the user
public function userPage()
{
return isset($this->data['userData']['userPage']) ?
Main::mdParse(
base64_decode(
$this->data['userData']['userPage']
),
true
) :
null;
}
// Get username change history // Get username change history
public function getUsernameHistory() public function getUsernameHistory()
{ {
@ -414,4 +429,92 @@ class User
return [1, 'SUCCESS', $username]; return [1, 'SUCCESS', $username];
} }
// Set a new e-mail address
public function setEMailAddress($email)
{
// Validate e-mail address
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
return [0, 'INVALID'];
}
// Check if the username is already in use
$getInUse = Database::fetch('users', false, [
'email' => [$email, '='],
]);
// Check if anything was returned
if ($getInUse) {
return [0, 'IN_USE', $getInUse['id']];
}
// Update userrow
Database::update('users', [
[
'email' => $email,
],
[
'id' => [$this->data['id'], '='],
],
]);
// Return success
return [1, 'SUCCESS', $email];
}
// Set a new password
public function setPassword($old, $new, $confirm)
{
// Validate password
switch ($this->data['password_algo']) {
// Abyssing
case 'nologin':
return [0, 'NO_LOGIN'];
// Default hashing method
default:
if (!Hashing::validatePassword($old, [
$this->data['password_algo'],
$this->data['password_iter'],
$this->data['password_salt'],
$this->data['password_hash'],
])) {
return [0, 'INCORRECT_PASSWORD', $this->data['password_chan']];
}
}
// Check password entropy
if (Main::pwdEntropy($new) < Configuration::getConfig('min_entropy')) {
return [0, 'PASS_TOO_SHIT'];
}
// Passwords do not match
if ($new != $confirm) {
return [0, 'PASS_NOT_MATCH'];
}
// Create hash
$password = Hashing::createHash($new);
// Update userrow
Database::update('users', [
[
'password_hash' => $password[3],
'password_salt' => $password[2],
'password_algo' => $password[0],
'password_iter' => $password[1],
'password_chan' => time(),
],
[
'id' => [$this->data['id'], '='],
],
]);
// Return success
return [1, 'SUCCESS'];
}
} }

View file

@ -8,7 +8,7 @@
namespace Sakura; namespace Sakura;
// Define Sakura version // Define Sakura version
define('SAKURA_VERSION', '20150923'); define('SAKURA_VERSION', '20150926');
define('SAKURA_VLABEL', 'Eminence'); define('SAKURA_VLABEL', 'Eminence');
define('SAKURA_COLOUR', '#6C3082'); define('SAKURA_COLOUR', '#6C3082');
define('SAKURA_STABLE', false); define('SAKURA_STABLE', false);

View file

@ -0,0 +1,14 @@
<script src="https://www.google.com/recaptcha/api.js" async defer></script>
<div class="g-recaptcha" data-sitekey="{{ sakura.recaptchaPublic }}" style="margin: auto; display: inline-block;"></div>
<noscript>
<div style="width: 302px; height: 352px; margin: auto; display: inline-block;">
<div style="width: 302px; height: 352px; position: relative;">
<div style="width: 302px; height: 352px; position: absolute;">
<iframe src="https://www.google.com/recaptcha/api/fallback?k={{ sakura.recaptchaPublic }}" frameborder="0" scrolling="no" style="width: 302px; height:352px; border-style: none;"></iframe>
</div>
<div style="width: 250px; height: 80px; position: absolute; border-style: none; bottom: 21px; left: 25px; margin: 0px; padding: 0px; right: 25px;">
<textarea id="g-recaptcha-response" name="g-recaptcha-response" class="g-recaptcha-response" style="width: 250px; height: 80px; border: 1px solid #c1c1c1; margin: 0px; padding: 0px; resize: none;" value=""></textarea>
</div>
</div>
</div>
</noscript>

View file

@ -143,13 +143,11 @@
// Error reporter // Error reporter
window.onerror = function(msg, url, line, col, error) { window.onerror = function(msg, url, line, col, error) {
notifyUI({ notifyUI({
"title": "An error has occurred!", "title": "An error has occurred!",
"text": "There was a problem while executing the JavaScript code for this page: " + msg + ", URL: " + url + ", Line: " + line + ", Column: " + col + ". Please report this to a developer.", "text": "There was a problem while executing the JavaScript code for this page: " + msg + ", URL: " + url + ", Line: " + line + ", Column: " + col + ". Please report this to a developer.",
"img": "FONT:fa-warning" "img": "FONT:fa-warning"
}); });
} }
</script> </script>

View file

@ -61,7 +61,7 @@
<input class="inputStyling" type="submit" name="submit" value="Request Password" id="requestPassBtn" /> <input class="inputStyling" type="submit" name="submit" value="Request Password" id="requestPassBtn" />
</div> </div>
<div class="subLinks centreAlign"> <div class="subLinks centreAlign">
If you lost access to the e-mail address you registered with then there's not much we can do, it's your own responsibility to keep track of it and attaching a working one to your account. Contact us if you lost access to your e-mail address!
</div> </div>
</form> </form>
</div> </div>
@ -113,20 +113,7 @@
<label for="recaptcha_response_field">Verification:</label> <label for="recaptcha_response_field">Verification:</label>
</div> </div>
<div class="centreAlign"> <div class="centreAlign">
<script src="https://www.google.com/recaptcha/api.js" async defer></script> {% include 'elements/captcha.tpl' %}
<div class="g-recaptcha" data-sitekey="{{ sakura.recaptchaPublic }}" style="margin: auto; display: inline-block;"></div>
<noscript>
<div style="width: 302px; height: 352px; margin: auto; display: inline-block;">
<div style="width: 302px; height: 352px; position: relative;">
<div style="width: 302px; height: 352px; position: absolute;">
<iframe src="https://www.google.com/recaptcha/api/fallback?k={{ sakura.recaptchaPublic }}" frameborder="0" scrolling="no" style="width: 302px; height:352px; border-style: none;"></iframe>
</div>
<div style="width: 250px; height: 80px; position: absolute; border-style: none; bottom: 21px; left: 25px; margin: 0px; padding: 0px; right: 25px;">
<textarea id="g-recaptcha-response" name="g-recaptcha-response" class="g-recaptcha-response" style="width: 250px; height: 80px; border: 1px solid #c1c1c1; margin: 0px; padding: 0px; resize: none;" value=""></textarea>
</div>
</div>
</div>
</noscript>
</div> </div>
{% endif %} {% endif %}
<div class="subLinks centreAlign"> <div class="subLinks centreAlign">

View file

@ -5,11 +5,7 @@
<h3 style="text-align: center;">Your e-mail address is currently set to <span style="font-weight: 700;">{{ user.data.email }}</span>.</h3> <h3 style="text-align: center;">Your e-mail address is currently set to <span style="font-weight: 700;">{{ user.data.email }}</span>.</h3>
<div class="profile-field"> <div class="profile-field">
<div><h2>E-mail address</h2></div> <div><h2>E-mail address</h2></div>
<div><input type="text" name="emailnew" placeholder="Enter your new e-mail address" class="inputStyling" /></div> <div><input type="text" name="email" placeholder="Enter your new e-mail address" class="inputStyling" /></div>
</div>
<div class="profile-field">
<div><h2>Confirmation</h2></div>
<div><input type="text" name="emailver" placeholder="Just to make sure..." class="inputStyling" /></div>
</div> </div>
<div class="profile-save"> <div class="profile-save">
<input type="submit" value="Save" name="submit" class="inputStyling" /> <input type="submit" value="Save" name="submit" class="inputStyling" />

View file

@ -4,15 +4,15 @@
<input type="hidden" name="mode" value="password" /> <input type="hidden" name="mode" value="password" />
<div class="profile-field"> <div class="profile-field">
<div><h2>Current Password</h2></div> <div><h2>Current Password</h2></div>
<div><input type="password" name="currentpw" placeholder="Enter your current password for verification." class="inputStyling" /></div> <div><input type="password" name="oldpassword" placeholder="Enter your current password for verification." class="inputStyling" /></div>
</div> </div>
<div class="profile-field"> <div class="profile-field">
<div><h2>New Password</h2></div> <div><h2>New Password</h2></div>
<div><input type="password" name="newpw" placeholder="Enter your new password." class="inputStyling" /></div> <div><input type="password" name="newpassword" placeholder="Enter your new password." class="inputStyling" /></div>
</div> </div>
<div class="profile-field"> <div class="profile-field">
<div><h2>Confirmation</h2></div> <div><h2>Confirmation</h2></div>
<div><input type="password" name="conpw" placeholder="Enter your new password again to make sure you didn't fuck up." class="inputStyling" /></div> <div><input type="password" name="newpasswordconfirm" placeholder="Enter your new password again to make sure you didn't fuck up." class="inputStyling" /></div>
</div> </div>
<div class="profile-save"> <div class="profile-save">
<input type="submit" value="Save" name="submit" class="inputStyling" /> <input type="submit" value="Save" name="submit" class="inputStyling" />

View file

@ -0,0 +1,35 @@
<form enctype="multipart/form-data" method="post" action="{{ sakura.currentPage }}" id="changePasswordForm">
<input type="hidden" name="sessid" value="{{ php.sessionid }}" />
<input type="hidden" name="timestamp" value="{{ php.time }}" />
<input type="hidden" name="mode" value="deactivate" />
<div class="profile-field">
<div><h2>Username</h2></div>
<div><input type="text" name="username" placeholder="Case sensitive" class="inputStyling" /></div>
</div>
<div class="profile-field">
<div><h2>Password</h2></div>
<div><input type="password" name="password" placeholder="Security" class="inputStyling" /></div>
</div>
<div class="profile-field">
<div><h2>E-mail address</h2></div>
<div><input type="text" name="email" placeholder="More security" class="inputStyling" /></div>
</div>
<div class="profile-field">
<div><h2>Type &quot;I am one hundred percent sure that I want to deactivate my account.&quot; without the quotes.</h2></div>
<div><input type="text" name="sensitive" placeholder="Are you 100% case sensitively sure?" class="inputStyling" /></div>
</div>
<div class="profile-field">
<div><h2>Verification</h2></div>
<div style="text-align: center;">{% include 'elements/captcha.tpl' %}</div>
</div>
<div class="profile-save">
<input type="submit" value="Goodbye!" name="submit" class="inputStyling" />
</div>
</form>
<script type="text/javascript">
window.addEventListener("load", function() {
prepareAjaxForm('changePasswordForm', 'Changing password...');
});
</script>

View file

@ -1,26 +1,34 @@
{# {% block js %}
{% if preview %} <script type="text/javascript" charset="utf-8" src="{{ sakura.contentPath }}/libraries/showdown.js"></script>
<div class="markdown" style="max-height: 600px;overflow-y:auto;"> {% endblock %}
{{ preview|raw }}
</div> <div class="markdown" id="userPagePreview" style="max-height: 500px; overflow-y: auto; background: #C2AEEE; box-shadow: inset 0 0 1em 1em #D3BFFF;">
<hr class="default" /> <noscript>
{% endif %} <h1 class="stylised" style="margin: 1em auto;">The preview requires JavaScript, enable it.</h1>
<form enctype="multipart/form-data" method="post" action="{{ sakura.currentPage }}"> </noscript>
</div>
<hr class="default" />
<form enctype="multipart/form-data" method="post" action="{{ sakura.currentPage }}" id="userPageEditorForm">
<input type="hidden" name="sessid" value="{{ php.sessionid }}" /> <input type="hidden" name="sessid" value="{{ php.sessionid }}" />
<input type="hidden" name="timestamp" value="{{ php.time }}" /> <input type="hidden" name="timestamp" value="{{ php.time }}" />
<input type="hidden" name="mode" value="userpage" /> <input type="hidden" name="mode" value="userpage" />
<div><textarea name="userpage" placeholder="# Welcome to my profile page!" class="inputStyling" style="width: calc(100% - 12px); height: 500px;" />{{ userPage.content }}</textarea></div> <div><textarea name="userpage" id="userPageEditor" placeholder="# Welcome to my user page!" class="inputStyling" style="width: calc(100% - 12px); height: 400px;" />{% if userPage %}{{ userPage }}{% else %}# Welcome to my user page!{% endif %}</textarea></div>
<div>
<h2>Parse mode</h2>
<input type="radio" name="parse" value="bbcode" id="bbcode"{% if userPage.parse == 1 %} checked="checked"{% endif %} /> <label for="bbcode">BBCodes</label>
<input type="radio" name="parse" value="markdown" id="markdown"{% if userPage.parse == 2 %} checked="checked"{% endif %} /> <label for="markdown">Markdown</label>
<input type="radio" name="parse" value="plain" id="plain"{% if userPage.parse == 0 %} checked="checked"{% endif %} /> <label for="plain">Plain Text</label>
</div>
<div class="profile-save"> <div class="profile-save">
<input type="submit" value="Save" name="submit" class="inputStyling" /> <input type="submit" value="Save" name="submit" class="inputStyling" />
<input type="submit" value="Preview" name="preview" class="inputStyling" />
<input type="reset" value="Reset" name="reset" class="inputStyling" /> <input type="reset" value="Reset" name="reset" class="inputStyling" />
</div> </div>
</form> </form>
#} <script type="text/javascript">
<h1 class="stylised">Redoing this bc garbage.</h1> var converter = new showdown.Converter();
function updateUserPage() {
document.getElementById('userPagePreview').innerHTML = converter.makeHtml(safeTagsReplace(document.getElementById('userPageEditor').value));
}
document.getElementById('userPageEditor').addEventListener('keyup', updateUserPage);
window.addEventListener('load', function() {
prepareAjaxForm('userPageEditorForm', 'Updating user page...');
updateUserPage();
});
</script>

View file

@ -1,13 +1,25 @@
{% block js %}
<script type="text/javascript">
window.addEventListener("load", function() {
var friendsListActions = document.querySelectorAll('[id^="friendslist-friend-action-"]');
for (var i in friendsListActions) {
prepareAjaxLink(friendsListActions[i], 'submitPost', ', true, "Please wait.."');
}
});
</script>
{% endblock %}
{% if friends|length %} {% if friends|length %}
<div class="friends-list"> <div class="friends-list">
{% for friend in friends[page.currentPage] %} {% for friend in friends[page.currentPage] %}
<div class="friend-container" id="friend-{{ friend.user.id }}"> <div class="friend-container" id="friendslist-friend-{{ friend.user.id }}">
<a class="friends-list-data clean" href="/u/{{ friend.user.id }}"> <a class="friends-list-data clean" href="/u/{{ friend.user.id }}">
<img src="/a/{{ friend.user.id }}" alt="{{ friend.user.username }}" class="friends-list-avatar default-avatar-setting" style="width: 150px; height: 150px;" /> <img src="/a/{{ friend.user.id }}" alt="{{ friend.user.username }}" class="friends-list-avatar default-avatar-setting" style="width: 150px; height: 150px;" />
<div class="friends-list-name" style="color: {% if friend.user.name_colour %}{{ friend.user.name_colour }}{% else %}{{ friend.rank.colour }}{% endif %};">{{ friend.user.username }}</div> <div class="friends-list-name" style="color: {% if friend.user.name_colour %}{{ friend.user.name_colour }}{% else %}{{ friend.rank.colour }}{% endif %};">{{ friend.user.username }}</div>
</a> </a>
<div class="friends-list-actions"> <div class="friends-list-actions">
<a class="remove fill fa fa-remove" title="Remove friend" href="/friends?remove={{ friend.user.id }}&amp;session={{ php.sessionid }}&amp;time={{ php.time }}&amp;redirect=/settings/listing/friends&amp;direct=true"></a> <a class="remove fill fa fa-remove" title="Remove friend" href="/friends?remove={{ friend.user.id }}&amp;session={{ php.sessionid }}&amp;time={{ php.time }}&amp;redirect=/settings/listing/friends&amp;direct=true" id="friendslist-friend-action-remove-{{ friend.user.id }}"></a>
<div class="clear"></div> <div class="clear"></div>
</div> </div>
</div> </div>

View file

@ -1,3 +1,15 @@
{% block js %}
<script type="text/javascript">
window.addEventListener("load", function() {
var friendsListActions = document.querySelectorAll('[id^="friendslist-friend-action-"]');
for (var i in friendsListActions) {
prepareAjaxLink(friendsListActions[i], 'submitPost', ', true, "Please wait.."');
}
});
</script>
{% endblock %}
{% if friends|length %} {% if friends|length %}
<div class="friends-list"> <div class="friends-list">
{% for friend in friends[page.currentPage] %} {% for friend in friends[page.currentPage] %}
@ -7,8 +19,8 @@
<div class="friends-list-name" style="color: {% if friend.user.name_colour %}{{ friend.user.name_colour }}{% else %}{{ friend.rank.colour }}{% endif %};">{{ friend.user.username }}</div> <div class="friends-list-name" style="color: {% if friend.user.name_colour %}{{ friend.user.name_colour }}{% else %}{{ friend.rank.colour }}{% endif %};">{{ friend.user.username }}</div>
</a> </a>
<div class="friends-list-actions"> <div class="friends-list-actions">
<a class="add fa fa-check" title="Add friend" href="/friends?add={{ friend.user.id }}&amp;session={{ php.sessionid }}&amp;time={{ php.time }}&amp;redirect=/settings/friendrequests&amp;direct=true"></a> <a class="add fa fa-check" title="Add friend" href="/friends?add={{ friend.user.id }}&amp;session={{ php.sessionid }}&amp;time={{ php.time }}&amp;redirect=/settings/friendrequests&amp;direct=true" id="friendslist-friend-action-add-{{ friend.user.id }}"></a>
<a class="remove fa fa-remove" title="Remove friend" href="/friends?remove={{ friend.user.id }}&amp;session={{ php.sessionid }}&amp;time={{ php.time }}&amp;redirect=/settings/friends/requests&amp;direct=true"></a> <a class="remove fa fa-remove" title="Remove friend" href="/friends?remove={{ friend.user.id }}&amp;session={{ php.sessionid }}&amp;time={{ php.time }}&amp;redirect=/settings/friends/requests&amp;direct=true" id="friendslist-friend-action-remove-{{ friend.user.id }}"></a>
<div class="clear"></div> <div class="clear"></div>
</div> </div>
</div> </div>

View file

@ -71,4 +71,4 @@ switch (isset($elems[0]) ? $elems[0] : false) {
$return = ['error' => ['NO_API_VERSION']]; $return = ['error' => ['NO_API_VERSION']];
} }
echo json_encode([$return], (isset($_GET['pretty']) ? JSON_PRETTY_PRINT : 0)); echo json_encode($return, (isset($_GET['pretty']) ? JSON_PRETTY_PRINT : 0));

12
cache/.htaccess vendored
View file

@ -1,12 +0,0 @@
# Disallow external connections
# Apache <= 2.2
<IfModule !mod_authz_core.c>
Order deny,allow
deny from all
</IfModule>
# Apache 2.4 =>
<IfModule mod_authz_core.c>
Require all denied
</IfModule>

1
cache/.sakura vendored Normal file
View file

@ -0,0 +1 @@
# To make sure Git keeps this folder here

View file

@ -1,39 +0,0 @@
AddType application/vnd.ms-fontobject .eot
AddType font/ttf .ttf
AddType font/otf .otf
AddType font/woff .woff
<FilesMatch "\.(ttf|otf|eot|woff)$">
<IfModule mod_headers.c>
Header set Access-Control-Allow-Origin "*"
</IfModule>
</FilesMatch>
<FilesMatch "global.css">
Header set Cache-Control "max-age=0, must-revalidate"
</FilesMatch>
Options -Indexes
RewriteEngine On
#
#RewriteCond %{HTTP_REFERER} !^$
#RewriteCond %{HTTP_REFERER} !^http://(.+\.)?flashii\.net [NC]
#RewriteCond %{HTTP_REFERER} !^http://(.+\.)?flashii\.org [NC]
#RewriteRule .*\.(jpe?g|gif|bmp|png|swf)$ http://i.imgur.com/Bv0MKtu.gif [L]
#
#RewriteCond %{HTTP_REFERER} !^$
#RewriteCond %{HTTP_REFERER} !^http://(.+\.)?flashii\.net [NC]
#RewriteCond %{HTTP_REFERER} !^http://(.+\.)?flashii\.org [NC]
#RewriteRule .*\.(wav|mp3)$ http://chat.flashii.net/sandstorm.mp3 [L]
#
#RewriteCond %{HTTP_REFERER} !^$
#RewriteCond %{HTTP_REFERER} !^http://(.+\.)?flashii\.net [NC]
#RewriteCond %{HTTP_REFERER} !^http://(.+\.)?flashii\.org [NC]
#RewriteRule .*\.(ogg)$ http://chat.flashii.net/sandstorm.ogg [L]
#
ErrorDocument 403 "403"
ErrorDocument 404 "404"
ErrorDocument 500 "500"

View file

@ -4,7 +4,7 @@
@charset "utf-8"; @charset "utf-8";
.markdown { .markdown {
font: 12px/1.4 "Helvetica Neue", Helvetica, "Segoe UI", Arial, freesans, sans-serif; line-height: 1.4;
word-wrap: break-word; word-wrap: break-word;
} }

View file

@ -307,7 +307,8 @@ a.default:active {
} }
.ajax-busy { .ajax-busy {
background: rgba(0, 0, 0, .4); background: #222;
background: linear-gradient(0deg, rgba(0, 0, 0, .4), transparent) rgba(0, 0, 0, .8);
position: fixed; position: fixed;
top: 0; top: 0;
left: 0; left: 0;
@ -316,33 +317,21 @@ a.default:active {
z-index: 5; z-index: 5;
text-align: center; text-align: center;
opacity: 1; opacity: 1;
display: flex;
align-items: center;
justify-content: center;
} }
.ajax-busy .ajax-inner { .ajax-busy .ajax-inner {
line-height: 2em; line-height: 2em;
color: #FFF; color: #FFF;
background: #222;
background: linear-gradient(0deg, rgba(0, 0, 0, .4) 20%, transparent) rgba(0, 0, 0, .8);
display: inline-block; display: inline-block;
margin: 10% auto 0;
padding: 10px 20px 15px; padding: 10px 20px 15px;
border-radius: 10px; border-radius: 10px;
box-shadow: 0 5px 1em #111;
} }
.ajax-busy .ajax-inner h2 { .ajax-busy .ajax-inner h2 {
padding-bottom: 5px; line-height: 2em;
}
@media (max-width: 1024px) {
.ajax-busy {
background: rgba(0, 0, 0, .8);
}
.ajax-busy .ajax-inner {
background: transparent;
box-shadow: 0 0 0 transparent;
}
} }
.homepage .content-right ul { .homepage .content-right ul {

View file

@ -845,6 +845,14 @@ function scrollToTop() {
} }
function replaceTag(tag) {
return {'&': '&amp;', '<': '&lt;', '>': '&gt;'}[tag] || tag;
}
function safeTagsReplace(str) {
return str.replace(/[&<>]/g, replaceTag);
}
// Formatting money // Formatting money
Number.prototype.formatMoney = function(c, d, t) { Number.prototype.formatMoney = function(c, d, t) {
var n = this, var n = this,

File diff suppressed because it is too large Load diff

View file

@ -329,7 +329,6 @@ if (isset($_REQUEST['request-notifications']) && $_REQUEST['request-notification
'success' => 0, 'success' => 0,
]; ];
break; break;
} }
@ -365,7 +364,6 @@ if (isset($_REQUEST['request-notifications']) && $_REQUEST['request-notification
'success' => 0, 'success' => 0,
]; ];
break; break;
} }
@ -487,7 +485,6 @@ if (isset($_REQUEST['request-notifications']) && $_REQUEST['request-notification
'success' => 1, 'success' => 1,
]; ];
break; break;
// Profile // Profile
@ -591,7 +588,6 @@ if (isset($_REQUEST['request-notifications']) && $_REQUEST['request-notification
]); ]);
} }
break; break;
// Site Options // Site Options
@ -625,7 +621,6 @@ if (isset($_REQUEST['request-notifications']) && $_REQUEST['request-notification
'success' => 1, 'success' => 1,
]; ];
break; break;
// Usertitle // Usertitle
@ -639,7 +634,6 @@ if (isset($_REQUEST['request-notifications']) && $_REQUEST['request-notification
'success' => 0, 'success' => 0,
]; ];
break; break;
} }
@ -652,7 +646,6 @@ if (isset($_REQUEST['request-notifications']) && $_REQUEST['request-notification
'success' => 0, 'success' => 0,
]; ];
break; break;
} }
@ -677,7 +670,6 @@ if (isset($_REQUEST['request-notifications']) && $_REQUEST['request-notification
'success' => 1, 'success' => 1,
]; ];
break; break;
// Username changing // Username changing
@ -715,28 +707,122 @@ if (isset($_REQUEST['request-notifications']) && $_REQUEST['request-notification
'success' => $userNameChange[0], 'success' => $userNameChange[0],
]; ];
break;
// E-mail changing
case 'email':
// Check permissions
if (!$currentUser->checkPermission('SITE', 'CHANGE_EMAIL')) {
$renderData['page'] = [
'redirect' => $redirect,
'message' => 'You aren\'t allowed to change your e-mail address.',
'success' => 0,
];
break;
}
// Attempt e-mail change
$emailChange = $currentUser->setEMailAddress(isset($_POST['email']) ? $_POST['email'] : '');
// Messages
$messages = [
'INVALID' => 'Your e-mail isn\'t considered valid!',
'IN_USE' => 'This e-mail address has already been used!',
'SUCCESS' => 'Successfully changed your e-mail address!',
];
// Set render data
$renderData['page'] = [
'redirect' => $redirect,
'message' => $messages[$emailChange[1]],
'success' => $emailChange[0],
];
break;
// Password changing
case 'password':
// Check permissions
if (!$currentUser->checkPermission('SITE', 'CHANGE_PASSWORD')) {
$renderData['page'] = [
'redirect' => $redirect,
'message' => 'You aren\'t allowed to change your password.',
'success' => 0,
];
break;
}
// Attempt password change
$passChange = $currentUser->setPassword(isset($_POST['oldpassword']) ? $_POST['oldpassword'] : '', isset($_POST['newpassword']) ? $_POST['newpassword'] : '', isset($_POST['newpasswordconfirm']) ? $_POST['newpasswordconfirm'] : '');
// Messages
$messages = [
'NO_LOGIN' => 'How are you even logged in right now?',
'INCORRECT_PASSWORD' => 'The password you provided is incorrect!',
'PASS_TOO_SHIT' => 'Your password isn\'t strong enough!',
'PASS_NOT_MATCH' => 'Your new passwords don\'t match!',
'SUCCESS' => 'Successfully changed your password!',
];
// Set render data
$renderData['page'] = [
'redirect' => $redirect,
'message' => $messages[$passChange[1]],
'success' => $passChange[0],
];
break;
// Deactivation
case 'deactivate':
// Check permissions
if (!$currentUser->checkPermission('SITE', 'DEACTIVATE_ACCOUNT')) {
$renderData['page'] = [
'redirect' => $redirect,
'message' => 'You aren\'t allowed to deactivate your own account.',
'success' => 0,
];
break;
}
// Set render data
$renderData['page'] = [
'redirect' => $redirect,
'message' => 'Nothing happened.',
'success' => 1,
];
break; break;
// Userpage // Userpage
/*case 'userpage': case 'userpage':
// Base64 encode the userpage // Base64 encode the userpage
$userPage = base64_encode($_POST['userpage']); $userPage = base64_encode($_POST['userpage']);
// Update database // Update database
Users::updateUserDataField(Session::$userId, ['userPage' => [$userPage, 0]]); Users::updateUserDataField(Session::$userId, ['userPage' => $userPage]);
// Set render data // Set render data
$renderData['page'] = [ $renderData['page'] = [
'redirect' => $redirect, 'redirect' => $redirect,
'message' => 'Your userpage has been updated!', 'message' => 'Your userpage has been updated!',
'success' => 1 'success' => 1,
]; ];
break;
break;*/
// Fallback // Fallback
default: default:
@ -1245,6 +1331,7 @@ if (Users::checkLogin()) {
// Profile // Profile
case 'appearance.userpage': case 'appearance.userpage':
$renderData['userPage'] = isset($currentUser->data['userData']['userPage']) ? base64_decode($currentUser->data['userData']['userPage']) : '';
break; break;
// Username changing // Username changing

View file

@ -1,12 +0,0 @@
# Disallow external connections
# Apache <= 2.2
<IfModule !mod_authz_core.c>
Order deny,allow
deny from all
</IfModule>
# Apache 2.4 =>
<IfModule mod_authz_core.c>
Require all denied
</IfModule>

1
uploads/.sakura Normal file
View file

@ -0,0 +1 @@
# To make sure Git keeps this folder here