mirror of
https://github.com/rr-/szurubooru.git
synced 2025-07-17 08:26:24 +00:00
Compare commits
50 Commits
Author | SHA1 | Date | |
---|---|---|---|
cf749aa5fd | |||
0712f15ee4 | |||
db180376d4 | |||
0eb1ef4fff | |||
5c76a41ae7 | |||
0ea25dad24 | |||
c648cd848d | |||
c662d52d62 | |||
e733da58d2 | |||
febf22a667 | |||
7d6bab9590 | |||
2279e5605b | |||
4ecb3f3b81 | |||
89826a0be9 | |||
d3eaf27bdc | |||
47759adb66 | |||
b5070e06fe | |||
e1acb8bd99 | |||
872780397d | |||
d135f84bf2 | |||
31f07672c4 | |||
328d3f833b | |||
87eaa9ba9e | |||
18097b6192 | |||
739e5d3b5d | |||
7cc2a98992 | |||
7f9aaad324 | |||
319a9852fc | |||
d45ab47d3b | |||
eaa8c4897d | |||
823888b0c1 | |||
90a75e4d30 | |||
ce302c438d | |||
70f931b921 | |||
7743753641 | |||
e910d2f517 | |||
83355f3789 | |||
9f5bdc3da0 | |||
0f72ef3963 | |||
6b55706fb4 | |||
ff3e4bc287 | |||
f2947a2550 | |||
aab67f4b6c | |||
aed60da6f9 | |||
58a6345ae8 | |||
bc24b7d2cf | |||
3052a6f032 | |||
4bfa2a019a | |||
688385d553 | |||
a3be044ced |
13
config.ini
13
config.ini
@ -10,14 +10,15 @@ mediaPath=./public_html/media/
|
||||
title=szurubooru
|
||||
featuredPostMaxDays=7
|
||||
debugQueries=0
|
||||
salt = "1A2/$_4xVa"
|
||||
|
||||
[browsing]
|
||||
usersPerPage=8
|
||||
postsPerPage=20
|
||||
thumbWidth=140
|
||||
thumbHeight=140
|
||||
thumbWidth=150
|
||||
thumbHeight=150
|
||||
thumbStyle=outside
|
||||
endlessScrolling=1
|
||||
endlessScrollingDefault=1
|
||||
maxSearchTokens=4
|
||||
|
||||
[comments]
|
||||
@ -32,7 +33,6 @@ passRegex = "/^.+$/"
|
||||
userNameMinLength = 3
|
||||
userNameMaxLength = 20
|
||||
userNameRegex = "/^[\w_-]+$/ui"
|
||||
salt = "1A2/$_4xVa"
|
||||
|
||||
needEmailForRegistering = 1
|
||||
needEmailForCommenting = 0
|
||||
@ -73,13 +73,16 @@ featurePost=moderator
|
||||
|
||||
listUsers=registered
|
||||
viewUser=registered
|
||||
viewUserEmail=admin
|
||||
viewUserEmail.all=admin
|
||||
viewUserEmail.own=registered
|
||||
changeUserPassword.own=registered
|
||||
changeUserPassword.all=admin
|
||||
changeUserEmail.own=registered
|
||||
changeUserEmail.all=admin
|
||||
changeUserAccessRank=admin
|
||||
changeUserName=moderator
|
||||
changeUserSettings.all=nobody
|
||||
changeUserSettings.own=registered
|
||||
acceptUserRegistration=moderator
|
||||
banUser.own=nobody
|
||||
banUser.all=admin
|
||||
|
3
init.php
3
init.php
@ -49,6 +49,9 @@ foreach ($lines as $line)
|
||||
download('http://raw.github.com/aehlke/tag-it/master/css/jquery.tagit.css', $libPath . 'tagit' . DS . 'jquery.tagit.css');
|
||||
download('http://raw.github.com/aehlke/tag-it/master/js/tag-it.min.js', $libPath . 'tagit' . DS . 'jquery.tagit.js');
|
||||
|
||||
//Mousetrap
|
||||
download('https://raw.github.com/ccampbell/mousetrap/master/mousetrap.min.js', $libPath . 'mousetrap' . DS . 'mousetrap.min.js');
|
||||
|
||||
//fonts
|
||||
download('http://googlefontdirectory.googlecode.com/hg/apache/droidsans/DroidSans.ttf', $fontsPath . 'DroidSans.ttf');
|
||||
download('http://googlefontdirectory.googlecode.com/hg/apache/droidsans/DroidSans-Bold.ttf', $fontsPath . 'DroidSans-Bold.ttf');
|
||||
|
Submodule lib/chibi-core updated: 5a936768ee...6f606d1075
@ -98,8 +98,8 @@ body {
|
||||
display: inline-block;
|
||||
float: left;
|
||||
width: 25px;
|
||||
line-height: 38px;
|
||||
margin-right: -1px;
|
||||
line-height: 28px;
|
||||
margin: 5px -1px 5px 0;
|
||||
box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
#top-nav li.safety a:after {
|
||||
@ -265,7 +265,11 @@ form.aligned input[type=file] {
|
||||
}
|
||||
form.aligned input[type=radio],
|
||||
form.aligned input[type=checkbox] {
|
||||
vertical-align: text-top;
|
||||
width: auto;
|
||||
max-width: auto;
|
||||
margin: 0 10px 0 0;
|
||||
padding: 0;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.input-wrapper {
|
||||
@ -276,8 +280,11 @@ form.aligned input[type=checkbox] {
|
||||
.input-wrapper input,
|
||||
.input-wrapper textarea,
|
||||
.input-wrapper select {
|
||||
width: 80%;
|
||||
max-width: 80%;
|
||||
width: 100%;
|
||||
max-width: 100%;
|
||||
-webkit-box-sizing: border-box;
|
||||
-moz-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
label {
|
||||
@ -368,3 +375,7 @@ pre.debug {
|
||||
.spoiler:hover {
|
||||
color: black;
|
||||
}
|
||||
|
||||
img {
|
||||
border: 0;
|
||||
}
|
||||
|
9
public_html/media/css/index-help.css
Normal file
9
public_html/media/css/index-help.css
Normal file
@ -0,0 +1,9 @@
|
||||
code {
|
||||
margin: 0 0.5em;
|
||||
}
|
||||
span.comma {
|
||||
margin-left: -0.5em;
|
||||
}
|
||||
h1 {
|
||||
margin-top: 2em;
|
||||
}
|
@ -1,70 +1,69 @@
|
||||
#sidebar {
|
||||
min-width: 100px;
|
||||
padding: 5em 0;
|
||||
width: 25%;
|
||||
margin-right: 5%;
|
||||
#welcome {
|
||||
text-align: center;
|
||||
}
|
||||
#sidebar p {
|
||||
#welcome p {
|
||||
font-size: small;
|
||||
margin-top: 0;
|
||||
}
|
||||
#sidebar p span:not(:last-child):after {
|
||||
#welcome p span:not(:last-child):after {
|
||||
content: '\022C5';
|
||||
margin: 0 0.5em;
|
||||
}
|
||||
|
||||
#sidebar h1 {
|
||||
#content h1 {
|
||||
font-size: 26pt;
|
||||
}
|
||||
#sidebar input {
|
||||
width: 100%;
|
||||
max-width: 300px;
|
||||
border: 2px solid #ccc;
|
||||
padding: 5px;
|
||||
margin-top: 1em;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
#inner-content {
|
||||
float: right;
|
||||
#content {
|
||||
margin: 0 auto;
|
||||
width: 70%;
|
||||
min-width: 500px;
|
||||
position: relative;
|
||||
}
|
||||
.small-screen #content {
|
||||
width: 100%;
|
||||
min-width: 0;
|
||||
max-width: 500px;
|
||||
}
|
||||
|
||||
#inner-content .header .tags:before {
|
||||
#content .header .tags:before {
|
||||
margin: 0 0.5em;
|
||||
content: '\2013';
|
||||
}
|
||||
#inner-content .header ul {
|
||||
#content .header ul {
|
||||
list-style-type: none;
|
||||
display: inline;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
#inner-content .header li {
|
||||
#content .header li {
|
||||
display: inline;
|
||||
}
|
||||
#inner-content .header li:not(:last-child) a:after {
|
||||
#content .header li:not(:last-child) a:after {
|
||||
content: ', ';
|
||||
}
|
||||
|
||||
#inner-content .body {
|
||||
#content .body {
|
||||
background: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAYAAAAGCAYAAADgzO9IAAAAJElEQVQImWNgYGBgePfu3X8YZoABFA6SIqwS+HXgtANZF7IEAJnGPJE70lLLAAAAAElFTkSuQmCC');
|
||||
margin: 1em 0;
|
||||
text-align: center;
|
||||
}
|
||||
#inner-content .body img {
|
||||
#content .body img {
|
||||
max-width: 100%;
|
||||
margin: 0 auto;
|
||||
display: block;
|
||||
}
|
||||
#inner-content .body a {
|
||||
#content .body a {
|
||||
display: block;
|
||||
}
|
||||
|
||||
#inner-content .header .favs-comments {
|
||||
#content .header .favs-comments {
|
||||
margin-left: 0.5em;
|
||||
float: right;
|
||||
}
|
||||
|
||||
#inner-content .footer {
|
||||
#content .footer {
|
||||
text-align: right;
|
||||
}
|
||||
|
@ -1,4 +1,9 @@
|
||||
.post {
|
||||
margin: 0.5em;
|
||||
float: left;
|
||||
}
|
||||
.posts-wrapper {
|
||||
text-align: center;
|
||||
}
|
||||
.posts {
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
@ -5,10 +5,29 @@
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
}
|
||||
.post-type-flash {
|
||||
border-color: #dd5;
|
||||
box-shadow: 0.25em 0.25em #eeb, 0.1em 0.1em 0.5em 0.1em rgba(238,238,187,0.5);
|
||||
.post-type-youtube:after,
|
||||
.post-type-flash:after {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0;
|
||||
width: 150px;
|
||||
height: 150px;
|
||||
content: ' ';
|
||||
pointer-events: none;
|
||||
}
|
||||
.post-type-flash {
|
||||
border-color: red;
|
||||
}
|
||||
.post-type-youtube {
|
||||
border-color: red;
|
||||
}
|
||||
.post-type-flash:after {
|
||||
background: url('../img/thumb-overlay-swf.png');
|
||||
}
|
||||
.post-type-youtube:after {
|
||||
background: url('../img/thumb-overlay-yt.png');
|
||||
}
|
||||
|
||||
|
||||
.post:focus,
|
||||
.post:hover {
|
||||
@ -20,10 +39,15 @@
|
||||
opacity: .9;
|
||||
}
|
||||
|
||||
.post a {
|
||||
display: inline-block;
|
||||
vertical-align: top;
|
||||
}
|
||||
.post img.thumb {
|
||||
width: 140px;
|
||||
height: 140px;
|
||||
display: block;
|
||||
display: inline-block;
|
||||
width: 150px;
|
||||
height: 150px;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
.post .info-bar {
|
||||
|
@ -10,7 +10,7 @@ embed {
|
||||
}
|
||||
|
||||
.post-type-image img {
|
||||
background: url('../img/bk-image.png') lemonchiffon;
|
||||
/*background: url('../img/bk-image.png') lemonchiffon;*/
|
||||
}
|
||||
.post-type-flash embed {
|
||||
background: url('../img/bk-swf.png') lemonchiffon;
|
||||
@ -21,6 +21,10 @@ embed {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
#sidebar .tags li {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
#sidebar .tags li .count {
|
||||
padding-left: 0.5em;
|
||||
color: silver;
|
||||
@ -42,6 +46,11 @@ embed {
|
||||
background-color: silver;
|
||||
}
|
||||
|
||||
#sidebar .uploader img {
|
||||
vertical-align: middle;
|
||||
margin: 0 0.5em 0 0;
|
||||
}
|
||||
|
||||
i.icon-prev {
|
||||
background-position: -12px -1px;
|
||||
}
|
||||
|
26
public_html/media/css/tabs.css
Normal file
26
public_html/media/css/tabs.css
Normal file
@ -0,0 +1,26 @@
|
||||
.tabs ul {
|
||||
list-style-type: none;
|
||||
margin: 0 0 1em 0;
|
||||
padding: 0;
|
||||
border-bottom: 1px solid #ccc;
|
||||
}
|
||||
.tabs li {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.tabs li a {
|
||||
display: inline-block;
|
||||
padding: 0.5em 1em;
|
||||
margin-bottom: -1px;
|
||||
}
|
||||
|
||||
.tabs li a {
|
||||
border: 1px solid white;
|
||||
border-bottom: 1px solid #ccc;
|
||||
color: silver;
|
||||
}
|
||||
.tabs li.selected a {
|
||||
border: 1px solid #ccc;
|
||||
border-bottom: 1px solid white;
|
||||
color: inherit;
|
||||
}
|
@ -6,11 +6,17 @@
|
||||
-moz-column-width: 14em;
|
||||
-webkit-column-width: 14em;
|
||||
}
|
||||
.tags li a:hover {
|
||||
opacity: 1 !important;
|
||||
}
|
||||
.tags li {
|
||||
margin: 0.2em 0.5em;
|
||||
text-align: top;
|
||||
width: 14em;
|
||||
display: inline-block;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.form-wrapper {
|
||||
|
@ -8,6 +8,13 @@
|
||||
float: left;
|
||||
}
|
||||
|
||||
.tab {
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
.tab.url {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#file-handler-wrapper {
|
||||
display: table;
|
||||
width: 100%;
|
||||
@ -17,7 +24,7 @@
|
||||
font-size: 150%;
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
height: 300px;
|
||||
height: 8em;
|
||||
display: table-cell;
|
||||
border: 3px dashed #ddd;
|
||||
}
|
||||
@ -26,28 +33,34 @@
|
||||
border-color: firebrick;
|
||||
}
|
||||
|
||||
#url-handler textarea {
|
||||
width: 100%;
|
||||
height: 10em;
|
||||
margin-bottom: 0.5em;
|
||||
}
|
||||
|
||||
.post .thumbnail {
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
line-height: 100px;
|
||||
background-image: url('../img/thumb-upload.png');
|
||||
background-image: url('../img/thumb.png');
|
||||
background-size: 100px 100px;
|
||||
border: 1px solid black;
|
||||
vertical-align: middle;
|
||||
text-align: center;
|
||||
display: block;
|
||||
float: left;
|
||||
margin-right: 1em;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.post .alert,
|
||||
#upload-step2,
|
||||
#upload-no-posts,
|
||||
#post-template {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.post {
|
||||
margin-bottom: 4em;
|
||||
margin: 2em 0;
|
||||
}
|
||||
|
||||
.post .ops {
|
||||
@ -101,7 +114,8 @@
|
||||
}
|
||||
.post label.left {
|
||||
display: inline-block;
|
||||
width: 4em;
|
||||
width: 60px;
|
||||
padding-right: 10px;
|
||||
float: left;
|
||||
}
|
||||
.post .safety label:not(.left) {
|
||||
@ -134,11 +148,8 @@ ul.tagit {
|
||||
font-size: 1em;
|
||||
}
|
||||
|
||||
.submit-wrapper {
|
||||
text-align: center;
|
||||
}
|
||||
#theSubmit {
|
||||
margin: 0 auto;
|
||||
#the-submit {
|
||||
margin: 0 0 0 205px;
|
||||
}
|
||||
|
||||
.post .form-wrapper {
|
||||
|
@ -3,33 +3,6 @@
|
||||
font-size: 90%;
|
||||
}
|
||||
|
||||
.tabs ul {
|
||||
list-style-type: none;
|
||||
margin: 0 0 1em 0;
|
||||
padding: 0;
|
||||
border-bottom: 1px solid #ccc;
|
||||
}
|
||||
.tabs li {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.tabs li a {
|
||||
display: inline-block;
|
||||
padding: 0.5em 1em;
|
||||
margin-bottom: -1px;
|
||||
}
|
||||
|
||||
.tabs li a {
|
||||
border: 1px solid white;
|
||||
border-bottom: 1px solid #ccc;
|
||||
color: silver;
|
||||
}
|
||||
.tabs li.selected a {
|
||||
border: 1px solid #ccc;
|
||||
border-bottom: 1px solid white;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
.avatar-wrapper {
|
||||
text-align: center;
|
||||
}
|
||||
@ -40,14 +13,20 @@
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
form.settings label.left,
|
||||
form.delete label.left,
|
||||
form.edit label.left {
|
||||
width: 9em;
|
||||
}
|
||||
|
||||
form.settings .alert,
|
||||
form.delete .alert,
|
||||
form.edit .alert {
|
||||
margin: 1em 0;
|
||||
}
|
||||
|
||||
form.settings input,
|
||||
form.delete input,
|
||||
form.edit select,
|
||||
form.edit input {
|
||||
width: 16em;
|
||||
|
BIN
public_html/media/img/thumb-overlay-swf.png
Normal file
BIN
public_html/media/img/thumb-overlay-swf.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.9 KiB |
BIN
public_html/media/img/thumb-overlay-yt.png
Normal file
BIN
public_html/media/img/thumb-overlay-yt.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.6 KiB |
Binary file not shown.
Before Width: | Height: | Size: 1.8 KiB |
Binary file not shown.
Before Width: | Height: | Size: 688 B |
@ -1,4 +1,5 @@
|
||||
$.fn.hasAttr = function(name) {
|
||||
$.fn.hasAttr = function(name)
|
||||
{
|
||||
return this.attr(name) !== undefined;
|
||||
};
|
||||
|
||||
@ -69,7 +70,7 @@ $(function()
|
||||
aDom.addClass('inactive');
|
||||
|
||||
var url = $(this).attr('href') + '?json';
|
||||
$.get(url, function(data)
|
||||
$.get(url, {submit: 1}, function(data)
|
||||
{
|
||||
if (data['success'])
|
||||
{
|
||||
@ -101,13 +102,14 @@ $(function()
|
||||
form.append(input);
|
||||
});
|
||||
});
|
||||
|
||||
$(window).resize();
|
||||
});
|
||||
|
||||
|
||||
//modify DOM on small viewports
|
||||
$(window).resize(function()
|
||||
{
|
||||
//modify DOM on small viewports
|
||||
if ($('body').width() == $('body').data('last-width'))
|
||||
return;
|
||||
$('#inner-content .unit').addClass('bottom-unit');
|
||||
if ($('body').width() < 600)
|
||||
{
|
||||
@ -118,7 +120,96 @@ $(window).resize(function()
|
||||
else
|
||||
{
|
||||
$('body').removeClass('small-screen');
|
||||
$('#inner-content').insertAfter($('#sidebar'));
|
||||
$('#sidebar').insertBefore($('#inner-content'));
|
||||
$('#sidebar .unit').removeClass('bottom-unit').addClass('left-unit');
|
||||
}
|
||||
$('body').data('last-width', $('body').width());
|
||||
});
|
||||
$(function()
|
||||
{
|
||||
$(window).resize();
|
||||
});
|
||||
|
||||
|
||||
//autocomplete
|
||||
function split(val)
|
||||
{
|
||||
return val.split(/\s+/);
|
||||
}
|
||||
|
||||
function extractLast(term)
|
||||
{
|
||||
return split(term).pop();
|
||||
}
|
||||
|
||||
$(function()
|
||||
{
|
||||
var searchInput = $('#top-nav .search input');
|
||||
searchInput
|
||||
// don't navigate away from the field on tab when selecting an item
|
||||
.bind("keydown", function(event)
|
||||
{
|
||||
if (event.keyCode === $.ui.keyCode.TAB && $(this).data("autocomplete").menu.active)
|
||||
{
|
||||
event.preventDefault();
|
||||
}
|
||||
}).autocomplete({
|
||||
minLength: 1,
|
||||
source: function(request, response)
|
||||
{
|
||||
var term = extractLast(request.term);
|
||||
$.get(searchInput.attr('data-autocomplete-url') + '?json', {filter: term}, function(data)
|
||||
{
|
||||
response($.map(data.tags, function(tag) { return { label: tag, value: tag }; }));
|
||||
});
|
||||
},
|
||||
focus: function()
|
||||
{
|
||||
// prevent value inserted on focus
|
||||
return false;
|
||||
},
|
||||
select: function(event, ui)
|
||||
{
|
||||
var terms = split(this.value);
|
||||
terms.pop();
|
||||
terms.push(ui.item.value);
|
||||
terms.push('');
|
||||
this.value = terms.join(' ');
|
||||
return false;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
function getTagItOptions()
|
||||
{
|
||||
return {
|
||||
caseSensitive: false,
|
||||
autocomplete:
|
||||
{
|
||||
source:
|
||||
function(request, response)
|
||||
{
|
||||
var term = request.term.toLowerCase();
|
||||
var results = $.grep(this.options.availableTags, function(a)
|
||||
{
|
||||
if (term.length < 3)
|
||||
return a.toLowerCase().indexOf(term) == 0;
|
||||
else
|
||||
return a.toLowerCase().indexOf(term) != -1;
|
||||
});
|
||||
if (!this.options.allowDuplicates)
|
||||
results = this._subtractArray(results, this.assignedTags());
|
||||
response(results);
|
||||
},
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
$(function()
|
||||
{
|
||||
Mousetrap.bind('q', function() { $('#top-nav input').focus(); return false; });
|
||||
Mousetrap.bind('w', function() { $('body,html').animate({scrollTop: '-=150px'}, 200); });
|
||||
Mousetrap.bind('s', function() { $('body,html').animate({scrollTop: '+=150px'}, 200); });
|
||||
Mousetrap.bind('a', function() { var url = $('.paginator .prev:not(.disabled) a').attr('href'); if (typeof url !== 'undefined') window.location.href = url; });
|
||||
Mousetrap.bind('d', function() { var url = $('.paginator .next:not(.disabled) a').attr('href'); if (typeof url !== 'undefined') window.location.href = url; });
|
||||
});
|
||||
|
@ -14,17 +14,16 @@ $(function()
|
||||
{
|
||||
tags = data['tags'];
|
||||
|
||||
var tagItOptions =
|
||||
{
|
||||
caseSensitive: true,
|
||||
availableTags: tags,
|
||||
placeholderText: $('.tags input').attr('placeholder')
|
||||
};
|
||||
var tagItOptions = getTagItOptions();
|
||||
tagItOptions.availableTags = tags;
|
||||
tagItOptions.placeholderText = $('.tags input').attr('placeholder');
|
||||
$('.tags input').tagit(tagItOptions);
|
||||
|
||||
e.preventDefault();
|
||||
var formDom = $('form.edit-post');
|
||||
formDom.show().css('height', formDom.height()).hide().slideDown();
|
||||
|
||||
$('html, body').animate({ scrollTop: $(formDom).offset().top + 'px' }, 'fast');
|
||||
});
|
||||
});
|
||||
|
||||
@ -121,4 +120,8 @@ $(function()
|
||||
|
||||
$.ajax(ajaxData);
|
||||
});
|
||||
|
||||
Mousetrap.bind('a', function() { var url = $('#sidebar .left a').attr('href'); if (typeof url !== 'undefined') window.location.href = url; });
|
||||
Mousetrap.bind('d', function() { var url = $('#sidebar .right a').attr('href'); if (typeof url !== 'undefined') window.location.href = url; });
|
||||
Mousetrap.bind('e', function() { $('li.edit a').trigger('click'); return false; });
|
||||
});
|
||||
|
@ -1,35 +1,36 @@
|
||||
$(function()
|
||||
{
|
||||
$('.tabs nav a').click(function(e)
|
||||
{
|
||||
e.preventDefault();
|
||||
var className = $(this).parents('li').attr('class').replace('selected', '').replace(/^\s+|\s+$/, '');
|
||||
$('.tabs nav li').removeClass('selected');
|
||||
$(this).parents('li').addClass('selected');
|
||||
$('.tab').hide();
|
||||
$('.tab.' + className).show();
|
||||
});
|
||||
|
||||
var tags = [];
|
||||
$.getJSON('/tags?json', function(data)
|
||||
{
|
||||
tags = data['tags'];
|
||||
});
|
||||
|
||||
var handler = $('#file-handler');
|
||||
handler.on('dragenter', function(e)
|
||||
$('#file-handler').on('dragenter', function(e)
|
||||
{
|
||||
$(this).addClass('active');
|
||||
});
|
||||
|
||||
handler.on('dragleave', function(e)
|
||||
}).on('dragleave', function(e)
|
||||
{
|
||||
$(this).removeClass('active');
|
||||
});
|
||||
|
||||
handler.on('dragover', function(e)
|
||||
}).on('dragover', function(e)
|
||||
{
|
||||
e.preventDefault();
|
||||
});
|
||||
|
||||
handler.on('drop', function(e)
|
||||
}).on('drop', function(e)
|
||||
{
|
||||
e.preventDefault();
|
||||
handleFiles(e.originalEvent.dataTransfer.files);
|
||||
$(this).trigger('dragleave');
|
||||
});
|
||||
|
||||
handler.on('click', function(e)
|
||||
}).on('click', function(e)
|
||||
{
|
||||
$(':file').show().focus().trigger('click').hide();
|
||||
});
|
||||
@ -39,6 +40,24 @@ $(function()
|
||||
handleFiles(this.files);
|
||||
});
|
||||
|
||||
|
||||
|
||||
$('#url-handler-wrapper button').click(function(e)
|
||||
{
|
||||
var urls = [];
|
||||
$.each($('#url-handler-wrapper textarea').val().split(/\s+/), function(i, url)
|
||||
{
|
||||
url = url.replace(/^\s+|\s+$/, '');
|
||||
if (url == '')
|
||||
return;
|
||||
urls.push(url);
|
||||
});
|
||||
$('#url-handler-wrapper textarea').val('');
|
||||
handleURLs(urls);
|
||||
});
|
||||
|
||||
|
||||
|
||||
$('.post .move-down-trigger, .post .move-up-trigger').on('click', function()
|
||||
{
|
||||
var dir = $(this).hasClass('move-down-trigger') ? 'd' : 'u';
|
||||
@ -53,15 +72,12 @@ $(function()
|
||||
$(this).parents('.post').slideUp(function()
|
||||
{
|
||||
$(this).remove();
|
||||
handleInputs([]);
|
||||
});
|
||||
if ($('#upload-step2 .post').length == 1)
|
||||
{
|
||||
$('#upload-step2').slideUp();
|
||||
$('#upload-no-posts').slideDown();
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
|
||||
function sendNextPost()
|
||||
{
|
||||
var posts = $('#upload-step2 .post');
|
||||
@ -73,15 +89,18 @@ $(function()
|
||||
|
||||
var postDom = posts.first();
|
||||
var url = postDom.find('form').attr('action') + '?json';
|
||||
var file = postDom.data('file');
|
||||
var sourceFile = postDom.data('file');
|
||||
var sourceUrl = postDom.data('url');
|
||||
var tags = postDom.find('[name=tags]').val();
|
||||
var safety = postDom.find('[name=safety]:checked').val();
|
||||
var source = postDom.find('[name=source]').val();
|
||||
var fd = new FormData();
|
||||
fd.append('file', file);
|
||||
fd.append('file', sourceFile);
|
||||
fd.append('url', sourceUrl);
|
||||
fd.append('tags', tags);
|
||||
fd.append('safety', safety);
|
||||
fd.append('source', source);
|
||||
fd.append('submit', 1);
|
||||
|
||||
var ajaxData =
|
||||
{
|
||||
@ -145,51 +164,79 @@ $(function()
|
||||
|
||||
function handleFiles(files)
|
||||
{
|
||||
$('#upload-step1').fadeOut(function()
|
||||
handleInputs(files, function(postDom, file)
|
||||
{
|
||||
for (var i = 0; i < files.length; i ++)
|
||||
postDom.data('file', file);
|
||||
$('.file-name strong', postDom).text(file.name);
|
||||
|
||||
if (file.type.match('image.*'))
|
||||
{
|
||||
var file = files[i];
|
||||
var postDom = $('#post-template').clone(true);
|
||||
postDom.find('form').submit(false);
|
||||
postDom.removeAttr('id');
|
||||
postDom.data('file', file);
|
||||
$('.file-name strong', postDom).text(file.name);
|
||||
$('.posts').append(postDom);
|
||||
|
||||
postDom.show();
|
||||
var tagItOptions =
|
||||
{
|
||||
caseSensitive: true,
|
||||
availableTags: tags,
|
||||
placeholderText: $('.tags input').attr('placeholder')
|
||||
};
|
||||
$('.tags input', postDom).tagit(tagItOptions);
|
||||
|
||||
if (!file.type.match('image.*'))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var img = postDom.find('img')
|
||||
var reader = new FileReader();
|
||||
reader.onload = (function(theFile, img)
|
||||
{
|
||||
return function(e)
|
||||
{
|
||||
/*img.css('max-width', img.css('width'));
|
||||
img.css('max-height', img.css('height'));
|
||||
img.css('width', 'auto');
|
||||
img.css('height', 'auto');*/
|
||||
img.css('background-image', 'none');
|
||||
img.attr('src', e.target.result);
|
||||
};
|
||||
})(file, img);
|
||||
reader.readAsDataURL(file);
|
||||
}
|
||||
$('#upload-step2').fadeIn(function()
|
||||
{
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function handleURLs(urls)
|
||||
{
|
||||
handleInputs(urls, function(postDom, url)
|
||||
{
|
||||
postDom.data('url', url);
|
||||
postDom.find('[name=source]').val(url);
|
||||
if (matches = url.match(/watch.*?=([a-zA-Z0-9_-]+)/))
|
||||
{
|
||||
postDom.find('.file-name strong').text(url);
|
||||
$.getJSON('http://gdata.youtube.com/feeds/api/videos/' + matches[1] + '?v=2&alt=jsonc', function(data)
|
||||
{
|
||||
postDom.find('.file-name strong')
|
||||
.text(data.data.title);
|
||||
postDom.find('img')
|
||||
.css('background-image', 'none')
|
||||
.attr('src', data.data.thumbnail.hqDefault);
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
postDom.find('.file-name strong')
|
||||
.text(url);
|
||||
postDom.find('img')
|
||||
.css('background-image', 'none')
|
||||
.attr('src', url);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function handleInputs(inputs, callback)
|
||||
{
|
||||
for (var i = 0; i < inputs.length; i ++)
|
||||
{
|
||||
var input = inputs[i];
|
||||
var postDom = $('#post-template').clone(true);
|
||||
postDom.find('form').submit(false);
|
||||
postDom.removeAttr('id');
|
||||
|
||||
$('.posts').append(postDom);
|
||||
|
||||
postDom.show();
|
||||
var tagItOptions = getTagItOptions();
|
||||
tagItOptions.availableTags = tags;
|
||||
tagItOptions.placeholderText = $('.tags input').attr('placeholder');
|
||||
$('.tags input', postDom).tagit(tagItOptions);
|
||||
|
||||
callback(postDom, input);
|
||||
}
|
||||
if ($('.posts .post').length == 0)
|
||||
$('#upload-step2').fadeOut();
|
||||
else
|
||||
$('#upload-step2').fadeIn();
|
||||
}
|
||||
});
|
||||
|
47
scripts/process-old-users.php
Normal file
47
scripts/process-old-users.php
Normal file
@ -0,0 +1,47 @@
|
||||
<?php
|
||||
require_once __DIR__ . '/../src/core.php';
|
||||
|
||||
function usage()
|
||||
{
|
||||
echo 'Usage: ' . basename(__FILE__);
|
||||
echo ' -print|-purge';
|
||||
return true;
|
||||
}
|
||||
|
||||
array_shift($argv);
|
||||
if (empty($argv))
|
||||
usage() and die;
|
||||
|
||||
function printUser($user)
|
||||
{
|
||||
echo 'ID: ' . $user->id . PHP_EOL;
|
||||
echo 'Name: ' . $user->name . PHP_EOL;
|
||||
echo 'E-mail: ' . $user->email_unconfirmed . PHP_EOL;
|
||||
echo 'Date joined: ' . date('Y-m-d H:i:s', $user->join_date) . PHP_EOL;
|
||||
echo PHP_EOL;
|
||||
}
|
||||
|
||||
$action = array_shift($argv);
|
||||
switch ($action)
|
||||
{
|
||||
case '-print':
|
||||
$func = 'printUser';
|
||||
break;
|
||||
|
||||
case '-purge':
|
||||
$func = function($user)
|
||||
{
|
||||
printUser($user);
|
||||
R::trash($user);
|
||||
};
|
||||
break;
|
||||
|
||||
default:
|
||||
die('Unknown action' . PHP_EOL);
|
||||
}
|
||||
|
||||
$rows = R::find('user', 'email_confirmed IS NULL AND DATETIME(join_date) < DATETIME("now", "-21 days")');
|
||||
foreach ($rows as $user)
|
||||
{
|
||||
$func($user);
|
||||
}
|
@ -6,12 +6,27 @@ class Bootstrap
|
||||
$this->context->loggedIn = false;
|
||||
if (isset($_SESSION['user-id']))
|
||||
{
|
||||
$this->context->user = R::findOne('user', 'id = ?', [$_SESSION['user-id']]);
|
||||
if (!isset($_SESSION['user']))
|
||||
{
|
||||
$dbUser = R::findOne('user', 'id = ?', [$_SESSION['user-id']]);
|
||||
$_SESSION['user'] = serialize($dbUser);
|
||||
}
|
||||
$this->context->user = unserialize($_SESSION['user']);
|
||||
if (!empty($this->context->user))
|
||||
{
|
||||
$this->context->loggedIn = true;
|
||||
}
|
||||
}
|
||||
if (!$this->context->loggedIn)
|
||||
{
|
||||
try
|
||||
{
|
||||
AuthController::tryAutoLogin();
|
||||
}
|
||||
catch (Exception $e)
|
||||
{
|
||||
}
|
||||
}
|
||||
if (empty($this->context->user))
|
||||
{
|
||||
$dummy = R::dispense('user');
|
||||
@ -37,6 +52,7 @@ class Bootstrap
|
||||
[
|
||||
'../lib/jquery/jquery.min.js',
|
||||
'../lib/jquery-ui/jquery-ui.min.js',
|
||||
'../lib/mousetrap/mousetrap.min.js',
|
||||
'core.js',
|
||||
];
|
||||
|
||||
|
@ -1,6 +1,43 @@
|
||||
<?php
|
||||
class AuthController
|
||||
{
|
||||
public static function tryLogin($name, $password)
|
||||
{
|
||||
$config = \Chibi\Registry::getConfig();
|
||||
|
||||
$dbUser = R::findOne('user', 'name = ?', [$name]);
|
||||
if ($dbUser === null)
|
||||
throw new SimpleException('Invalid username');
|
||||
|
||||
$passwordHash = Model_User::hashPassword($password, $dbUser->pass_salt);
|
||||
if ($passwordHash != $dbUser->pass_hash)
|
||||
throw new SimpleException('Invalid password');
|
||||
|
||||
if (!$dbUser->staff_confirmed and $config->registration->staffActivation)
|
||||
throw new SimpleException('Staff hasn\'t confirmed your registration yet');
|
||||
|
||||
if ($dbUser->banned)
|
||||
throw new SimpleException('You are banned');
|
||||
|
||||
if ($config->registration->needEmailForRegistering)
|
||||
PrivilegesHelper::confirmEmail($dbUser);
|
||||
|
||||
$_SESSION['user-id'] = $dbUser->id;
|
||||
$_SESSION['user'] = serialize($dbUser);
|
||||
\Chibi\UrlHelper::forward(\Chibi\UrlHelper::route('index', 'index'));
|
||||
return $dbUser;
|
||||
}
|
||||
|
||||
public static function tryAutoLogin()
|
||||
{
|
||||
if (!isset($_COOKIE['auth']))
|
||||
return;
|
||||
|
||||
$token = TextHelper::decrypt($_COOKIE['auth']);
|
||||
list ($name, $password) = array_map('base64_decode', explode('|', $token));
|
||||
return self::tryLogin($name, $password);
|
||||
}
|
||||
|
||||
/**
|
||||
* @route /auth/login
|
||||
*/
|
||||
@ -17,29 +54,17 @@ class AuthController
|
||||
return;
|
||||
}
|
||||
|
||||
$suppliedName = InputHelper::get('name');
|
||||
$suppliedPassword = InputHelper::get('password');
|
||||
if ($suppliedName !== null and $suppliedPassword !== null)
|
||||
if (InputHelper::get('submit'))
|
||||
{
|
||||
$dbUser = R::findOne('user', 'name = ?', [$suppliedName]);
|
||||
if ($dbUser === null)
|
||||
throw new SimpleException('Invalid username');
|
||||
$suppliedName = InputHelper::get('name');
|
||||
$suppliedPassword = InputHelper::get('password');
|
||||
$dbUser = self::tryLogin($suppliedName, $suppliedPassword);
|
||||
|
||||
$suppliedPasswordHash = Model_User::hashPassword($suppliedPassword, $dbUser->pass_salt);
|
||||
if ($suppliedPasswordHash != $dbUser->pass_hash)
|
||||
throw new SimpleException('Invalid password');
|
||||
|
||||
if (!$dbUser->staff_confirmed and $this->config->registration->staffActivation)
|
||||
throw new SimpleException('Staff hasn\'t confirmed your registration yet');
|
||||
|
||||
if ($dbUser->banned)
|
||||
throw new SimpleException('You are banned');
|
||||
|
||||
if ($this->config->registration->needEmailForRegistering)
|
||||
PrivilegesHelper::confirmEmail($dbUser);
|
||||
|
||||
$_SESSION['user-id'] = $dbUser->id;
|
||||
\Chibi\UrlHelper::forward(\Chibi\UrlHelper::route('index', 'index'));
|
||||
if (InputHelper::get('remember'))
|
||||
{
|
||||
$token = implode('|', [base64_encode($suppliedName), base64_encode($suppliedPassword)]);
|
||||
setcookie('auth', TextHelper::encrypt($token), time() + 365 * 24 * 3600, '/');
|
||||
}
|
||||
$this->context->transport->success = true;
|
||||
}
|
||||
}
|
||||
@ -52,6 +77,7 @@ class AuthController
|
||||
$this->context->viewName = null;
|
||||
$this->context->viewName = null;
|
||||
unset($_SESSION['user-id']);
|
||||
setcookie('auth', false, 0, '/');
|
||||
\Chibi\UrlHelper::forward(\Chibi\UrlHelper::route('index', 'index'));
|
||||
}
|
||||
}
|
||||
|
@ -11,8 +11,9 @@ class CommentController
|
||||
$this->context->stylesheets []= 'post-small.css';
|
||||
$this->context->stylesheets []= 'comment-list.css';
|
||||
$this->context->stylesheets []= 'comment-small.css';
|
||||
$this->context->stylesheets []= 'paginator.css';
|
||||
$this->context->subTitle = 'comments';
|
||||
if ($this->config->browsing->endlessScrolling)
|
||||
if ($this->context->user->hasEnabledEndlessScrolling())
|
||||
$this->context->scripts []= 'paginator-endless.js';
|
||||
|
||||
$page = intval($page);
|
||||
|
@ -49,6 +49,7 @@ class IndexController
|
||||
*/
|
||||
public function helpAction()
|
||||
{
|
||||
$this->context->stylesheets []= 'index-help.css';
|
||||
$this->context->subTitle = 'help';
|
||||
}
|
||||
}
|
||||
|
@ -60,7 +60,7 @@ class PostController
|
||||
$this->context->stylesheets []= 'post-small.css';
|
||||
$this->context->stylesheets []= 'post-list.css';
|
||||
$this->context->stylesheets []= 'paginator.css';
|
||||
if ($this->config->browsing->endlessScrolling)
|
||||
if ($this->context->user->hasEnabledEndlessScrolling())
|
||||
$this->context->scripts []= 'paginator-endless.js';
|
||||
|
||||
//redirect requests in form of /posts/?query=... to canonical address
|
||||
@ -178,27 +178,95 @@ class PostController
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @route /random
|
||||
* @route /random/{page}
|
||||
* @validate page \d*
|
||||
*/
|
||||
public function randomAction($page = 1)
|
||||
{
|
||||
$this->listAction('order:random', $page);
|
||||
$this->context->viewName = 'post-list';
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @route /post/upload
|
||||
*/
|
||||
public function uploadAction()
|
||||
{
|
||||
$this->context->stylesheets []= 'upload.css';
|
||||
$this->context->stylesheets []= 'tabs.css';
|
||||
$this->context->scripts []= 'upload.js';
|
||||
$this->context->subTitle = 'upload';
|
||||
PrivilegesHelper::confirmWithException(Privilege::UploadPost);
|
||||
if ($this->config->registration->needEmailForUploading)
|
||||
PrivilegesHelper::confirmEmail($this->context->user);
|
||||
|
||||
if (!empty($_FILES['file']['name']))
|
||||
if (InputHelper::get('submit'))
|
||||
{
|
||||
/* file contents */
|
||||
$suppliedFile = $_FILES['file'];
|
||||
self::handleUploadErrors($suppliedFile);
|
||||
if (isset($_FILES['file']))
|
||||
{
|
||||
$suppliedFile = $_FILES['file'];
|
||||
self::handleUploadErrors($suppliedFile);
|
||||
$origName = basename($suppliedFile['name']);
|
||||
$sourcePath = $suppliedFile['tmp_name'];
|
||||
}
|
||||
elseif (InputHelper::get('url'))
|
||||
{
|
||||
$url = InputHelper::get('url');
|
||||
$origName = $url;
|
||||
if (!preg_match('/^https?:\/\//', $url))
|
||||
throw new SimpleException('Invalid URL "' . $url . '"');
|
||||
|
||||
if (preg_match('/youtube.com\/watch.*?=([a-zA-Z0-9_-]+)/', $url, $matches))
|
||||
{
|
||||
$origName = $matches[1];
|
||||
$postType = PostType::Youtube;
|
||||
$sourcePath = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
$sourcePath = tempnam(sys_get_temp_dir(), 'upload') . '.dat';
|
||||
|
||||
//warning: low level sh*t ahead
|
||||
//download the URL $url into $sourcePath
|
||||
$maxBytes = TextHelper::stripBytesUnits(ini_get('upload_max_filesize'));
|
||||
set_time_limit(0);
|
||||
$urlFP = fopen($url, 'rb');
|
||||
if (!$urlFP)
|
||||
throw new SimpleException('Cannot open URL for reading');
|
||||
$sourceFP = fopen($sourcePath, 'w+b');
|
||||
if (!$sourceFP)
|
||||
{
|
||||
fclose($urlFP);
|
||||
throw new SimpleException('Cannot open file for writing');
|
||||
}
|
||||
try
|
||||
{
|
||||
while (!feof($urlFP))
|
||||
{
|
||||
$buffer = fread($urlFP, 4 * 1024);
|
||||
if (fwrite($sourceFP, $buffer) === false)
|
||||
throw new SimpleException('Cannot write into file');
|
||||
fflush($sourceFP);
|
||||
if (ftell($sourceFP) > $maxBytes)
|
||||
throw new SimpleException('File is too big (maximum allowed size: ' . TextHelper::useBytesUnits($maxBytes) . ')');
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
fclose($urlFP);
|
||||
fclose($sourceFP);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* file details */
|
||||
$mimeType = mime_content_type($suppliedFile['tmp_name']);
|
||||
$mimeType = $sourcePath ? mime_content_type($sourcePath) : null;
|
||||
$imageWidth = null;
|
||||
$imageHeight = null;
|
||||
switch ($mimeType)
|
||||
@ -207,20 +275,36 @@ class PostController
|
||||
case 'image/png':
|
||||
case 'image/jpeg':
|
||||
$postType = PostType::Image;
|
||||
list ($imageWidth, $imageHeight) = getimagesize($suppliedFile['tmp_name']);
|
||||
list ($imageWidth, $imageHeight) = getimagesize($sourcePath);
|
||||
break;
|
||||
case 'application/x-shockwave-flash':
|
||||
$postType = PostType::Flash;
|
||||
list ($imageWidth, $imageHeight) = getimagesize($suppliedFile['tmp_name']);
|
||||
list ($imageWidth, $imageHeight) = getimagesize($sourcePath);
|
||||
break;
|
||||
default:
|
||||
throw new SimpleException('Invalid file type "' . $mimeType . '"');
|
||||
if (!isset($postType))
|
||||
throw new SimpleException('Invalid file type "' . $mimeType . '"');
|
||||
}
|
||||
|
||||
$fileHash = md5_file($suppliedFile['tmp_name']);
|
||||
$duplicatedPost = R::findOne('post', 'file_hash = ?', [$fileHash]);
|
||||
if ($duplicatedPost !== null)
|
||||
throw new SimpleException('Duplicate upload: @' . $duplicatedPost->id);
|
||||
if ($sourcePath)
|
||||
{
|
||||
$fileSize = filesize($sourcePath);
|
||||
$fileHash = md5_file($sourcePath);
|
||||
$duplicatedPost = R::findOne('post', 'file_hash = ?', [$fileHash]);
|
||||
if ($duplicatedPost !== null)
|
||||
throw new SimpleException('Duplicate upload: @' . $duplicatedPost->id);
|
||||
}
|
||||
else
|
||||
{
|
||||
$fileSize = 0;
|
||||
$fileHash = null;
|
||||
if ($postType == PostType::Youtube)
|
||||
{
|
||||
$duplicatedPost = R::findOne('post', 'orig_name = ?', [$origName]);
|
||||
if ($duplicatedPost !== null)
|
||||
throw new SimpleException('Duplicate upload: @' . $duplicatedPost->id);
|
||||
}
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
@ -247,9 +331,9 @@ class PostController
|
||||
$dbPost = R::dispense('post');
|
||||
$dbPost->type = $postType;
|
||||
$dbPost->name = $name;
|
||||
$dbPost->orig_name = basename($suppliedFile['name']);
|
||||
$dbPost->orig_name = $origName;
|
||||
$dbPost->file_hash = $fileHash;
|
||||
$dbPost->file_size = filesize($suppliedFile['tmp_name']);
|
||||
$dbPost->file_size = $fileSize;
|
||||
$dbPost->mime_type = $mimeType;
|
||||
$dbPost->safety = $suppliedSafety;
|
||||
$dbPost->source = $suppliedSource;
|
||||
@ -261,7 +345,13 @@ class PostController
|
||||
$dbPost->ownFavoritee = [];
|
||||
$dbPost->sharedTag = $dbTags;
|
||||
|
||||
move_uploaded_file($suppliedFile['tmp_name'], $path);
|
||||
if ($sourcePath)
|
||||
{
|
||||
if (is_uploaded_file($sourcePath))
|
||||
move_uploaded_file($sourcePath, $path);
|
||||
else
|
||||
rename($sourcePath, $path);
|
||||
}
|
||||
R::store($dbPost);
|
||||
|
||||
$this->context->transport->success = true;
|
||||
@ -277,73 +367,71 @@ class PostController
|
||||
{
|
||||
$post = Model_Post::locate($id);
|
||||
R::preload($post, ['uploader' => 'user']);
|
||||
$edited = false;
|
||||
|
||||
$this->context->transport->post = $post;
|
||||
|
||||
/* safety */
|
||||
$suppliedSafety = InputHelper::get('safety');
|
||||
if ($suppliedSafety !== null)
|
||||
if (InputHelper::get('submit'))
|
||||
{
|
||||
PrivilegesHelper::confirmWithException(Privilege::EditPostSafety, PrivilegesHelper::getIdentitySubPrivilege($post->uploader));
|
||||
$suppliedSafety = Model_Post::validateSafety($suppliedSafety);
|
||||
$post->safety = $suppliedSafety;
|
||||
$edited = true;
|
||||
}
|
||||
/* safety */
|
||||
$suppliedSafety = InputHelper::get('safety');
|
||||
if ($suppliedSafety !== null)
|
||||
{
|
||||
PrivilegesHelper::confirmWithException(Privilege::EditPostSafety, PrivilegesHelper::getIdentitySubPrivilege($post->uploader));
|
||||
$suppliedSafety = Model_Post::validateSafety($suppliedSafety);
|
||||
$post->safety = $suppliedSafety;
|
||||
$edited = true;
|
||||
}
|
||||
|
||||
|
||||
/* tags */
|
||||
$suppliedTags = InputHelper::get('tags');
|
||||
if ($suppliedTags !== null)
|
||||
{
|
||||
PrivilegesHelper::confirmWithException(Privilege::EditPostTags, PrivilegesHelper::getIdentitySubPrivilege($post->uploader));
|
||||
$currentToken = self::serializeTags($post);
|
||||
if (InputHelper::get('tags-token') != $currentToken)
|
||||
throw new SimpleException('Someone else has changed the tags in the meantime');
|
||||
/* tags */
|
||||
$suppliedTags = InputHelper::get('tags');
|
||||
if ($suppliedTags !== null)
|
||||
{
|
||||
PrivilegesHelper::confirmWithException(Privilege::EditPostTags, PrivilegesHelper::getIdentitySubPrivilege($post->uploader));
|
||||
$currentToken = self::serializeTags($post);
|
||||
if (InputHelper::get('tags-token') != $currentToken)
|
||||
throw new SimpleException('Someone else has changed the tags in the meantime');
|
||||
|
||||
$suppliedTags = Model_Tag::validateTags($suppliedTags);
|
||||
$dbTags = Model_Tag::insertOrUpdate($suppliedTags);
|
||||
$post->sharedTag = $dbTags;
|
||||
$edited = true;
|
||||
}
|
||||
$suppliedTags = Model_Tag::validateTags($suppliedTags);
|
||||
$dbTags = Model_Tag::insertOrUpdate($suppliedTags);
|
||||
$post->sharedTag = $dbTags;
|
||||
$edited = true;
|
||||
}
|
||||
|
||||
|
||||
/* thumbnail */
|
||||
if (!empty($_FILES['thumb']['name']))
|
||||
{
|
||||
PrivilegesHelper::confirmWithException(Privilege::EditPostThumb, PrivilegesHelper::getIdentitySubPrivilege($post->uploader));
|
||||
$suppliedFile = $_FILES['thumb'];
|
||||
self::handleUploadErrors($suppliedFile);
|
||||
/* thumbnail */
|
||||
if (!empty($_FILES['thumb']['name']))
|
||||
{
|
||||
PrivilegesHelper::confirmWithException(Privilege::EditPostThumb, PrivilegesHelper::getIdentitySubPrivilege($post->uploader));
|
||||
$suppliedFile = $_FILES['thumb'];
|
||||
self::handleUploadErrors($suppliedFile);
|
||||
|
||||
$mimeType = mime_content_type($suppliedFile['tmp_name']);
|
||||
if (!in_array($mimeType, ['image/gif', 'image/png', 'image/jpeg']))
|
||||
throw new SimpleException('Invalid thumbnail type "' . $mimeType . '"');
|
||||
list ($imageWidth, $imageHeight) = getimagesize($suppliedFile['tmp_name']);
|
||||
if ($imageWidth != $this->config->browsing->thumbWidth)
|
||||
throw new SimpleException('Invalid thumbnail width (should be ' . $this->config->browsing->thumbWidth . ')');
|
||||
if ($imageWidth != $this->config->browsing->thumbHeight)
|
||||
throw new SimpleException('Invalid thumbnail width (should be ' . $this->config->browsing->thumbHeight . ')');
|
||||
$mimeType = mime_content_type($suppliedFile['tmp_name']);
|
||||
if (!in_array($mimeType, ['image/gif', 'image/png', 'image/jpeg']))
|
||||
throw new SimpleException('Invalid thumbnail type "' . $mimeType . '"');
|
||||
list ($imageWidth, $imageHeight) = getimagesize($suppliedFile['tmp_name']);
|
||||
if ($imageWidth != $this->config->browsing->thumbWidth)
|
||||
throw new SimpleException('Invalid thumbnail width (should be ' . $this->config->browsing->thumbWidth . ')');
|
||||
if ($imageWidth != $this->config->browsing->thumbHeight)
|
||||
throw new SimpleException('Invalid thumbnail width (should be ' . $this->config->browsing->thumbHeight . ')');
|
||||
|
||||
$path = $this->config->main->thumbsPath . DS . $post->name;
|
||||
move_uploaded_file($suppliedFile['tmp_name'], $path);
|
||||
}
|
||||
$path = $this->config->main->thumbsPath . DS . $post->name;
|
||||
move_uploaded_file($suppliedFile['tmp_name'], $path);
|
||||
}
|
||||
|
||||
|
||||
/* source */
|
||||
$suppliedSource = InputHelper::get('source');
|
||||
if ($suppliedSource !== null)
|
||||
{
|
||||
PrivilegesHelper::confirmWithException(Privilege::EditPostSource, PrivilegesHelper::getIdentitySubPrivilege($post->uploader));
|
||||
$suppliedSource = Model_Post::validateSource($suppliedSource);
|
||||
$post->source = $suppliedSource;
|
||||
$edited = true;
|
||||
}
|
||||
/* source */
|
||||
$suppliedSource = InputHelper::get('source');
|
||||
if ($suppliedSource !== null)
|
||||
{
|
||||
PrivilegesHelper::confirmWithException(Privilege::EditPostSource, PrivilegesHelper::getIdentitySubPrivilege($post->uploader));
|
||||
$suppliedSource = Model_Post::validateSource($suppliedSource);
|
||||
$post->source = $suppliedSource;
|
||||
$edited = true;
|
||||
}
|
||||
|
||||
|
||||
/* db storage */
|
||||
if ($edited)
|
||||
R::store($post);
|
||||
$this->context->transport->success = true;
|
||||
$this->context->transport->success = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -354,10 +442,14 @@ class PostController
|
||||
public function hideAction($id)
|
||||
{
|
||||
$post = Model_Post::locate($id);
|
||||
R::preload($post, ['uploader' => 'user']);
|
||||
PrivilegesHelper::confirmWithException(Privilege::HidePost, PrivilegesHelper::getIdentitySubPrivilege($post->uploader));
|
||||
$post->hidden = true;
|
||||
R::store($post);
|
||||
$this->context->transport->success = true;
|
||||
if (InputHelper::get('submit'))
|
||||
{
|
||||
$post->hidden = true;
|
||||
R::store($post);
|
||||
$this->context->transport->success = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -366,10 +458,14 @@ class PostController
|
||||
public function unhideAction($id)
|
||||
{
|
||||
$post = Model_Post::locate($id);
|
||||
R::preload($post, ['uploader' => 'user']);
|
||||
PrivilegesHelper::confirmWithException(Privilege::HidePost, PrivilegesHelper::getIdentitySubPrivilege($post->uploader));
|
||||
$post->hidden = false;
|
||||
R::store($post);
|
||||
$this->context->transport->success = true;
|
||||
if (InputHelper::get('submit'))
|
||||
{
|
||||
$post->hidden = false;
|
||||
R::store($post);
|
||||
$this->context->transport->success = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -378,13 +474,17 @@ class PostController
|
||||
public function deleteAction($id)
|
||||
{
|
||||
$post = Model_Post::locate($id);
|
||||
R::preload($post, ['uploader' => 'user']);
|
||||
PrivilegesHelper::confirmWithException(Privilege::DeletePost, PrivilegesHelper::getIdentitySubPrivilege($post->uploader));
|
||||
//remove stuff from auxiliary tables
|
||||
$post->ownFavoritee = [];
|
||||
$post->sharedTag = [];
|
||||
R::store($post);
|
||||
R::trash($post);
|
||||
$this->context->transport->success = true;
|
||||
if (InputHelper::get('submit'))
|
||||
{
|
||||
//remove stuff from auxiliary tables
|
||||
$post->ownFavoritee = [];
|
||||
$post->sharedTag = [];
|
||||
R::store($post);
|
||||
R::trash($post);
|
||||
$this->context->transport->success = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -397,18 +497,21 @@ class PostController
|
||||
{
|
||||
$post = Model_Post::locate($id);
|
||||
R::preload($post, ['favoritee' => 'user']);
|
||||
|
||||
if (!$this->context->loggedIn)
|
||||
throw new SimpleException('Not logged in');
|
||||
|
||||
foreach ($post->via('favoritee')->sharedUser as $fav)
|
||||
if ($fav->id == $this->context->user->id)
|
||||
throw new SimpleException('Already in favorites');
|
||||
|
||||
PrivilegesHelper::confirmWithException(Privilege::FavoritePost);
|
||||
$post->link('favoritee')->user = $this->context->user;
|
||||
R::store($post);
|
||||
$this->context->transport->success = true;
|
||||
|
||||
if (InputHelper::get('submit'))
|
||||
{
|
||||
if (!$this->context->loggedIn)
|
||||
throw new SimpleException('Not logged in');
|
||||
|
||||
foreach ($post->via('favoritee')->sharedUser as $fav)
|
||||
if ($fav->id == $this->context->user->id)
|
||||
throw new SimpleException('Already in favorites');
|
||||
|
||||
$post->link('favoritee')->user = $this->context->user;
|
||||
R::store($post);
|
||||
$this->context->transport->success = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -419,22 +522,25 @@ class PostController
|
||||
{
|
||||
$post = Model_Post::locate($id);
|
||||
R::preload($post, ['favoritee' => 'user']);
|
||||
|
||||
PrivilegesHelper::confirmWithException(Privilege::FavoritePost);
|
||||
if (!$this->context->loggedIn)
|
||||
throw new SimpleException('Not logged in');
|
||||
|
||||
$finalKey = null;
|
||||
foreach ($post->ownFavoritee as $key => $fav)
|
||||
if ($fav->user->id == $this->context->user->id)
|
||||
$finalKey = $key;
|
||||
if (InputHelper::get('submit'))
|
||||
{
|
||||
if (!$this->context->loggedIn)
|
||||
throw new SimpleException('Not logged in');
|
||||
|
||||
if ($finalKey === null)
|
||||
throw new SimpleException('Not in favorites');
|
||||
$finalKey = null;
|
||||
foreach ($post->ownFavoritee as $key => $fav)
|
||||
if ($fav->user->id == $this->context->user->id)
|
||||
$finalKey = $key;
|
||||
|
||||
unset ($post->ownFavoritee[$finalKey]);
|
||||
R::store($post);
|
||||
$this->context->transport->success = true;
|
||||
if ($finalKey === null)
|
||||
throw new SimpleException('Not in favorites');
|
||||
|
||||
unset ($post->ownFavoritee[$finalKey]);
|
||||
R::store($post);
|
||||
$this->context->transport->success = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -528,25 +634,33 @@ class PostController
|
||||
|
||||
/**
|
||||
* Action that renders the thumbnail of the requested file and sends it to user.
|
||||
* @route /post/{id}/thumb
|
||||
* @route /post/{name}/thumb
|
||||
*/
|
||||
public function thumbAction($id)
|
||||
public function thumbAction($name)
|
||||
{
|
||||
$this->context->layoutName = 'layout-file';
|
||||
$post = Model_Post::locate($id);
|
||||
|
||||
PrivilegesHelper::confirmWithException(Privilege::ViewPost);
|
||||
PrivilegesHelper::confirmWithException(Privilege::ViewPost, PostSafety::toString($post->safety));
|
||||
|
||||
$path = $this->config->main->thumbsPath . DS . $post->name;
|
||||
$path = $this->config->main->thumbsPath . DS . $name;
|
||||
if (!file_exists($path))
|
||||
{
|
||||
$post = Model_Post::locate($name);
|
||||
|
||||
PrivilegesHelper::confirmWithException(Privilege::ViewPost);
|
||||
PrivilegesHelper::confirmWithException(Privilege::ViewPost, PostSafety::toString($post->safety));
|
||||
$srcPath = $this->config->main->filesPath . DS . $post->name;
|
||||
$dstPath = $path;
|
||||
$dstWidth = $this->config->browsing->thumbWidth;
|
||||
$dstHeight = $this->config->browsing->thumbHeight;
|
||||
|
||||
switch ($post->mime_type)
|
||||
if ($post->type == PostType::Youtube)
|
||||
{
|
||||
$tmpPath = tempnam(sys_get_temp_dir(), 'thumb') . '.png';
|
||||
$contents = file_get_contents('http://img.youtube.com/vi/' . $post->orig_name . '/mqdefault.jpg');
|
||||
file_put_contents($tmpPath, $contents);
|
||||
if (file_exists($tmpPath))
|
||||
$srcImage = imagecreatefromjpeg($tmpPath);
|
||||
}
|
||||
else switch ($post->mime_type)
|
||||
{
|
||||
case 'image/jpeg':
|
||||
$srcImage = imagecreatefromjpeg($srcPath);
|
||||
@ -558,10 +672,17 @@ class PostController
|
||||
$srcImage = imagecreatefromgif($srcPath);
|
||||
break;
|
||||
case 'application/x-shockwave-flash':
|
||||
$path = $this->config->main->mediaPath . DS . 'img' . DS . 'thumb-swf.png';
|
||||
$srcImage = null;
|
||||
exec('which swfrender', $tmp, $exitCode);
|
||||
if ($exitCode == 0)
|
||||
{
|
||||
$tmpPath = tempnam(sys_get_temp_dir(), 'thumb') . '.png';
|
||||
exec('swfrender ' . $srcPath . ' -o ' . $tmpPath);
|
||||
if (file_exists($tmpPath))
|
||||
$srcImage = imagecreatefrompng($tmpPath);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
$path = $this->config->main->mediaPath . DS . 'img' . DS . 'thumb.png';
|
||||
break;
|
||||
}
|
||||
|
||||
@ -583,13 +704,20 @@ class PostController
|
||||
imagedestroy($srcImage);
|
||||
imagedestroy($dstImage);
|
||||
}
|
||||
else
|
||||
{
|
||||
$path = $this->config->main->mediaPath . DS . 'img' . DS . 'thumb.png';
|
||||
}
|
||||
|
||||
if (isset($tmpPath))
|
||||
unlink($tmpPath);
|
||||
}
|
||||
if (!is_readable($path))
|
||||
throw new SimpleException('Thumbnail file is not readable');
|
||||
|
||||
$this->context->transport->cacheDaysToLive = 30;
|
||||
$this->context->transport->mimeType = 'image/png';
|
||||
$this->context->transport->fileHash = 'thumb' . $post->file_hash;
|
||||
$this->context->transport->fileHash = 'thumb' . md5($name . filemtime($path));
|
||||
$this->context->transport->filePath = $path;
|
||||
}
|
||||
|
||||
@ -667,7 +795,7 @@ class PostController
|
||||
->innerJoin('tag')
|
||||
->on('post_tag.tag_id = tag.id')
|
||||
->where('post_id = post.id')
|
||||
->and('tag.name = ?')->put($val)
|
||||
->and('LOWER(tag.name) = LOWER(?)')->put($val)
|
||||
->close();
|
||||
continue;
|
||||
}
|
||||
@ -693,6 +821,10 @@ class PostController
|
||||
case 'img':
|
||||
$type = PostType::Image;
|
||||
break;
|
||||
case 'yt':
|
||||
case 'youtube':
|
||||
$type = PostType::Youtube;
|
||||
break;
|
||||
default:
|
||||
throw new SimpleException('Unknown type "' . $val . '"');
|
||||
}
|
||||
|
@ -10,15 +10,26 @@ class TagController
|
||||
$this->context->subTitle = 'tags';
|
||||
|
||||
PrivilegesHelper::confirmWithException(Privilege::ListTags);
|
||||
$suppliedFilter = InputHelper::get('filter');
|
||||
|
||||
$dbQuery = R::$f->begin();
|
||||
$dbQuery->select('tag.name, COUNT(1) AS count');
|
||||
$dbQuery->select('tag.*, COUNT(1) AS count');
|
||||
$dbQuery->from('tag');
|
||||
$dbQuery->innerJoin('post_tag');
|
||||
$dbQuery->on('tag.id = post_tag.tag_id');
|
||||
if ($suppliedFilter)
|
||||
{
|
||||
if (strlen($suppliedFilter) >= 3)
|
||||
$suppliedFilter = '%' . $suppliedFilter;
|
||||
$suppliedFilter .= '%';
|
||||
$dbQuery->where('LOWER(tag.name) LIKE LOWER(?)')->put($suppliedFilter);
|
||||
}
|
||||
$dbQuery->groupBy('tag.id');
|
||||
$dbQuery->orderBy('LOWER(tag.name)')->asc();
|
||||
if ($suppliedFilter)
|
||||
$dbQuery->limit(15);
|
||||
$rows = $dbQuery->get();
|
||||
$tags = R::convertToBeans('tag', $rows);
|
||||
|
||||
$tags = [];
|
||||
$tagDistribution = [];
|
||||
@ -38,22 +49,25 @@ class TagController
|
||||
public function mergeAction()
|
||||
{
|
||||
PrivilegesHelper::confirmWithException(Privilege::MergeTags);
|
||||
$sourceTag = Model_Tag::locate(InputHelper::get('source-tag'));
|
||||
$targetTag = Model_Tag::locate(InputHelper::get('target-tag'));
|
||||
|
||||
R::preload($sourceTag, 'post');
|
||||
|
||||
foreach ($sourceTag->sharedPost as $post)
|
||||
if (InputHelper::get('submit'))
|
||||
{
|
||||
foreach ($post->sharedTag as $key => $postTag)
|
||||
if ($postTag->id == $sourceTag->id)
|
||||
unset($post->sharedTag[$key]);
|
||||
$post->sharedTag []= $targetTag;
|
||||
R::store($post);
|
||||
$sourceTag = Model_Tag::locate(InputHelper::get('source-tag'));
|
||||
$targetTag = Model_Tag::locate(InputHelper::get('target-tag'));
|
||||
|
||||
R::preload($sourceTag, 'post');
|
||||
|
||||
foreach ($sourceTag->sharedPost as $post)
|
||||
{
|
||||
foreach ($post->sharedTag as $key => $postTag)
|
||||
if ($postTag->id == $sourceTag->id)
|
||||
unset($post->sharedTag[$key]);
|
||||
$post->sharedTag []= $targetTag;
|
||||
R::store($post);
|
||||
}
|
||||
R::trash($sourceTag);
|
||||
\Chibi\UrlHelper::forward(\Chibi\UrlHelper::route('tag', 'list'));
|
||||
$this->view->context->success = true;
|
||||
}
|
||||
R::trash($sourceTag);
|
||||
\Chibi\UrlHelper::forward(\Chibi\UrlHelper::route('tag', 'list'));
|
||||
$this->view->context->success = true;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -62,18 +76,20 @@ class TagController
|
||||
public function renameAction()
|
||||
{
|
||||
PrivilegesHelper::confirmWithException(Privilege::MergeTags);
|
||||
if (InputHelper::get('submit'))
|
||||
{
|
||||
$suppliedSourceTag = InputHelper::get('source-tag');
|
||||
$suppliedSourceTag = Model_Tag::validateTag($suppliedSourceTag);
|
||||
|
||||
$suppliedSourceTag = InputHelper::get('source-tag');
|
||||
$suppliedSourceTag = Model_Tag::validateTag($suppliedSourceTag);
|
||||
$suppliedTargetTag = InputHelper::get('target-tag');
|
||||
$suppliedTargetTag = Model_Tag::validateTag($suppliedTargetTag);
|
||||
|
||||
$suppliedTargetTag = InputHelper::get('target-tag');
|
||||
$suppliedTargetTag = Model_Tag::validateTag($suppliedTargetTag);
|
||||
$sourceTag = Model_Tag::locate($suppliedSourceTag);
|
||||
$sourceTag->name = $suppliedTargetTag;
|
||||
R::store($sourceTag);
|
||||
|
||||
$sourceTag = Model_Tag::locate($suppliedSourceTag);
|
||||
$sourceTag->name = $suppliedTargetTag;
|
||||
R::store($sourceTag);
|
||||
|
||||
\Chibi\UrlHelper::forward(\Chibi\UrlHelper::route('tag', 'list'));
|
||||
$this->context->transport->success = true;
|
||||
\Chibi\UrlHelper::forward(\Chibi\UrlHelper::route('tag', 'list'));
|
||||
$this->context->transport->success = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -53,7 +53,7 @@ class UserController
|
||||
{
|
||||
$this->context->stylesheets []= 'user-list.css';
|
||||
$this->context->stylesheets []= 'paginator.css';
|
||||
if ($this->config->browsing->endlessScrolling)
|
||||
if ($this->context->user->hasEnabledEndlessScrolling())
|
||||
$this->context->scripts []= 'paginator-endless.js';
|
||||
|
||||
$page = intval($page);
|
||||
@ -128,9 +128,12 @@ class UserController
|
||||
{
|
||||
$user = Model_User::locate($name);
|
||||
PrivilegesHelper::confirmWithException(Privilege::BanUser, PrivilegesHelper::getIdentitySubPrivilege($user));
|
||||
$user->banned = true;
|
||||
R::store($user);
|
||||
$this->context->transport->success = true;
|
||||
if (InputHelper::get('submit'))
|
||||
{
|
||||
$user->banned = true;
|
||||
R::store($user);
|
||||
$this->context->transport->success = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -141,9 +144,12 @@ class UserController
|
||||
{
|
||||
$user = Model_User::locate($name);
|
||||
PrivilegesHelper::confirmWithException(Privilege::BanUser, PrivilegesHelper::getIdentitySubPrivilege($user));
|
||||
$user->banned = false;
|
||||
R::store($user);
|
||||
$this->context->transport->success = true;
|
||||
if (InputHelper::get('submit'))
|
||||
{
|
||||
$user->banned = false;
|
||||
R::store($user);
|
||||
$this->context->transport->success = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -154,14 +160,16 @@ class UserController
|
||||
{
|
||||
$user = Model_User::locate($name);
|
||||
PrivilegesHelper::confirmWithException(Privilege::AcceptUserRegistration);
|
||||
$user->staff_confirmed = true;
|
||||
R::store($user);
|
||||
$this->context->transport->success = true;
|
||||
if (InputHelper::get('submit'))
|
||||
{
|
||||
$user->staff_confirmed = true;
|
||||
R::store($user);
|
||||
$this->context->transport->success = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @route /user/{name}/delete
|
||||
* @validate name [^\/]+
|
||||
@ -176,12 +184,13 @@ class UserController
|
||||
$this->context->transport->user = $user;
|
||||
$this->context->transport->tab = 'delete';
|
||||
$this->context->viewName = 'user-view';
|
||||
$this->context->stylesheets []= 'tabs.css';
|
||||
$this->context->stylesheets []= 'user-view.css';
|
||||
$this->context->subTitle = $name;
|
||||
|
||||
$this->context->suppliedCurrentPassword = $suppliedCurrentPassword = InputHelper::get('current-password');
|
||||
|
||||
if (InputHelper::get('remove'))
|
||||
if (InputHelper::get('submit'))
|
||||
{
|
||||
if ($this->context->user->id == $user->id)
|
||||
{
|
||||
@ -209,6 +218,42 @@ class UserController
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @route /user/{name}/settings
|
||||
* @validate name [^\/]+
|
||||
*/
|
||||
public function settingsAction($name)
|
||||
{
|
||||
$user = Model_User::locate($name);
|
||||
PrivilegesHelper::confirmWithException(Privilege::ViewUser, PrivilegesHelper::getIdentitySubPrivilege($user));
|
||||
PrivilegesHelper::confirmWithException(Privilege::ChangeUserSettings, PrivilegesHelper::getIdentitySubPrivilege($user));
|
||||
|
||||
$this->context->handleExceptions = true;
|
||||
$this->context->transport->user = $user;
|
||||
$this->context->transport->tab = 'settings';
|
||||
$this->context->viewName = 'user-view';
|
||||
$this->context->stylesheets []= 'tabs.css';
|
||||
$this->context->stylesheets []= 'user-view.css';
|
||||
$this->context->subTitle = $name;
|
||||
|
||||
if (InputHelper::get('submit'))
|
||||
{
|
||||
$suppliedSafety = InputHelper::get('safety');
|
||||
if (!is_array($suppliedSafety))
|
||||
$suppliedSafety = [];
|
||||
foreach (PostSafety::getAll() as $safety)
|
||||
$user->enableSafety($safety, in_array($safety, $suppliedSafety));
|
||||
|
||||
$user->enableEndlessScrolling(InputHelper::get('endless-scrolling'));
|
||||
|
||||
R::store($user);
|
||||
$this->context->transport->user = $user;
|
||||
$this->context->transport->success = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @route /user/{name}/edit
|
||||
* @validate name [^\/]+
|
||||
@ -217,15 +262,14 @@ class UserController
|
||||
{
|
||||
try
|
||||
{
|
||||
|
||||
$user = Model_User::locate($name);
|
||||
$edited = false;
|
||||
PrivilegesHelper::confirmWithException(Privilege::ViewUser, PrivilegesHelper::getIdentitySubPrivilege($user));
|
||||
|
||||
$this->context->handleExceptions = true;
|
||||
$this->context->transport->user = $user;
|
||||
$this->context->transport->tab = 'edit';
|
||||
$this->context->viewName = 'user-view';
|
||||
$this->context->stylesheets []= 'tabs.css';
|
||||
$this->context->stylesheets []= 'user-view.css';
|
||||
$this->context->subTitle = $name;
|
||||
|
||||
@ -237,51 +281,47 @@ class UserController
|
||||
$this->context->suppliedAccessRank = $suppliedAccessRank = InputHelper::get('access-rank');
|
||||
$currentPasswordHash = $user->pass_hash;
|
||||
|
||||
if ($suppliedName != '' and $suppliedName != $user->name)
|
||||
if (InputHelper::get('submit'))
|
||||
{
|
||||
PrivilegesHelper::confirmWithException(Privilege::ChangeUserName, PrivilegesHelper::getIdentitySubPrivilege($user));
|
||||
$suppliedName = Model_User::validateUserName($suppliedName);
|
||||
$user->name = $suppliedName;
|
||||
$edited = true;
|
||||
}
|
||||
|
||||
if ($suppliedPassword1 != '')
|
||||
{
|
||||
PrivilegesHelper::confirmWithException(Privilege::ChangeUserPassword, PrivilegesHelper::getIdentitySubPrivilege($user));
|
||||
if ($suppliedPassword1 != $suppliedPassword2)
|
||||
throw new SimpleException('Specified passwords must be the same');
|
||||
$suppliedPassword = Model_User::validatePassword($suppliedPassword1);
|
||||
$user->pass_hash = Model_User::hashPassword($suppliedPassword, $user->pass_salt);
|
||||
$edited = true;
|
||||
}
|
||||
|
||||
if ($suppliedEmail != '' and $suppliedEmail != $user->email_confirmed)
|
||||
{
|
||||
PrivilegesHelper::confirmWithException(Privilege::ChangeUserEmail, PrivilegesHelper::getIdentitySubPrivilege($user));
|
||||
$suppliedEmail = Model_User::validateEmail($suppliedEmail);
|
||||
if ($this->context->user->id == $user->id)
|
||||
if ($suppliedName != '' and $suppliedName != $user->name)
|
||||
{
|
||||
$user->email_unconfirmed = $suppliedEmail;
|
||||
if (!empty($user->email_unconfirmed))
|
||||
self::sendEmailConfirmation($user);
|
||||
PrivilegesHelper::confirmWithException(Privilege::ChangeUserName, PrivilegesHelper::getIdentitySubPrivilege($user));
|
||||
$suppliedName = Model_User::validateUserName($suppliedName);
|
||||
$user->name = $suppliedName;
|
||||
}
|
||||
else
|
||||
|
||||
if ($suppliedPassword1 != '')
|
||||
{
|
||||
$user->email_confirmed = $suppliedEmail;
|
||||
PrivilegesHelper::confirmWithException(Privilege::ChangeUserPassword, PrivilegesHelper::getIdentitySubPrivilege($user));
|
||||
if ($suppliedPassword1 != $suppliedPassword2)
|
||||
throw new SimpleException('Specified passwords must be the same');
|
||||
$suppliedPassword = Model_User::validatePassword($suppliedPassword1);
|
||||
$user->pass_hash = Model_User::hashPassword($suppliedPassword, $user->pass_salt);
|
||||
}
|
||||
$edited = true;
|
||||
}
|
||||
|
||||
if ($suppliedAccessRank != '' and $suppliedAccessRank != $user->access_rank)
|
||||
{
|
||||
PrivilegesHelper::confirmWithException(Privilege::ChangeUserAccessRank, PrivilegesHelper::getIdentitySubPrivilege($user));
|
||||
$suppliedAccessRank = Model_User::validateAccessRank($suppliedAccessRank);
|
||||
$user->access_rank = $suppliedAccessRank;
|
||||
$edited = true;
|
||||
}
|
||||
if ($suppliedEmail != '' and $suppliedEmail != $user->email_confirmed)
|
||||
{
|
||||
PrivilegesHelper::confirmWithException(Privilege::ChangeUserEmail, PrivilegesHelper::getIdentitySubPrivilege($user));
|
||||
$suppliedEmail = Model_User::validateEmail($suppliedEmail);
|
||||
if ($this->context->user->id == $user->id)
|
||||
{
|
||||
$user->email_unconfirmed = $suppliedEmail;
|
||||
if (!empty($user->email_unconfirmed))
|
||||
self::sendEmailConfirmation($user);
|
||||
}
|
||||
else
|
||||
{
|
||||
$user->email_confirmed = $suppliedEmail;
|
||||
}
|
||||
}
|
||||
|
||||
if ($suppliedAccessRank != '' and $suppliedAccessRank != $user->access_rank)
|
||||
{
|
||||
PrivilegesHelper::confirmWithException(Privilege::ChangeUserAccessRank, PrivilegesHelper::getIdentitySubPrivilege($user));
|
||||
$suppliedAccessRank = Model_User::validateAccessRank($suppliedAccessRank);
|
||||
$user->access_rank = $suppliedAccessRank;
|
||||
}
|
||||
|
||||
if ($edited)
|
||||
{
|
||||
if ($this->context->user->id == $user->id)
|
||||
{
|
||||
$suppliedPasswordHash = Model_User::hashPassword($suppliedCurrentPassword, $user->pass_salt);
|
||||
@ -291,7 +331,6 @@ class UserController
|
||||
R::store($user);
|
||||
$this->context->transport->success = true;
|
||||
}
|
||||
|
||||
}
|
||||
catch (Exception $e)
|
||||
{
|
||||
@ -319,11 +358,12 @@ class UserController
|
||||
$page = 1;
|
||||
|
||||
PrivilegesHelper::confirmWithException(Privilege::ViewUser, PrivilegesHelper::getIdentitySubPrivilege($user));
|
||||
$this->context->stylesheets []= 'tabs.css';
|
||||
$this->context->stylesheets []= 'user-view.css';
|
||||
$this->context->stylesheets []= 'post-list.css';
|
||||
$this->context->stylesheets []= 'post-small.css';
|
||||
$this->context->stylesheets []= 'paginator.css';
|
||||
if ($this->config->browsing->endlessScrolling)
|
||||
if ($this->context->user->hasEnabledEndlessScrolling())
|
||||
$this->context->scripts []= 'paginator-endless.js';
|
||||
$this->context->subTitle = $name;
|
||||
|
||||
@ -405,8 +445,7 @@ class UserController
|
||||
*/
|
||||
public function toggleSafetyAction($safety)
|
||||
{
|
||||
if (!$this->context->loggedIn)
|
||||
throw new SimpleException('Not logged in');
|
||||
PrivilegesHelper::confirmWithException(Privilege::ChangeUserSettings, PrivilegesHelper::getIdentitySubPrivilege($this->context->user));
|
||||
|
||||
if (!in_array($safety, PostSafety::getAll()))
|
||||
throw new SimpleExcetpion('Invalid safety');
|
||||
@ -446,7 +485,7 @@ class UserController
|
||||
$this->context->suppliedPassword2 = $suppliedPassword2;
|
||||
$this->context->suppliedEmail = $suppliedEmail;
|
||||
|
||||
if ($suppliedName !== null)
|
||||
if (InputHelper::get('submit'))
|
||||
{
|
||||
$suppliedName = Model_User::validateUserName($suppliedName);
|
||||
|
||||
@ -478,6 +517,7 @@ class UserController
|
||||
{
|
||||
$dbUser->access_rank = AccessRank::Admin;
|
||||
$dbUser->staff_confirmed = true;
|
||||
$dbUser->email_unconfirmed = null;
|
||||
$dbUser->email_confirmed = $suppliedEmail;
|
||||
}
|
||||
else
|
||||
|
@ -63,6 +63,18 @@ class TextHelper
|
||||
return constant($constantName);
|
||||
}
|
||||
|
||||
private static function stripUnits($string, $base, $suffixes)
|
||||
{
|
||||
$suffix = substr($string, -1, 1);
|
||||
$index = array_search($suffix, $suffixes);
|
||||
if ($index === false)
|
||||
return $string;
|
||||
$number = intval($string);
|
||||
for ($i = 0; $i < $index; $i ++)
|
||||
$number *= $base;
|
||||
return $number;
|
||||
}
|
||||
|
||||
private static function useUnits($number, $base, $suffixes)
|
||||
{
|
||||
$suffix = array_shift($suffixes);
|
||||
@ -89,6 +101,16 @@ class TextHelper
|
||||
return self::useUnits($number, 1000, ['', 'K', 'M']);
|
||||
}
|
||||
|
||||
public static function stripBytesUnits($string)
|
||||
{
|
||||
return self::stripUnits($string, 1024, ['B', 'K', 'M', 'G']);
|
||||
}
|
||||
|
||||
public static function stripDecimalUnits($string)
|
||||
{
|
||||
return self::stripUnits($string, 1000, ['', 'K', 'M']);
|
||||
}
|
||||
|
||||
public static function removeUnsafeKeys(&$input, $regex)
|
||||
{
|
||||
if (is_array($input))
|
||||
@ -149,4 +171,22 @@ class TextHelper
|
||||
$output = preg_replace('{</?p>}', '', $output);
|
||||
return $output;
|
||||
}
|
||||
|
||||
public static function encrypt($text)
|
||||
{
|
||||
$salt = \Chibi\Registry::getConfig()->main->salt;
|
||||
$alg = MCRYPT_RIJNDAEL_256;
|
||||
$mode = MCRYPT_MODE_ECB;
|
||||
$iv = mcrypt_create_iv(mcrypt_get_iv_size($alg, $mode), MCRYPT_RAND);
|
||||
return trim(base64_encode(mcrypt_encrypt($alg, $salt, $text, $mode, $iv)));
|
||||
}
|
||||
|
||||
public static function decrypt($text)
|
||||
{
|
||||
$salt = \Chibi\Registry::getConfig()->main->salt;
|
||||
$alg = MCRYPT_RIJNDAEL_256;
|
||||
$mode = MCRYPT_MODE_ECB;
|
||||
$iv = mcrypt_create_iv(mcrypt_get_iv_size($alg, $mode), MCRYPT_RAND);
|
||||
return trim(mcrypt_decrypt($alg, $salt, base64_decode($text), $mode, $iv));
|
||||
}
|
||||
}
|
||||
|
@ -1,11 +1,15 @@
|
||||
<?php
|
||||
class Model_Comment extends RedBean_SimpleModel
|
||||
{
|
||||
public static function locate($key)
|
||||
public static function locate($key, $throw = true)
|
||||
{
|
||||
$comment = R::findOne('comment', 'id = ?', [$key]);
|
||||
if (!$comment)
|
||||
throw new SimpleException('Invalid comment ID "' . $key . '"');
|
||||
{
|
||||
if ($throw)
|
||||
throw new SimpleException('Invalid comment ID "' . $key . '"');
|
||||
return null;
|
||||
}
|
||||
return $comment;
|
||||
}
|
||||
|
||||
|
@ -1,19 +1,27 @@
|
||||
<?php
|
||||
class Model_Post extends RedBean_SimpleModel
|
||||
{
|
||||
public static function locate($key, $disallowNumeric = false)
|
||||
public static function locate($key, $disallowNumeric = false, $throw = true)
|
||||
{
|
||||
if (is_numeric($key) and !$disallowNumeric)
|
||||
{
|
||||
$post = R::findOne('post', 'id = ?', [$key]);
|
||||
if (!$post)
|
||||
throw new SimpleException('Invalid post ID "' . $key . '"');
|
||||
{
|
||||
if ($throw)
|
||||
throw new SimpleException('Invalid post ID "' . $key . '"');
|
||||
return null;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$post = R::findOne('post', 'name = ?', [$key]);
|
||||
if (!$post)
|
||||
throw new SimpleException('Invalid post name "' . $key . '"');
|
||||
{
|
||||
if ($throw)
|
||||
throw new SimpleException('Invalid post name "' . $key . '"');
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return $post;
|
||||
}
|
||||
|
@ -1,12 +1,16 @@
|
||||
<?php
|
||||
class Model_Tag extends RedBean_SimpleModel
|
||||
{
|
||||
public static function locate($key)
|
||||
public static function locate($key, $throw = true)
|
||||
{
|
||||
$user = R::findOne('tag', 'name = ?', [$key]);
|
||||
if (!$user)
|
||||
throw new SimpleException('Invalid tag name "' . $key . '"');
|
||||
return $user;
|
||||
$tag = R::findOne('tag', 'LOWER(name) = LOWER(?)', [$key]);
|
||||
if (!$tag)
|
||||
{
|
||||
if ($throw)
|
||||
throw new SimpleException('Invalid tag name "' . $key . '"');
|
||||
return null;
|
||||
}
|
||||
return $tag;
|
||||
}
|
||||
|
||||
public static function insertOrUpdate($tags)
|
||||
@ -14,7 +18,7 @@ class Model_Tag extends RedBean_SimpleModel
|
||||
$dbTags = [];
|
||||
foreach ($tags as $tag)
|
||||
{
|
||||
$dbTag = R::findOne('tag', 'name = ?', [$tag]);
|
||||
$dbTag = self::locate($tag, false);
|
||||
if (!$dbTag)
|
||||
{
|
||||
$dbTag = R::dispense('tag');
|
||||
@ -37,7 +41,10 @@ class Model_Tag extends RedBean_SimpleModel
|
||||
if (strlen($tag) > $maxLength)
|
||||
throw new SimpleException('Tag must have at most ' . $maxLength . ' characters');
|
||||
|
||||
if (!preg_match('/^[a-zA-Z0-9_-]+$/i', $tag))
|
||||
if (!preg_match('/^[a-zA-Z0-9_.-]+$/i', $tag))
|
||||
throw new SimpleException('Invalid tag "' . $tag . '"');
|
||||
|
||||
if (preg_match('/^\.\.?$/', $tag))
|
||||
throw new SimpleException('Invalid tag "' . $tag . '"');
|
||||
|
||||
return $tag;
|
||||
|
@ -1,11 +1,15 @@
|
||||
<?php
|
||||
class Model_User extends RedBean_SimpleModel
|
||||
{
|
||||
public static function locate($key)
|
||||
public static function locate($key, $throw = true)
|
||||
{
|
||||
$user = R::findOne('user', 'name = ?', [$key]);
|
||||
if (!$user)
|
||||
throw new SimpleException('Invalid user name "' . $key . '"');
|
||||
{
|
||||
if ($throw)
|
||||
throw new SimpleException('Invalid user name "' . $key . '"');
|
||||
return null;
|
||||
}
|
||||
return $user;
|
||||
}
|
||||
|
||||
@ -37,29 +41,60 @@ class Model_User extends RedBean_SimpleModel
|
||||
$this->settings = $settings;
|
||||
}
|
||||
|
||||
public function update()
|
||||
{
|
||||
$context = \Chibi\Registry::getContext();
|
||||
if ($context->user->id == $this->id)
|
||||
{
|
||||
$context->user = $this;
|
||||
unset($_SESSION['user']);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
const SETTING_SAFETY = 1;
|
||||
const SETTING_ENDLESS_SCROLLING = 2;
|
||||
|
||||
public function hasEnabledSafety($safety)
|
||||
{
|
||||
return $this->getSetting('safety-' . $safety) !== false;
|
||||
$all = $this->getSetting(self::SETTING_SAFETY);
|
||||
if (!$all)
|
||||
return true;
|
||||
return $all & PostSafety::toFlag($safety);
|
||||
}
|
||||
|
||||
public function enableSafety($safety, $enabled)
|
||||
{
|
||||
$new = $this->getSetting(self::SETTING_SAFETY);
|
||||
if (!$enabled)
|
||||
{
|
||||
$this->setSetting('safety-' . $safety, false);
|
||||
$anythingEnabled = false;
|
||||
foreach (PostSafety::getAll() as $safety)
|
||||
if (self::hasEnabledSafety($safety))
|
||||
$anythingEnabled = true;
|
||||
if (!$anythingEnabled)
|
||||
$this->setSetting('safety-' . PostSafety::Safe, true);
|
||||
$new &= ~PostSafety::toFlag($safety);
|
||||
if (!$new)
|
||||
$new = PostSafety::toFlag(PostSafety::Safe);
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->setSetting('safety-' . $safety, true);
|
||||
$new |= PostSafety::toFlag($safety);
|
||||
}
|
||||
$this->setSetting(self::SETTING_SAFETY, $new);
|
||||
}
|
||||
|
||||
public function hasEnabledEndlessScrolling()
|
||||
{
|
||||
$ret = $this->getSetting(self::SETTING_ENDLESS_SCROLLING);
|
||||
if ($ret === null)
|
||||
$ret = \Chibi\Registry::getConfig()->browsing->endlessScrollingDefault;
|
||||
return $ret;
|
||||
}
|
||||
|
||||
public function enableEndlessScrolling($enabled)
|
||||
{
|
||||
$this->setSetting(self::SETTING_ENDLESS_SCROLLING, $enabled ? 1 : 0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static function validateUserName($userName)
|
||||
{
|
||||
$userName = trim($userName);
|
||||
@ -131,7 +166,7 @@ class Model_User extends RedBean_SimpleModel
|
||||
|
||||
public static function hashPassword($pass, $salt2)
|
||||
{
|
||||
$salt1 = \Chibi\Registry::getConfig()->registration->salt;
|
||||
$salt1 = \Chibi\Registry::getConfig()->main->salt;
|
||||
return sha1($salt1 . $salt2 . $pass);
|
||||
}
|
||||
|
||||
|
@ -4,4 +4,9 @@ class PostSafety extends Enum
|
||||
const Safe = 1;
|
||||
const Sketchy = 2;
|
||||
const Unsafe = 3;
|
||||
|
||||
public static function toFlag($safety)
|
||||
{
|
||||
return pow(2, $safety);
|
||||
}
|
||||
}
|
||||
|
@ -3,4 +3,5 @@ class PostType extends Enum
|
||||
{
|
||||
const Image = 1;
|
||||
const Flash = 2;
|
||||
const Youtube = 3;
|
||||
}
|
||||
|
@ -23,6 +23,7 @@ class Privilege extends Enum
|
||||
const ChangeUserAccessRank = 16;
|
||||
const ChangeUserEmail = 17;
|
||||
const ChangeUserName = 18;
|
||||
const ChangeUserSettings = 28;
|
||||
const DeleteUser = 19;
|
||||
|
||||
const ListComments = 20;
|
||||
|
@ -1,12 +1,11 @@
|
||||
<form action="<?php echo \Chibi\UrlHelper::route('auth', 'login') ?>" class="auth aligned" method="post">
|
||||
|
||||
<div>
|
||||
<p>If you don't have an account yet,<br/><a href="<?php echo \Chibi\UrlHelper::route('user', 'registration'); ?>">click here</a> to create a new one.</p>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label class="left" for="name">User name:</label>
|
||||
<div class="input-wrapper"><input id="name" name="name"/></div>
|
||||
<div class="input-wrapper"><input type="text" id="name" name="name"/></div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
@ -14,10 +13,20 @@
|
||||
<div class="input-wrapper"><input type="password" id="password" name="password"/></div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label class="left"> </label>
|
||||
<div class="input-wrapper">
|
||||
<input type="checkbox" name="remember" value="1"/>
|
||||
Remember me
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php if (isset($this->context->transport->errorMessage)): ?>
|
||||
<p class="alert alert-error">Error: <?php echo $this->context->transport->errorMessage ?></p>
|
||||
<?php endif ?>
|
||||
|
||||
<input type="hidden" name="submit" value="1"/>
|
||||
|
||||
<div>
|
||||
<label class="left"></label>
|
||||
<button type="submit">Log in</button>
|
||||
|
@ -4,6 +4,15 @@
|
||||
|
||||
<p>If you’re not a registered user, you will only see public (Safe) posts. Logging in to your account will enable you to filter content by its rating: Safe, Sketchy, and NSFW.</p>
|
||||
|
||||
<p>You can use your keyboard to navigate around the site. There are a few shortcuts:</p>
|
||||
|
||||
<ul>
|
||||
<li>focus search field: <code>[Q]</code></li>
|
||||
<li>scroll up/down: <code>[W]</code><span class="comma">, </span><code>[S]</code></li>
|
||||
<li>go to newer/older post or page: <code>[A]</code><span class="comma">, </span><code>[D]</code></li>
|
||||
<li>edit post: <code>[E]</code></li>
|
||||
</ul>
|
||||
|
||||
<h1>Search syntax</h1>
|
||||
|
||||
<ul>
|
||||
@ -12,10 +21,10 @@
|
||||
<li>uploaded by David: <a href="<?php echo \Chibi\UrlHelper::route('post', 'list', ['query' => 'submit:David']) ?>"><code>submit:David</code></a> (note no spaces)</li>
|
||||
<li>favorited by David: <a href="<?php echo \Chibi\UrlHelper::route('post', 'list', ['query' => 'fav:David']) ?>"><code>fav:David</code></a></li>
|
||||
<li>favorited by at least four users: <a href="<?php echo \Chibi\UrlHelper::route('post', 'list', ['query' => 'favmin:4']) ?>"><code>favmin:4</code></a></li>
|
||||
<li>exactly from the specified date: <a href="<?php echo \Chibi\UrlHelper::route('post', 'list', ['query' => 'date:2001']) ?>"><code>date:2001</code></a>, <a href="<?php echo \Chibi\UrlHelper::route('post', 'list', ['query' => 'date:2012-09-29']) ?>"><code>date:2012-09-29</code></a> (yyyy-mm-dd format)</li>
|
||||
<li>exactly from the specified date: <a href="<?php echo \Chibi\UrlHelper::route('post', 'list', ['query' => 'date:2001']) ?>"><code>date:2001</code></a><span class="comma">, </span><a href="<?php echo \Chibi\UrlHelper::route('post', 'list', ['query' => 'date:2012-09-29']) ?>"><code>date:2012-09-29</code></a> (yyyy-mm-dd format)</li>
|
||||
<li>from the specified date onwards: <a href="<?php echo \Chibi\UrlHelper::route('post', 'list', ['query' => 'datemin:2001-01-01']) ?>"><code>datemin:2001-01-01</code></a></li>
|
||||
<li>up to the specified date: <a href="<?php echo \Chibi\UrlHelper::route('post', 'list', ['query' => 'datemax:2004-07']) ?>"><code>datemax:2004-07</code></a></li>
|
||||
<li>by content type: <a href="<?php echo \Chibi\UrlHelper::route('post', 'list', ['query' => 'type:img']) ?>"><code>type:img</code></a>, <a href="<?php echo \Chibi\UrlHelper::route('post', 'list', ['query' => 'type:swf']) ?>"><code>type:swf</code></a> (images and flash files, respectively)</li>
|
||||
<li>by content type: <a href="<?php echo \Chibi\UrlHelper::route('post', 'list', ['query' => 'type:img']) ?>"><code>type:img</code></a><span class="comma">, </span><a href="<?php echo \Chibi\UrlHelper::route('post', 'list', ['query' => 'type:swf']) ?>"><code>type:swf</code></a> (images and flash files, respectively)</li>
|
||||
</ul>
|
||||
|
||||
<p>You can combine tags and negate any of them for interesting results. <a href="<?php echo \Chibi\UrlHelper::route('post', 'list', ['query' => 'sea -favmin:8 type:swf submit:Pirate']) ?>"><code>sea -favmin:8 type:swf submit:Pirate</code></a> will show you <strong>flash files</strong> tagged as <strong>sea</strong>, that were <strong>liked by seven people</strong> at most, uploaded by user <strong>Pirate</strong>.</p>
|
||||
@ -30,7 +39,7 @@
|
||||
<li>loved by most: <a href="<?php echo \Chibi\UrlHelper::route('post', 'list', ['query' => 'order:favs']) ?>"><code>order:favs</code></a></li>
|
||||
</ul>
|
||||
|
||||
<p>As shown with <a href="<?php echo \Chibi\UrlHelper::route('post', 'list', ['query' => 'order:date']) ?>"><code>order:date</code></a>, any of them can be reversed in the same way as negating other tags: by placing a dash before the tag.</p>
|
||||
<p>As shown with <a href="<?php echo \Chibi\UrlHelper::route('post', 'list', ['query' => '-order:date']) ?>"><code>-order:date</code></a><span class="comma">, </span>any of them can be reversed in the same way as negating other tags: by placing a dash before the tag.</p>
|
||||
|
||||
<h1>Registration</h1>
|
||||
|
||||
@ -38,6 +47,16 @@
|
||||
|
||||
<p>Oh, and you can delete your account at any time. Posts you uploaded will stay, unless some angry admin removes them.</p>
|
||||
|
||||
<h1>Comments</h1>
|
||||
|
||||
<p>Registered users can post comments. Comments support <a href="http://daringfireball.net/projects/markdown/syntax">Markdown syntax</a>, extended by some handy tags:</p>
|
||||
|
||||
<ul>
|
||||
<li>permalink to post number 426: <a href="<?php echo \Chibi\UrlHelper::route('post', 'view', ['id' => 426]) ?>"><code>@426</code></a></li>
|
||||
<li>link to tag "Dragon_Ball": <a href="<?php echo \Chibi\UrlHelper::route('post', 'list', ['query' => 'Dragon_Ball']) ?>"><code>#Dragon_Ball</code></a></li>
|
||||
<li>mark text as spoiler and hide it: <code class="spoiler">[spoiler]There is no spoon.[/spoiler]</code></li>
|
||||
</ul>
|
||||
|
||||
<h1>Uploads</h1>
|
||||
|
||||
<p>After registering, you gain the power to upload files to the service, for everyone else to see. Owners of the site are not responsible for content uploaded by users. You are not allowed to post any form of <a href="http://www.urbandictionary.com/define.php?term=cp">cp</a>. If you possess it, we ask you to leave immediately and never come back.</p>
|
||||
<p>After registering and activating your account, you gain the power to upload files to the service, for everyone else to see. Owners of the site are not responsible for content uploaded by users. You are not allowed to post any form of <a href="http://www.urbandictionary.com/define.php?term=cp">cp</a>. If you possess it, we ask you to leave immediately and never come back.</p>
|
||||
|
@ -1,53 +1,45 @@
|
||||
<div id="sidebar">
|
||||
<div id="welcome">
|
||||
<h1><?php echo $this->config->main->title ?></h1>
|
||||
|
||||
<form name="search" action="<?php echo \Chibi\UrlHelper::route('post', 'list') ?>" method="get">
|
||||
<input type="search" name="query" placeholder="Search…" value="<?php echo isset($this->context->transport->searchQuery) ? htmlspecialchars($this->context->transport->searchQuery) : '' ?>">
|
||||
</form>
|
||||
|
||||
<p>
|
||||
<span>serving <?php echo $this->context->transport->postCount ?> posts</span>
|
||||
<span>powered by <a href="<?php echo SZURU_LINK ?>">szurubooru</a></span>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<?php if (!empty($this->context->featuredPost)): ?>
|
||||
<div id="inner-content">
|
||||
<div class="header">
|
||||
Featured image
|
||||
<div class="header">
|
||||
Featured image
|
||||
|
||||
<ul class="tags">
|
||||
<?php foreach ($this->context->featuredPost->sharedTag as $tag): ?>
|
||||
<li>
|
||||
<a href="<?php echo \Chibi\UrlHelper::route('post', 'list', ['query' => $tag->name]) ?>">
|
||||
<?php echo $tag->name ?>
|
||||
</a>
|
||||
</li>
|
||||
<?php endforeach ?>
|
||||
</ul>
|
||||
|
||||
<span class="favs-comments">
|
||||
<?php printf('%d fav%s', $x = $this->context->featuredPost->countOwn('favoritee'), $x == 1 ? '' : 's') ?>, 
|
||||
<?php printf('%d comment%s', $x = $this->context->featuredPost->countOwn('comment'), $x == 1 ? '' : 's') ?>
|
||||
</span>
|
||||
<div class="clear"></div>
|
||||
</div>
|
||||
|
||||
<div class="body">
|
||||
<a href="<?php echo \Chibi\UrlHelper::route('post', 'view', ['id' => $this->context->featuredPost->id]) ?>">
|
||||
<img src="<?php echo \Chibi\UrlHelper::route('post', 'retrieve', ['name' => $this->context->featuredPost->name]) ?>" alt="<?php echo $this->context->featuredPost->name ?>"/>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="footer">
|
||||
Featured 
|
||||
<?php if ($this->context->featuredPostUser): ?>
|
||||
by <a href="<?php echo \Chibi\UrlHelper::route('user', 'view', ['name' => $this->context->featuredPostUser->name]) ?>"><?php echo $this->context->featuredPostUser->name ?></a>, 
|
||||
<?php endif ?>
|
||||
<?php printf('%d day%s', $x = round((time() - $this->context->featuredPostDate) / (24 * 3600.)), $x == 1 ? '' : 's') ?> ago
|
||||
<div class="clear"></div>
|
||||
</div>
|
||||
<ul class="tags">
|
||||
<?php foreach ($this->context->featuredPost->sharedTag as $tag): ?>
|
||||
<li>
|
||||
<a href="<?php echo \Chibi\UrlHelper::route('post', 'list', ['query' => $tag->name]) ?>">
|
||||
<?php echo $tag->name ?>
|
||||
</a>
|
||||
</li>
|
||||
<?php endforeach ?>
|
||||
</ul>
|
||||
|
||||
<span class="favs-comments">
|
||||
<?php printf('%d fav%s', $x = $this->context->featuredPost->countOwn('favoritee'), $x == 1 ? '' : 's') ?>, 
|
||||
<?php printf('%d comment%s', $x = $this->context->featuredPost->countOwn('comment'), $x == 1 ? '' : 's') ?>
|
||||
</span>
|
||||
<div class="clear"></div>
|
||||
</div>
|
||||
|
||||
<div class="body">
|
||||
<a href="<?php echo \Chibi\UrlHelper::route('post', 'view', ['id' => $this->context->featuredPost->id]) ?>">
|
||||
<img src="<?php echo \Chibi\UrlHelper::route('post', 'retrieve', ['name' => $this->context->featuredPost->name]) ?>" alt="<?php echo $this->context->featuredPost->name ?>"/>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="footer">
|
||||
Featured 
|
||||
<?php if ($this->context->featuredPostUser): ?>
|
||||
by <a href="<?php echo \Chibi\UrlHelper::route('user', 'view', ['name' => $this->context->featuredPostUser->name]) ?>"><?php echo $this->context->featuredPostUser->name ?></a>, 
|
||||
<?php endif ?>
|
||||
<?php printf('%d day%s', $x = round((time() - $this->context->featuredPostDate) / (24 * 3600.)), $x == 1 ? '' : 's') ?> ago
|
||||
<div class="clear"></div>
|
||||
</div>
|
||||
|
||||
<div class="clear"></div>
|
||||
<?php endif ?>
|
||||
|
@ -27,6 +27,9 @@
|
||||
if (PrivilegesHelper::confirm(Privilege::ListPosts))
|
||||
$nav []= ['Browse', \Chibi\UrlHelper::route('post', 'list')];
|
||||
|
||||
if (PrivilegesHelper::confirm(Privilege::ListPosts))
|
||||
$nav []= ['Random', \Chibi\UrlHelper::route('post', 'random')];
|
||||
|
||||
if (PrivilegesHelper::confirm(Privilege::ListPosts))
|
||||
$nav []= ['Favorites', \Chibi\UrlHelper::route('post', 'favorites')];
|
||||
|
||||
@ -82,7 +85,7 @@
|
||||
|
||||
<li class="search">
|
||||
<form name="search" action="<?php echo \Chibi\UrlHelper::route('post', 'list') ?>" method="get">
|
||||
<input type="search" name="query" placeholder="Search…" value="<?php echo isset($this->context->transport->searchQuery) ? htmlspecialchars($this->context->transport->searchQuery) : '' ?>">
|
||||
<input type="search" name="query" placeholder="Search…" value="<?php echo isset($this->context->transport->searchQuery) ? htmlspecialchars($this->context->transport->searchQuery) : '' ?>" data-autocomplete-url="<?php echo \Chibi\UrlHelper::route('tag', 'list') ?>"/>
|
||||
</form>
|
||||
</li>
|
||||
</ul>
|
||||
|
43
src/Views/post-edit.phtml
Normal file
43
src/Views/post-edit.phtml
Normal file
@ -0,0 +1,43 @@
|
||||
<form action="<?php echo \Chibi\UrlHelper::route('post', 'edit', ['id' => $this->context->transport->post->id]) ?>" method="post" enctype="multipart/form-data" class="edit-post aligned unit">
|
||||
<h1>edit post</h1>
|
||||
<?php if (PrivilegesHelper::confirm(Privilege::EditPostSafety, PrivilegesHelper::getIdentitySubPrivilege($this->context->transport->post->uploader))): ?>
|
||||
<div class="safety">
|
||||
<label class="left">Safety:</label>
|
||||
<?php foreach (PostSafety::getAll() as $safety): ?>
|
||||
<label>
|
||||
<input type="radio" name="safety" value="<?php echo $safety ?>" <?php if ($this->context->transport->post->safety == $safety) echo 'checked="checked"' ?>/>
|
||||
<?php echo TextHelper::camelCaseToHumanCase(PostSafety::toString($safety), true) ?>
|
||||
</label>
|
||||
<?php endforeach ?>
|
||||
</div>
|
||||
<?php endif ?>
|
||||
|
||||
<?php if (PrivilegesHelper::confirm(Privilege::EditPostTags, PrivilegesHelper::getIdentitySubPrivilege($this->context->transport->post->uploader))): ?>
|
||||
<div class="tags">
|
||||
<label class="left" for="tags">Tags:</label>
|
||||
<div class="input-wrapper"><input type="text" name="tags" id="tags" placeholder="enter some tags…" value="<?php echo join(',', array_map(function($tag) { return $tag->name; }, $this->context->transport->post->sharedTag)) ?>"/></div>
|
||||
</div>
|
||||
<input type="hidden" name="tags-token" id="tags-token" value="<?php echo $this->context->transport->tagsToken ?>"/>
|
||||
<?php endif ?>
|
||||
|
||||
<?php if (PrivilegesHelper::confirm(Privilege::EditPostSource, PrivilegesHelper::getIdentitySubPrivilege($this->context->transport->post->uploader))): ?>
|
||||
<div class="source">
|
||||
<label class="left" for="source">Source:</label>
|
||||
<div class="input-wrapper"><input type="text" name="source" id="source" value="<?php echo $this->context->transport->post->source ?>"/></div>
|
||||
</div>
|
||||
<?php endif ?>
|
||||
|
||||
<?php if (PrivilegesHelper::confirm(Privilege::EditPostThumb, PrivilegesHelper::getIdentitySubPrivilege($this->context->transport->post->uploader))): ?>
|
||||
<div class="thumb">
|
||||
<label class="left" for="thumb">Thumb:</label>
|
||||
<div class="input-wrapper"><input type="file" name="thumb" id="thumb"/></div>
|
||||
</div>
|
||||
<?php endif ?>
|
||||
|
||||
<input type="hidden" name="submit" value="1"/>
|
||||
|
||||
<div>
|
||||
<label class="left"> </label>
|
||||
<button type="submit">Submit</button>
|
||||
</div>
|
||||
</form>
|
@ -1,6 +1,6 @@
|
||||
<div class="post post-type-<?php echo TextHelper::camelCaseToHumanCase(PostType::toString($this->context->post->type)) ?>">
|
||||
<a href="<?php echo \Chibi\UrlHelper::route('post', 'view', ['id' => $this->context->post->id]) ?>">
|
||||
<img class="thumb" src="<?php echo \Chibi\UrlHelper::route('post', 'thumb', ['id' => $this->context->post->id]) ?>" alt="@<?php echo $this->context->post->id ?>"/>
|
||||
<img class="thumb" src="<?php echo \Chibi\UrlHelper::route('post', 'thumb', ['name' => $this->context->post->name]) ?>" alt="@<?php echo $this->context->post->id ?>"/>
|
||||
</a>
|
||||
<div class="info-bar">
|
||||
<i class="icon-comments"></i> <span><?php echo $this->context->post->countOwn('comment') ?></span>
|
||||
|
@ -14,11 +14,40 @@
|
||||
|
||||
<div id="inner-content">
|
||||
<div id="upload-step1">
|
||||
<input type=file multiple style="display: none"/>
|
||||
<div id="file-handler-wrapper">
|
||||
<div id="file-handler">
|
||||
Drop files here!<br>
|
||||
Or just click on this box.
|
||||
<div class="tabs">
|
||||
<nav>
|
||||
<ul>
|
||||
<li class="selected file">
|
||||
<a href="#">
|
||||
Upload from file
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<li class="url">
|
||||
<a href="#">
|
||||
Upload from URL
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
|
||||
<div class="tab file">
|
||||
<input type=file multiple style="display: none"/>
|
||||
<div id="file-handler-wrapper">
|
||||
<div id="file-handler">
|
||||
Drop files here!<br>
|
||||
Or just click on this box.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="tab url">
|
||||
<div id="url-handler-wrapper">
|
||||
<div id="url-handler">
|
||||
<div class="input-wrapper"><textarea placeholder="Paste some URLs here, one per line." name="urls"></textarea></div>
|
||||
</div>
|
||||
<button type="submit">Add</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -26,6 +55,8 @@
|
||||
</div>
|
||||
|
||||
<div id="upload-step2" data-redirect-url="<?php echo \Chibi\UrlHelper::route('post', 'list') ?>">
|
||||
<hr>
|
||||
|
||||
<div class="posts">
|
||||
</div>
|
||||
|
||||
@ -62,9 +93,14 @@
|
||||
|
||||
<div class="safety">
|
||||
<label class="left">Safety:</label>
|
||||
<label><input type="radio" name="safety" value="<?php echo PostSafety::Safe ?>" checked="checked"/> Safe for work</label>
|
||||
<label><input type="radio" name="safety" value="<?php echo PostSafety::Sketchy ?>"/> Sketchy</label>
|
||||
<label><input type="radio" name="safety" value="<?php echo PostSafety::Unsafe ?>"/> Not safe for work</label>
|
||||
<?php $checked = false ?>
|
||||
<?php foreach (PostSafety::getAll() as $safety): ?>
|
||||
<label>
|
||||
<input type="radio" name="safety" value="<?php echo $safety ?>"<?php if (!$checked) echo ' checked="checked"' ?>/>
|
||||
<?php echo TextHelper::camelCaseToHumanCase(PostSafety::toString($safety), true) ?>
|
||||
<?php $checked = true ?>
|
||||
</label>
|
||||
<?php endforeach ?>
|
||||
</div>
|
||||
|
||||
<div class="tags">
|
||||
@ -76,14 +112,11 @@
|
||||
<label class="left">Source:</label>
|
||||
<div class="input-wrapper"><input type="text" name="source" placeholder="where did you get this from? (optional)"/></div>
|
||||
</div>
|
||||
|
||||
<input type="hidden" name="submit" value="1"/>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="upload-no-posts">
|
||||
<p class="alert alert-warning">Well, that’s disappointing…</p>
|
||||
<p><a href="<?php echo \Chibi\UrlHelper::route('post', 'list') ?>">Back to post list</a> or <a href="<?php echo \Chibi\UrlHelper::route('post', 'upload') ?>">try uploading again</a>.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php endif ?>
|
||||
|
@ -29,7 +29,7 @@
|
||||
<h1>tags (<?php echo count($this->context->transport->post->sharedTag) ?>)</h1>
|
||||
<ul>
|
||||
<?php foreach ($this->context->transport->post->sharedTag as $tag): ?>
|
||||
<li>
|
||||
<li title="<?php echo $tag->name ?>">
|
||||
<a href="<?php echo \Chibi\UrlHelper::route('post', 'list', ['query' => $tag->name]) ?>">
|
||||
<?php echo $tag->name ?>
|
||||
</a>
|
||||
@ -44,18 +44,12 @@
|
||||
<div class="unit details">
|
||||
<h1>details</h1>
|
||||
|
||||
<div class="key-value safety">
|
||||
<span class="key">Safety:</span>
|
||||
<span class="value" title="<?php echo $val = TextHelper::camelCaseToHumanCase(PostSafety::toString($this->context->transport->post->safety)) ?>">
|
||||
<?php echo $val ?>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="key-value uploader">
|
||||
<span class="key">Uploader:</span>
|
||||
<?php if ($this->context->transport->post->uploader): ?>
|
||||
<span class="value" title="<?php echo $val = $this->context->transport->post->uploader->name ?>">
|
||||
<a href="<?php echo \Chibi\UrlHelper::route('user', 'view', ['name' => $this->context->transport->post->uploader->name]) ?>">
|
||||
<img src="<?php echo htmlentities($this->context->transport->post->uploader->getAvatarUrl(16)) ?>" alt="<?php echo $this->context->transport->post->uploader->name ?>"/>
|
||||
<?php echo $val ?>
|
||||
</a>
|
||||
</span>
|
||||
@ -66,6 +60,13 @@
|
||||
<?php endif ?>
|
||||
</div>
|
||||
|
||||
<div class="key-value safety">
|
||||
<span class="key">Safety:</span>
|
||||
<span class="value" title="<?php echo $val = TextHelper::camelCaseToHumanCase(PostSafety::toString($this->context->transport->post->safety)) ?>">
|
||||
<?php echo $val ?>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="key-value date">
|
||||
<span class="key">Date:</span>
|
||||
<span class="value" title="<?php echo $val = date('Y-m-d H:i', $this->context->transport->post->upload_date) ?>">
|
||||
@ -91,17 +92,21 @@
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="permalink">
|
||||
<a href="<?php echo \Chibi\UrlHelper::route('post', 'retrieve', ['name' => $this->context->transport->post->name]) ?>" title="Download">
|
||||
<i class="icon-dl"></i>
|
||||
<span class="ext">
|
||||
<?php echo strtoupper(substr($this->context->transport->post->orig_name, strrpos($this->context->transport->post->orig_name, '.') + 1)) ?>
|
||||
</span>
|
||||
<span class="size">
|
||||
<?php echo TextHelper::useBytesUnits($this->context->transport->post->file_size) ?>
|
||||
</span>
|
||||
</a>
|
||||
</div>
|
||||
<?php if ($this->context->transport->post->type != PostType::Youtube): ?>
|
||||
<div class="permalink">
|
||||
<a href="<?php echo \Chibi\UrlHelper::route('post', 'retrieve', ['name' => $this->context->transport->post->name]) ?>" title="Download">
|
||||
<i class="icon-dl"></i>
|
||||
<span class="ext">
|
||||
<?php $mimes = ['image/jpeg' => 'JPG', 'image/gif' => 'GIF', 'image/png' => 'PNG', 'application/x-shockwave-flash' => 'SWF'] ?>
|
||||
<?php $mime = $this->context->transport->post->mimeType ?>
|
||||
<?php echo isset($mimes[$mime]) ? $mimes[$mime] : 'unknown' ?>
|
||||
</span>
|
||||
<span class="size">
|
||||
<?php echo TextHelper::useBytesUnits($this->context->transport->post->file_size) ?>
|
||||
</span>
|
||||
</a>
|
||||
</div>
|
||||
<?php endif ?>
|
||||
</div>
|
||||
|
||||
<div class="unit favorites">
|
||||
@ -208,55 +213,21 @@
|
||||
|
||||
<div id="inner-content">
|
||||
<div class="post-wrapper post-type-<?php echo strtolower(PostType::toString($this->context->transport->post->type)) ?>">
|
||||
<?php if ($this->context->transport->post->type == PostType::Image): ?>
|
||||
<img src="<?php echo \Chibi\UrlHelper::route('post', 'retrieve', ['name' => $this->context->transport->post->name]) ?>" alt="<?php echo $this->context->transport->post->name ?>"/>
|
||||
<?php elseif ($this->context->transport->post->type == PostType::Flash): ?>
|
||||
<embed width="<?php echo $this->context->transport->post->image_width ?>" height="<?php echo $this->context->transport->post->image_height ?>" type="application/x-shockwave-flash" src="<?php echo \Chibi\UrlHelper::route('post', 'retrieve', ['name' => $this->context->transport->post->name]) ?>"/>
|
||||
<?php endif ?>
|
||||
<?php switch ($this->context->transport->post->type):
|
||||
case PostType::Image: ?>
|
||||
<img src="<?php echo \Chibi\UrlHelper::route('post', 'retrieve', ['name' => $this->context->transport->post->name]) ?>" alt="<?php echo $this->context->transport->post->name ?>"/>
|
||||
<?php break ?>
|
||||
<?php case PostType::Flash: ?>
|
||||
<embed width="<?php echo $this->context->transport->post->image_width ?>" height="<?php echo $this->context->transport->post->image_height ?>" type="application/x-shockwave-flash" src="<?php echo \Chibi\UrlHelper::route('post', 'retrieve', ['name' => $this->context->transport->post->name]) ?>"/>
|
||||
<?php break ?>
|
||||
<?php case PostType::Youtube: ?>
|
||||
<iframe width="800" height="600" src="//www.youtube.com/embed/<?php echo $this->context->transport->post->orig_name ?>" frameborder="0" allowfullscreen></iframe>
|
||||
<?php break ?>
|
||||
<?php endswitch ?>
|
||||
</div>
|
||||
|
||||
<?php if ($canEditAnything): ?>
|
||||
<form action="<?php echo \Chibi\UrlHelper::route('post', 'edit', ['id' => $this->context->transport->post->id]) ?>" method="post" enctype="multipart/form-data" class="edit-post aligned unit">
|
||||
<h1>edit post</h1>
|
||||
<?php if ($editPostPrivileges[Privilege::EditPostSafety]): ?>
|
||||
<div class="safety">
|
||||
<label class="left">Safety:</label>
|
||||
<?php foreach (PostSafety::getAll() as $safety): ?>
|
||||
<label>
|
||||
<input type="radio" name="safety" value="<?php echo $safety ?>" <?php if ($this->context->transport->post->safety == $safety) echo 'checked="checked"' ?>/>
|
||||
<?php echo TextHelper::camelCaseToHumanCase(PostSafety::toString($safety), true) ?>
|
||||
</label>
|
||||
<?php endforeach ?>
|
||||
</div>
|
||||
<?php endif ?>
|
||||
|
||||
<?php if ($editPostPrivileges[Privilege::EditPostTags]): ?>
|
||||
<div class="tags">
|
||||
<label class="left" for="tags">Tags:</label>
|
||||
<div class="input-wrapper"><input type="text" name="tags" id="tags" placeholder="enter some tags…" value="<?php echo join(',', array_map(function($tag) { return $tag->name; }, $this->context->transport->post->sharedTag)) ?>"/></div>
|
||||
</div>
|
||||
<input type="hidden" name="tags-token" id="tags-token" value="<?php echo $this->context->transport->tagsToken ?>"/>
|
||||
<?php endif ?>
|
||||
|
||||
<?php if ($editPostPrivileges[Privilege::EditPostSource]): ?>
|
||||
<div class="source">
|
||||
<label class="left" for="source">Source:</label>
|
||||
<div class="input-wrapper"><input type="text" name="source" id="suorce" value="<?php echo $this->context->transport->post->source ?>"/></div>
|
||||
</div>
|
||||
<?php endif ?>
|
||||
|
||||
<?php if ($editPostPrivileges[Privilege::EditPostThumb]): ?>
|
||||
<div class="thumb">
|
||||
<label class="left" for="thumb">Thumb:</label>
|
||||
<div class="input-wrapper"><input type="file" name="thumb" id="thumb"/></div>
|
||||
</div>
|
||||
<?php endif ?>
|
||||
|
||||
<div>
|
||||
<label class="left"> </label>
|
||||
<button type="submit">Submit</button>
|
||||
</div>
|
||||
</form>
|
||||
<?php $this->renderFile('post-edit') ?>
|
||||
<?php endif ?>
|
||||
|
||||
<div class="comments unit">
|
||||
|
@ -1,8 +1,9 @@
|
||||
<?php $max = max($this->context->transport->tagDistribution) ?>
|
||||
<div class="tags">
|
||||
<ul>
|
||||
<?php foreach ($this->context->transport->tagDistribution as $tagName => $count): ?>
|
||||
<li class="tag">
|
||||
<a href="<?php echo \Chibi\UrlHelper::route('post', 'list', ['query' => $tagName]) ?>">
|
||||
<li class="tag" title="<?php echo $tagName ?> (<?php echo $count ?>)">
|
||||
<a href="<?php echo \Chibi\UrlHelper::route('post', 'list', ['query' => $tagName]) ?>" style="opacity: <?php printf('%.02f', 0.25 + 0.75 * log($count) / log($max)) ?>">
|
||||
<?php echo $tagName . ' (' . $count . ')' ?>
|
||||
</a>
|
||||
</li>
|
||||
@ -24,6 +25,8 @@
|
||||
<div class="input-wrapper"><input type="text" name="target-tag" id="merge-target-tag"></div>
|
||||
</div>
|
||||
|
||||
<input type="hidden" name="submit" value="1"/>
|
||||
|
||||
<div>
|
||||
<label class="left"> </label>
|
||||
<button type="submit">Merge!</button>
|
||||
@ -46,6 +49,8 @@
|
||||
<div class="input-wrapper"><input type="text" name="target-tag" id="rename-target-tag"></div>
|
||||
</div>
|
||||
|
||||
<input type="hidden" name="submit" value="1"/>
|
||||
|
||||
<div>
|
||||
<label class="left"> </label>
|
||||
<button type="submit">Rename!</button>
|
||||
|
21
src/Views/user-delete.phtml
Normal file
21
src/Views/user-delete.phtml
Normal file
@ -0,0 +1,21 @@
|
||||
<form action="<?php echo \Chibi\UrlHelper::route('user', 'delete', ['name' => $this->context->transport->user->name]) ?>" method="post" class="delete aligned" autocomplete="off" data-confirm-text="Are you sure you want to delete your account?">
|
||||
<?php if ($this->context->user->id == $this->context->transport->user->id): ?>
|
||||
<div class="current-password">
|
||||
<label class="left" for="current-password">Current password:</label>
|
||||
<div class="input-wrapper"><input type="password" name="current-password" id="current-password" placeholder="Current password"/></div>
|
||||
</div>
|
||||
<?php endif ?>
|
||||
|
||||
<input type="hidden" name="submit" value="1"/>
|
||||
|
||||
<?php if ($this->context->transport->success === true): ?>
|
||||
<p class="alert alert-success">Account settings updated!</p>
|
||||
<?php elseif (isset($this->context->transport->errorMessage)): ?>
|
||||
<p class="alert alert-error">Error: <?php echo $this->context->transport->errorMessage ?></p>
|
||||
<?php endif ?>
|
||||
|
||||
<div>
|
||||
<label class="left"> </label>
|
||||
<button type="submit">Delete account</button>
|
||||
</div>
|
||||
</form>
|
65
src/Views/user-edit.phtml
Normal file
65
src/Views/user-edit.phtml
Normal file
@ -0,0 +1,65 @@
|
||||
<form action="<?php echo \Chibi\UrlHelper::route('user', 'edit', ['name' => $this->context->transport->user->name]) ?>" method="post" class="edit aligned" autocomplete="off">
|
||||
<?php if ($this->context->user->id == $this->context->transport->user->id): ?>
|
||||
<div class="current-password">
|
||||
<label class="left" for="current-password">Current password:</label>
|
||||
<div class="input-wrapper"><input type="password" name="current-password" id="current-password" placeholder="Current password"/></div>
|
||||
</div>
|
||||
<hr>
|
||||
<?php endif ?>
|
||||
|
||||
<?php if (PrivilegesHelper::confirm(Privilege::ChangeUserName, PrivilegesHelper::getIdentitySubPrivilege($this->context->transport->user))): ?>
|
||||
<div class="nickname">
|
||||
<label class="left" for="name">Name:</label>
|
||||
<div class="input-wrapper"><input type="text" name="name" id="name" placeholder="New name…" value="<?php echo $this->context->suppliedName ?>"/></div>
|
||||
</div>
|
||||
<?php endif ?>
|
||||
|
||||
<?php if (PrivilegesHelper::confirm(Privilege::ChangeUserEmail, PrivilegesHelper::getIdentitySubPrivilege($this->context->transport->user))): ?>
|
||||
<div class="email">
|
||||
<label class="left" for="name">E-mail:</label>
|
||||
<div class="input-wrapper"><input type="text" name="email" id="email" placeholder="New e-mail…" value="<?php echo $this->context->suppliedEmail ?>"/></div>
|
||||
</div>
|
||||
<?php endif ?>
|
||||
|
||||
<?php if (PrivilegesHelper::confirm(Privilege::ChangeUserPassword, PrivilegesHelper::getIdentitySubPrivilege($this->context->transport->user))): ?>
|
||||
<div class="password1">
|
||||
<label class="left" for="password1">New password:</label>
|
||||
<div class="input-wrapper"><input type="password" name="password1" id="password1" placeholder="New password…" value="<?php echo $this->context->suppliedPassword1 ?>"/></div>
|
||||
</div>
|
||||
<div class="password2">
|
||||
<label class="left" for="password2"></label>
|
||||
<div class="input-wrapper"><input type="password" name="password2" id="password2" placeholder="New password… (repeat)" value="<?php echo $this->context->suppliedPassword2 ?>"/></div>
|
||||
</div>
|
||||
<?php endif ?>
|
||||
|
||||
<?php if (PrivilegesHelper::confirm(Privilege::ChangeUserAccessRank, PrivilegesHelper::getIdentitySubPrivilege($this->context->transport->user))): ?>
|
||||
<div class="access-rank">
|
||||
<label class="left" for="access-rank">Access rank:</label>
|
||||
<div class="input-wrapper"><select name="access-rank" id="access-rank">
|
||||
<?php foreach (AccessRank::getAll() as $rank): ?>
|
||||
<?php if ($rank == AccessRank::Nobody) continue ?>
|
||||
<?php if (($this->context->suppliedAccessRank != '' and $rank == $this->context->suppliedAccessRank) or ($this->context->suppliedAccessRank == '' and $rank == $this->context->transport->user->access_rank)): ?>
|
||||
<option value="<?php echo $rank ?>" selected="selected">
|
||||
<?php else: ?>
|
||||
<option value="<?php echo $rank ?>">
|
||||
<?php endif ?>
|
||||
<?php echo TextHelper::camelCaseToHumanCase(AccessRank::toString($rank)) ?>
|
||||
</option>
|
||||
<?php endforeach ?>
|
||||
</select></div>
|
||||
</div>
|
||||
<?php endif ?>
|
||||
|
||||
<input type="hidden" name="submit" value="1"/>
|
||||
|
||||
<?php if ($this->context->transport->success === true): ?>
|
||||
<p class="alert alert-success">Account settings updated! <?php if (!empty($this->context->mailSent)) echo 'You will be sent new e-mail address confirmation message soon.' ?></p>
|
||||
<?php elseif (isset($this->context->transport->errorMessage)): ?>
|
||||
<p class="alert alert-error">Error: <?php echo $this->context->transport->errorMessage ?></p>
|
||||
<?php endif ?>
|
||||
|
||||
<div>
|
||||
<label class="left"> </label>
|
||||
<button type="submit">Submit</button>
|
||||
</div>
|
||||
</form>
|
@ -16,7 +16,7 @@
|
||||
|
||||
<div>
|
||||
<label class="left" for="name">User name:</label>
|
||||
<div class="input-wrapper"><input id="name" name="name" value="<?php echo $this->context->suppliedName ?>" placeholder="e.g. darth_vader" autocomplete="off"/></div>
|
||||
<div class="input-wrapper"><input type="text" id="name" name="name" value="<?php echo $this->context->suppliedName ?>" placeholder="e.g. darth_vader" autocomplete="off"/></div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
@ -31,7 +31,7 @@
|
||||
|
||||
<div>
|
||||
<label class="left" for="email">E-mail address:</label>
|
||||
<div class="input-wrapper"><input id="email" name="email" value="<?php echo $this->context->suppliedEmail ?>" placeholder="e.g. vader@empire.gov" autocomplete="off"/></div>
|
||||
<div class="input-wrapper"><input type="text" id="email" name="email" value="<?php echo $this->context->suppliedEmail ?>" placeholder="e.g. vader@empire.gov" autocomplete="off"/></div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
@ -44,6 +44,8 @@
|
||||
</div>
|
||||
<?php endif ?>
|
||||
|
||||
<input type="hidden" name="submit" value="1"/>
|
||||
|
||||
<div>
|
||||
<label class="left"></label>
|
||||
<button type="submit">Register</button>
|
||||
|
37
src/Views/user-settings.phtml
Normal file
37
src/Views/user-settings.phtml
Normal file
@ -0,0 +1,37 @@
|
||||
<form action="<?php echo \Chibi\UrlHelper::route('user', 'settings', ['name' => $this->context->transport->user->name]) ?>" method="post" class="settings aligned">
|
||||
<div class="safety">
|
||||
<label class="left" for="name">Safety:</label>
|
||||
<div class="input-wrapper">
|
||||
<?php foreach (PostSafety::getAll() as $safety): ?>
|
||||
<?php if (PrivilegesHelper::confirm(Privilege::ListPosts, PostSafety::toString($safety))): ?>
|
||||
<label><input type="checkbox" name="safety[]" value="<?php echo $safety ?>"<?php if ($this->context->transport->user->hasEnabledSafety($safety)) echo ' checked="checked"' ?>/>
|
||||
<?php echo TextHelper::camelCaseToHumanCase(PostSafety::toString($safety), true) ?></label>
|
||||
<?php endif ?>
|
||||
<?php endforeach ?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="endless-scrolling">
|
||||
<label class="left" for="name">Endless scrolling:</label>
|
||||
<div class="input-wrapper">
|
||||
<label>
|
||||
<input type="checkbox" name="endless-scrolling" <?php if ($this->context->transport->user->hasEnabledEndlessScrolling()) echo ' checked="checked"' ?>/>
|
||||
Enabled
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<input type="hidden" name="submit" value="1"/>
|
||||
|
||||
<?php if ($this->context->transport->success === true): ?>
|
||||
<p class="alert alert-success">Browsing settings updated!</p>
|
||||
<?php elseif (isset($this->context->transport->errorMessage)): ?>
|
||||
<p class="alert alert-error">Error: <?php echo $this->context->transport->errorMessage ?></p>
|
||||
<?php endif ?>
|
||||
|
||||
<div>
|
||||
<label class="left"> </label>
|
||||
<button type="submit">Update settings</button>
|
||||
</div>
|
||||
</form>
|
||||
|
@ -19,7 +19,7 @@
|
||||
<span class="value" title="<?php echo $val = TextHelper::camelCaseToHumanCase(AccessRank::toString($this->context->transport->user->access_rank)) ?>"><?php echo $val ?></span>
|
||||
</div>
|
||||
|
||||
<?php if (PrivilegesHelper::confirm(Privilege::ViewUserEmail)): ?>
|
||||
<?php if (PrivilegesHelper::confirm(Privilege::ViewUserEmail, PrivilegesHelper::getIdentitySubPrivilege($this->context->transport->user))): ?>
|
||||
<div class="key-value email">
|
||||
<span class="key">E-mail:</span>
|
||||
<span class="value" title="<?php echo $val = ($this->context->transport->user->email_unconfirmed ? '(unconfirmed) ' . $this->context->transport->user->email_unconfirmed : $this->context->transport->user->email_confirmed ?: 'none specified') ?>"><?php echo $val ?></span>
|
||||
@ -121,6 +121,18 @@
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<?php if (PrivilegesHelper::confirm(Privilege::ChangeUserSettings, PrivilegesHelper::getIdentitySubPrivilege($this->context->transport->user))): ?>
|
||||
<?php if ($this->context->transport->tab == 'settings'): ?>
|
||||
<li class="selected settings">
|
||||
<?php else: ?>
|
||||
<li class="settings">
|
||||
<?php endif ?>
|
||||
<a href="<?php echo \Chibi\UrlHelper::route('user', 'settings', ['name' => $this->context->transport->user->name]) ?>">
|
||||
Browsing settings
|
||||
</a>
|
||||
</li>
|
||||
<?php endif ?>
|
||||
|
||||
<?php if ($canModifyAnything): ?>
|
||||
<?php if ($this->context->transport->tab == 'edit'): ?>
|
||||
<li class="selected edit">
|
||||
@ -152,95 +164,12 @@
|
||||
<?php $this->renderFile('post-list') ?>
|
||||
<?php endif ?>
|
||||
|
||||
<?php if ($this->context->transport->tab == 'edit'): ?>
|
||||
<form action="<?php echo \Chibi\UrlHelper::route('user', 'edit', ['name' => $this->context->transport->user->name]) ?>" method="post" class="edit aligned" autocomplete="off">
|
||||
<?php if ($this->context->user->id == $this->context->transport->user->id): ?>
|
||||
<div class="current-password">
|
||||
<label class="left" for="current-password">Current password:</label>
|
||||
<div class="input-wrapper"><input type="password" name="current-password" id="current-password" placeholder="Current password"/></div>
|
||||
</div>
|
||||
<hr>
|
||||
<?php endif ?>
|
||||
|
||||
<?php if (PrivilegesHelper::confirm(Privilege::ChangeUserName, PrivilegesHelper::getIdentitySubPrivilege($this->context->transport->user))): ?>
|
||||
<div class="nickname">
|
||||
<label class="left" for="name">Name:</label>
|
||||
<div class="input-wrapper"><input type="text" name="name" id="name" placeholder="New name…" value="<?php echo $this->context->suppliedName ?>"/></div>
|
||||
</div>
|
||||
<?php endif ?>
|
||||
|
||||
<?php if (PrivilegesHelper::confirm(Privilege::ChangeUserEmail, PrivilegesHelper::getIdentitySubPrivilege($this->context->transport->user))): ?>
|
||||
<div class="email">
|
||||
<label class="left" for="name">E-mail:</label>
|
||||
<div class="input-wrapper"><input type="text" name="email" id="email" placeholder="New e-mail…" value="<?php echo $this->context->suppliedEmail ?>"/></div>
|
||||
</div>
|
||||
<?php endif ?>
|
||||
|
||||
<?php if (PrivilegesHelper::confirm(Privilege::ChangeUserPassword, PrivilegesHelper::getIdentitySubPrivilege($this->context->transport->user))): ?>
|
||||
<div class="password1">
|
||||
<label class="left" for="password1">New password:</label>
|
||||
<div class="input-wrapper"><input type="password" name="password1" id="password1" placeholder="New password…" value="<?php echo $this->context->suppliedPassword1 ?>"/></div>
|
||||
</div>
|
||||
<div class="password2">
|
||||
<label class="left" for="password2"></label>
|
||||
<div class="input-wrapper"><input type="password" name="password2" id="password2" placeholder="New password… (repeat)" value="<?php echo $this->context->suppliedPassword2 ?>"/></div>
|
||||
</div>
|
||||
<?php endif ?>
|
||||
|
||||
<?php if (PrivilegesHelper::confirm(Privilege::ChangeUserAccessRank, PrivilegesHelper::getIdentitySubPrivilege($this->context->transport->user))): ?>
|
||||
<div class="access-rank">
|
||||
<label class="left" for="access-rank">Access rank:</label>
|
||||
<div class="input-wrapper"><select name="access-rank" id="access-rank">
|
||||
<?php foreach (AccessRank::getAll() as $rank): ?>
|
||||
<?php if ($rank == AccessRank::Nobody) continue ?>
|
||||
<?php if (($this->context->suppliedAccessRank != '' and $rank == $this->context->suppliedAccessRank) or ($this->context->suppliedAccessRank == '' and $rank == $this->context->transport->user->access_rank)): ?>
|
||||
<option value="<?php echo $rank ?>" selected="selected">
|
||||
<?php else: ?>
|
||||
<option value="<?php echo $rank ?>">
|
||||
<?php endif ?>
|
||||
<?php echo TextHelper::camelCaseToHumanCase(AccessRank::toString($rank)) ?>
|
||||
</option>
|
||||
<?php endforeach ?>
|
||||
</select></div>
|
||||
</div>
|
||||
<?php endif ?>
|
||||
|
||||
<?php if ($this->context->transport->success === true): ?>
|
||||
<p class="alert alert-success">Account settings updated! <?php if (!empty($this->context->mailSent)) echo 'You will be sent new e-mail address confirmation message soon.' ?></p>
|
||||
<?php elseif (isset($this->context->transport->errorMessage)): ?>
|
||||
<p class="alert alert-error">Error: <?php echo $this->context->transport->errorMessage ?></p>
|
||||
<?php endif ?>
|
||||
|
||||
<div>
|
||||
<label class="left"> </label>
|
||||
<button type="submit">Submit</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<?php if ($this->context->transport->tab == 'settings'): ?>
|
||||
<?php $this->renderFile('user-settings') ?>
|
||||
<?php elseif ($this->context->transport->tab == 'edit'): ?>
|
||||
<?php $this->renderFile('user-edit') ?>
|
||||
<?php elseif ($this->context->transport->tab == 'delete'): ?>
|
||||
|
||||
<form action="<?php echo \Chibi\UrlHelper::route('user', 'delete', ['name' => $this->context->transport->user->name]) ?>" method="post" class="edit aligned" autocomplete="off" data-confirm-text="Are you sure you want to delete your account?">
|
||||
<?php if ($this->context->user->id == $this->context->transport->user->id): ?>
|
||||
<div class="current-password">
|
||||
<label class="left" for="current-password">Current password:</label>
|
||||
<div class="input-wrapper"><input type="password" name="current-password" id="current-password" placeholder="Current password"/></div>
|
||||
</div>
|
||||
<?php endif ?>
|
||||
|
||||
<input type="hidden" name="remove" value="1"/>
|
||||
|
||||
<?php if ($this->context->transport->success === true): ?>
|
||||
<p class="alert alert-success">Account settings updated!</p>
|
||||
<?php elseif (isset($this->context->transport->errorMessage)): ?>
|
||||
<p class="alert alert-error">Error: <?php echo $this->context->transport->errorMessage ?></p>
|
||||
<?php endif ?>
|
||||
|
||||
<div>
|
||||
<label class="left"> </label>
|
||||
<button type="submit">Delete account</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<?php $this->renderFile('user-delete') ?>
|
||||
<?php endif ?>
|
||||
|
||||
</div>
|
||||
|
@ -1,5 +1,5 @@
|
||||
<?php
|
||||
define('SZURU_VERSION', '0.1.0');
|
||||
define('SZURU_VERSION', '0.2.0');
|
||||
define('SZURU_LINK', 'http://github.com/rr-/szurubooru');
|
||||
|
||||
function trueStartTime()
|
||||
|
Reference in New Issue
Block a user