add server-side filesize check on uploads

This commit is contained in:
Régis Hanol 2013-07-24 00:54:18 +02:00
parent 75491d2cf6
commit be9217d4c8
34 changed files with 114 additions and 97 deletions

View File

@ -163,41 +163,55 @@ Discourse.Utilities = {
/** /**
Validate a list of files to be uploaded Validate a list of files to be uploaded
@method validateFilesForUpload @method validateUploadedFiles
@param {Array} files The list of files we want to upload @param {Array} files The list of files we want to upload
**/ **/
validateFilesForUpload: function(files) { validateUploadedFiles: function(files) {
if (!files || files.length === 0) { return false; } if (!files || files.length === 0) { return false; }
// can only upload one file at a time // can only upload one file at a time
if (files.length > 1) { if (files.length > 1) {
bootbox.alert(I18n.t('post.errors.too_many_uploads')); bootbox.alert(I18n.t('post.errors.too_many_uploads'));
return false; return false;
} }
var upload = files[0]; var upload = files[0];
// ensures that new users can upload image/attachment
if (Discourse.Utilities.isUploadForbidden(upload.name)) { // CHROME ONLY: if the image was pasted, sets its name to a default one
if (Discourse.Utilities.isAnImage(upload.name)) {
bootbox.alert(I18n.t('post.errors.image_upload_not_allowed_for_new_user'));
} else {
bootbox.alert(I18n.t('post.errors.attachment_upload_not_allowed_for_new_user'));
}
return false;
}
// if the image was pasted, sets its name to a default one
if (upload instanceof Blob && !(upload instanceof File) && upload.type === "image/png") { upload.name = "blob.png"; } if (upload instanceof Blob && !(upload instanceof File) && upload.type === "image/png") { upload.name = "blob.png"; }
return Discourse.Utilities.validateUploadedFile(upload, Discourse.Utilities.isAnImage(upload.name) ? 'image' : 'attachment');
},
/**
Validate a file to be uploaded
@method validateUploadedFile
@param {File} file The file to be uploaded
@param {string} type The type of the file
**/
validateUploadedFile: function(file, type) {
// check that the uploaded file is authorized // check that the uploaded file is authorized
if (!Discourse.Utilities.isAuthorizedUpload(upload)) { if (!Discourse.Utilities.isAuthorizedUpload(file)) {
var extensions = Discourse.SiteSettings.authorized_extensions.replace(/\|/g, ", "); var extensions = Discourse.SiteSettings.authorized_extensions.replace(/\|/g, ", ");
bootbox.alert(I18n.t('post.errors.upload_not_authorized', { authorized_extensions: extensions })); bootbox.alert(I18n.t('post.errors.upload_not_authorized', { authorized_extensions: extensions }));
return false; return false;
} }
// check file size
var fileSizeKB = upload.size / 1024; // ensures that new users can upload a file
var maxSizeKB = Discourse.Utilities.maxUploadSizeInKB(upload.name); if (Discourse.User.current('trust_level') === 0 && Discourse.SiteSettings['newuser_max_' + type + 's'] === 0) {
if (fileSizeKB > maxSizeKB) { bootbox.alert(I18n.t('post.errors.' + type + '_upload_not_allowed_for_new_user'));
bootbox.alert(I18n.t('post.errors.upload_too_large', { max_size_kb: maxSizeKB }));
return false; return false;
} }
// check file size
var fileSizeKB = file.size / 1024;
var maxSizeKB = Discourse.SiteSettings['max_' + type + '_size_kb'];
if (fileSizeKB > maxSizeKB) {
bootbox.alert(I18n.t('post.errors.' + type + '_too_large', { max_size_kb: maxSizeKB }));
return false;
}
// everything went fine // everything went fine
return true; return true;
}, },
@ -238,27 +252,6 @@ Discourse.Utilities = {
return path && path.match(/\.(png|jpg|jpeg|gif|bmp|tif|tiff)$/i); return path && path.match(/\.(png|jpg|jpeg|gif|bmp|tif|tiff)$/i);
}, },
/**
Retrieve max upload size in KB depending on the file is an image or not
@method maxUploadSizeInKB
@param {String} path The path
**/
maxUploadSizeInKB: function(path) {
return Discourse.Utilities.isAnImage(path) ? Discourse.SiteSettings.max_image_size_kb : Discourse.SiteSettings.max_attachment_size_kb;
},
/**
Test whether an upload is forbidden or not
@method isUploadForbidden
@param {String} path The path
**/
isUploadForbidden: function(path) {
if (Discourse.User.current('trust_level') > 0) { return false; }
return Discourse.Utilities.isAnImage(path) ? Discourse.SiteSettings.newuser_max_images === 0 : Discourse.SiteSettings.newuser_max_attachments === 0;
},
/** /**
Determines whether we allow attachments or not Determines whether we allow attachments or not

View File

@ -252,7 +252,7 @@ Discourse.ComposerView = Discourse.View.extend({
// submit - this event is triggered for each upload // submit - this event is triggered for each upload
$uploadTarget.on('fileuploadsubmit', function (e, data) { $uploadTarget.on('fileuploadsubmit', function (e, data) {
var result = Discourse.Utilities.validateFilesForUpload(data.files); var result = Discourse.Utilities.validateUploadedFiles(data.files);
// reset upload status when everything is ok // reset upload status when everything is ok
if (result) composerView.setProperties({ uploadProgress: 0, isUploading: true }); if (result) composerView.setProperties({ uploadProgress: 0, isUploading: true });
return result; return result;
@ -300,10 +300,11 @@ Discourse.ComposerView = Discourse.View.extend({
switch (data.jqXHR.status) { switch (data.jqXHR.status) {
// 0 == cancel from the user // 0 == cancel from the user
case 0: return; case 0: return;
// 413 == entity too large, returned usually from nginx // 413 == entity too large, usually returned from the web server
case 413: case 413:
var maxSizeKB = Discourse.Utilities.maxUploadSizeInKB(data.files[0].name); var type = Discourse.Utilities.isAnImage(data.files[0].name) ? "image" : "attachment";
bootbox.alert(I18n.t('post.errors.upload_too_large', { max_size_kb: maxSizeKB })); var maxSizeKB = Discourse.SiteSettings['max_' + type + '_size_kb'];
bootbox.alert(I18n.t('post.errors.' + type + '_too_large', { max_size_kb: maxSizeKB }));
return; return;
// 415 == media type not authorized // 415 == media type not authorized
case 415: case 415:

View File

@ -4,21 +4,28 @@ class UploadsController < ApplicationController
def create def create
file = params[:file] || params[:files].first file = params[:file] || params[:files].first
# check if the extension is allowed
unless SiteSetting.authorized_upload?(file) unless SiteSetting.authorized_upload?(file)
text = I18n.t("upload.unauthorized", authorized_extensions: SiteSetting.authorized_extensions.gsub("|", ", ")) text = I18n.t("upload.unauthorized", authorized_extensions: SiteSetting.authorized_extensions.gsub("|", ", "))
return render status: 415, text: text return render status: 415, text: text
end end
upload = Upload.create_for(current_user.id, file) # check the file size (note: this might also be done in the web server)
filesize = File.size(file.tempfile)
type = SiteSetting.authorized_image?(file) ? "image" : "attachment"
max_size_kb = SiteSetting.send("max_#{type}_size_kb") * 1024
return render status: 413, text: I18n.t("upload.#{type}s.too_large", max_size_kb: max_size_kb) if filesize > max_size_kb
upload = Upload.create_for(current_user.id, file, filesize)
render_serialized(upload, UploadSerializer, root: false) render_serialized(upload, UploadSerializer, root: false)
rescue FastImage::ImageFetchFailure rescue FastImage::ImageFetchFailure
render status: 422, text: I18n.t("upload.image.fetch_failure") render status: 422, text: I18n.t("upload.images.fetch_failure")
rescue FastImage::UnknownImageType rescue FastImage::UnknownImageType
render status: 422, text: I18n.t("upload.image.unknown_image_type") render status: 422, text: I18n.t("upload.images.unknown_image_type")
rescue FastImage::SizeNotFound rescue FastImage::SizeNotFound
render status: 422, text: I18n.t("upload.image.size_not_found") render status: 422, text: I18n.t("upload.images.size_not_found")
end end
end end

View File

@ -43,7 +43,7 @@ class Upload < ActiveRecord::Base
end end
end end
def self.create_for(user_id, file) def self.create_for(user_id, file, filesize)
# compute the sha # compute the sha
sha1 = Digest::SHA1.file(file.tempfile).hexdigest sha1 = Digest::SHA1.file(file.tempfile).hexdigest
# check if the file has already been uploaded # check if the file has already been uploaded
@ -61,7 +61,7 @@ class Upload < ActiveRecord::Base
upload = Upload.create!({ upload = Upload.create!({
user_id: user_id, user_id: user_id,
original_filename: file.original_filename, original_filename: file.original_filename,
filesize: File.size(file.tempfile), filesize: filesize,
sha1: sha1, sha1: sha1,
url: "", url: "",
width: width, width: width,

View File

@ -788,7 +788,7 @@ cs:
create: "Bohužel nastala chyba při vytváření příspěvku. Prosím zkuste to znovu." create: "Bohužel nastala chyba při vytváření příspěvku. Prosím zkuste to znovu."
edit: "Bohužel nastala chyba při editaci příspěvku. Prosím zkuste to znovu." edit: "Bohužel nastala chyba při editaci příspěvku. Prosím zkuste to znovu."
upload: "Bohužel nastala chyba při nahrávání příspěvku. Prosím zkuste to znovu." upload: "Bohužel nastala chyba při nahrávání příspěvku. Prosím zkuste to znovu."
upload_too_large: "Soubor, který se snažíte nahrát je bohužel příliš velký (maximální velikost je {{max_size_kb}}kb). Prosím zmenšete ho zkuste to znovu." image_too_large: "Soubor, který se snažíte nahrát je bohužel příliš velký (maximální velikost je {{max_size_kb}}kb). Prosím zmenšete ho zkuste to znovu."
too_many_uploads: "Bohužel, najednou smíte nahrát jen jeden soubor." too_many_uploads: "Bohužel, najednou smíte nahrát jen jeden soubor."
upload_not_authorized: "Bohužel, soubor, který se snažíte nahrát, není povolený (povolené přípony: {{authorized_extensions}})." upload_not_authorized: "Bohužel, soubor, který se snažíte nahrát, není povolený (povolené přípony: {{authorized_extensions}})."
upload_not_allowed_for_new_user: "Bohužel, noví uživatelé nemohou nahrávat obrázky." upload_not_allowed_for_new_user: "Bohužel, noví uživatelé nemohou nahrávat obrázky."

View File

@ -762,7 +762,7 @@ de:
create: "Entschuldige, es gab einen Fehler beim Anlegen des Beitrags. Bitte versuche es noch einmal." create: "Entschuldige, es gab einen Fehler beim Anlegen des Beitrags. Bitte versuche es noch einmal."
edit: "Entschuldige, es gab einen Fehler beim Bearbeiten des Beitrags. Bitte versuche es noch einmal." edit: "Entschuldige, es gab einen Fehler beim Bearbeiten des Beitrags. Bitte versuche es noch einmal."
upload: "Entschuldige, es gab einen Fehler beim Hochladen der Datei. Bitte versuche es noch einmal." upload: "Entschuldige, es gab einen Fehler beim Hochladen der Datei. Bitte versuche es noch einmal."
upload_too_large: "Entschuldige, die Datei die du hochladen wolltest ist zu groß (Maximalgröße {{max_size_kb}}kb), bitte reduziere die Dateigröße und versuche es nochmal." image_too_large: "Entschuldige, die Datei die du hochladen wolltest ist zu groß (Maximalgröße {{max_size_kb}}kb), bitte reduziere die Dateigröße und versuche es nochmal."
abandon: "Willst Du diesen Beitrag wirklich verwerfen?" abandon: "Willst Du diesen Beitrag wirklich verwerfen?"

View File

@ -762,7 +762,8 @@ en:
create: "Sorry, there was an error creating your post. Please try again." create: "Sorry, there was an error creating your post. Please try again."
edit: "Sorry, there was an error editing your post. Please try again." edit: "Sorry, there was an error editing your post. Please try again."
upload: "Sorry, there was an error uploading that file. Please try again." upload: "Sorry, there was an error uploading that file. Please try again."
upload_too_large: "Sorry, the file you are trying to upload is too big (maximum size is {{max_size_kb}}kb), please resize it and try again." attachment_too_large: "Sorry, the file you are trying to upload is too big (maximum size is {{max_size_kb}}kb)."
image_too_large: "Sorry, the image you are trying to upload is too big (maximum size is {{max_size_kb}}kb), please resize it and try again."
too_many_uploads: "Sorry, you can only upload one file at a time." too_many_uploads: "Sorry, you can only upload one file at a time."
upload_not_authorized: "Sorry, the file you are trying to upload is not authorized (authorized extension: {{authorized_extensions}})." upload_not_authorized: "Sorry, the file you are trying to upload is not authorized (authorized extension: {{authorized_extensions}})."
image_upload_not_allowed_for_new_user: "Sorry, new users can not upload images." image_upload_not_allowed_for_new_user: "Sorry, new users can not upload images."

View File

@ -743,7 +743,8 @@ fr:
create: "Désolé, il y a eu une erreur lors de la publication de votre message. Merci de réessayer." create: "Désolé, il y a eu une erreur lors de la publication de votre message. Merci de réessayer."
edit: "Désolé, il y a eu une erreur lors de l'édition de votre message. Merci de réessayer." edit: "Désolé, il y a eu une erreur lors de l'édition de votre message. Merci de réessayer."
upload: "Désolé, il y a eu une erreur lors de l'envoi du fichier. Merci de réessayer." upload: "Désolé, il y a eu une erreur lors de l'envoi du fichier. Merci de réessayer."
upload_too_large: "Désolé, le fichier que vous êtes en train d'envoyer est trop grand (maximum {{max_size_kb}}Kb). Merci de le redimensionner et de réessayer." image_too_large: "Désolé, l'image que vous êtes en train d'envoyer est trop grande (taille maximum de {{max_size_kb}} Ko). Merci de le redimensionner et de réessayer."
attachment_too_large: "Désolé, le fichier que vous êtes en train d'envoyer est trop grand (taille maximum de {{max_size_kb}} Ko)."
too_many_uploads: "Désolé, vous ne pouvez envoyer qu'un seul fichier à la fois." too_many_uploads: "Désolé, vous ne pouvez envoyer qu'un seul fichier à la fois."
upload_not_authorized: "Désole, le fichier que vous êtes en train d'uploader n'est pas autorisé (extensions autorisées : {{authorized_extensions}})." upload_not_authorized: "Désole, le fichier que vous êtes en train d'uploader n'est pas autorisé (extensions autorisées : {{authorized_extensions}})."
image_upload_not_allowed_for_new_user: "Désolé, les nouveaux utilisateurs ne peuvent pas uploader d'image." image_upload_not_allowed_for_new_user: "Désolé, les nouveaux utilisateurs ne peuvent pas uploader d'image."

View File

@ -660,7 +660,7 @@ it:
create: "Spiacenti, si è verificato un errore durante la creazione del tuo post. Per favore, prova di nuovo." create: "Spiacenti, si è verificato un errore durante la creazione del tuo post. Per favore, prova di nuovo."
edit: "Spiacenti, si è verificato un errore durante la modifica del tuo post. Per favore, prova di nuovo." edit: "Spiacenti, si è verificato un errore durante la modifica del tuo post. Per favore, prova di nuovo."
upload: "Spiacenti, si è verificato un errore durante il caricamento del file. Per favore, prova di nuovo." upload: "Spiacenti, si è verificato un errore durante il caricamento del file. Per favore, prova di nuovo."
upload_too_large: "Spiacenti, il file che stai cercando di caricare è troppo grande (la dimensione massima è {{max_size_kb}}kb), per favore ridimensionalo e prova di nuovo." image_too_large: "Spiacenti, il file che stai cercando di caricare è troppo grande (la dimensione massima è {{max_size_kb}}kb), per favore ridimensionalo e prova di nuovo."
too_many_uploads: "Spiacenti, puoi caricare un'immagine per volta." too_many_uploads: "Spiacenti, puoi caricare un'immagine per volta."
abandon: "Sei sicuro di voler abbandonare il tuo post?" abandon: "Sei sicuro di voler abbandonare il tuo post?"

View File

@ -610,7 +610,7 @@ ko:
create: "죄송합니다, 귀하의 게시물을 만드는 동안 오류가 발생했습니다. 다시 시도하십시오." create: "죄송합니다, 귀하의 게시물을 만드는 동안 오류가 발생했습니다. 다시 시도하십시오."
edit: "죄송합니다, 귀하의 게시물을 수정하는 중에 오류가 발생했습니다. 다시 시도하십시오." edit: "죄송합니다, 귀하의 게시물을 수정하는 중에 오류가 발생했습니다. 다시 시도하십시오."
upload: "죄송합니다, 오류가 업로드하는 파일이 있었다. 다시 시도하십시오." upload: "죄송합니다, 오류가 업로드하는 파일이 있었다. 다시 시도하십시오."
upload_too_large: "죄송합니다, 당신이 업로드하려는 파일이 너무 큽니다. (최대 크기는 {{max_size_kb}}kb), 사이즈를 조정하고 다시 시도해보세요" image_too_large: "죄송합니다, 당신이 업로드하려는 파일이 너무 큽니다. (최대 크기는 {{max_size_kb}}kb), 사이즈를 조정하고 다시 시도해보세요"
upload_too_many_images: "죄송합니다, 당신은 한 번에 하나의 이미지를 업로드 할 수 있습니다." upload_too_many_images: "죄송합니다, 당신은 한 번에 하나의 이미지를 업로드 할 수 있습니다."
only_images_are_supported: "죄송합니다, 당신은 한 번에 하나의 이미지를 업로드 할 수 있습니다." only_images_are_supported: "죄송합니다, 당신은 한 번에 하나의 이미지를 업로드 할 수 있습니다."

View File

@ -680,7 +680,7 @@ nb_NO:
create: "Beklager, det oppstod en feil ved å publisere ditt innlegg. Vennligst prøv igjen." create: "Beklager, det oppstod en feil ved å publisere ditt innlegg. Vennligst prøv igjen."
edit: "Beklager, det oppstod en feil ved redigeringen av ditt innlegg. Vennligst prøv igjen." edit: "Beklager, det oppstod en feil ved redigeringen av ditt innlegg. Vennligst prøv igjen."
upload: "Sorry, there was an error uploading that file. Please try again." upload: "Sorry, there was an error uploading that file. Please try again."
upload_too_large: "Beklager, filen du prøve å laste opp er for stor (maks størrelse er {{max_size_kb}}kb), vennligst reduser størrelsen og prøv igjen." image_too_large: "Beklager, filen du prøve å laste opp er for stor (maks størrelse er {{max_size_kb}}kb), vennligst reduser størrelsen og prøv igjen."
too_many_uploads: "Beklager, du kan bare laste opp ett bilde om gangen." too_many_uploads: "Beklager, du kan bare laste opp ett bilde om gangen."
abandon: "Er du sikker på at du vil forlate innlegget ditt?" abandon: "Er du sikker på at du vil forlate innlegget ditt?"

View File

@ -757,7 +757,7 @@ nl:
create: "Sorry, er is iets misgegaan bij het plaatsen van je bericht. Probeer het nog eens." create: "Sorry, er is iets misgegaan bij het plaatsen van je bericht. Probeer het nog eens."
edit: "Sorry, er is iets misgegaan bij het bewerken van je bericht. Probeer het nog eens." edit: "Sorry, er is iets misgegaan bij het bewerken van je bericht. Probeer het nog eens."
upload: "Sorry, er is iets misgegaan bij het uploaden van je bestand. Probeer het nog eens." upload: "Sorry, er is iets misgegaan bij het uploaden van je bestand. Probeer het nog eens."
upload_too_large: "Sorry, het bestand dat je wil uploaden is te groot (maximum grootte is {{max_size_kb}}kb), verklein het bestand en probeer het opnieuw." image_too_large: "Sorry, het bestand dat je wil uploaden is te groot (maximum grootte is {{max_size_kb}}kb), verklein het bestand en probeer het opnieuw."
too_many_uploads: "Sorry, je kan maar één afbeelding tegelijk uploaden." too_many_uploads: "Sorry, je kan maar één afbeelding tegelijk uploaden."
upload_not_authorized: "Sorry, je mag dat type bestand niet uploaden (toegestane extensies: {{authorized_extensions}})." upload_not_authorized: "Sorry, je mag dat type bestand niet uploaden (toegestane extensies: {{authorized_extensions}})."
upload_not_allowed_for_new_user: "Sorry, nieuwe gebruikers mogen nog geen afbeeldingen uploaden." upload_not_allowed_for_new_user: "Sorry, nieuwe gebruikers mogen nog geen afbeeldingen uploaden."

View File

@ -731,7 +731,7 @@ pseudo:
edit: '[[ Šóřřý, ťĥéřé ŵáš áɳ éřřóř éďíťíɳǧ ýóůř ƿóšť. Рłéášé ťřý áǧáíɳ. ]]' edit: '[[ Šóřřý, ťĥéřé ŵáš áɳ éřřóř éďíťíɳǧ ýóůř ƿóšť. Рłéášé ťřý áǧáíɳ. ]]'
upload: '[[ Šóřřý, ťĥéřé ŵáš áɳ éřřóř ůƿłóáďíɳǧ ťĥáť ƒíłé. Рłéášé ťřý áǧáíɳ. upload: '[[ Šóřřý, ťĥéřé ŵáš áɳ éřřóř ůƿłóáďíɳǧ ťĥáť ƒíłé. Рłéášé ťřý áǧáíɳ.
]]' ]]'
upload_too_large: '[[ Šóřřý, ťĥé ƒíłé ýóů ářé ťřýíɳǧ ťó ůƿłóáď íš ťóó ƀíǧ image_too_large: '[[ Šóřřý, ťĥé ƒíłé ýóů ářé ťřýíɳǧ ťó ůƿłóáď íš ťóó ƀíǧ
(ɱáхíɱůɱ šížé íš {{max_size_kb}}ǩƀ), ƿłéášé řéšížé íť áɳď ťřý áǧáíɳ. ]]' (ɱáхíɱůɱ šížé íš {{max_size_kb}}ǩƀ), ƿłéášé řéšížé íť áɳď ťřý áǧáíɳ. ]]'
too_many_uploads: '[[ Šóřřý, ýóů čáɳ óɳłý ůƿłóáď óɳé ƒíłé áť á ťíɱé. ]]' too_many_uploads: '[[ Šóřřý, ýóů čáɳ óɳłý ůƿłóáď óɳé ƒíłé áť á ťíɱé. ]]'
upload_not_authorized: '[[ Šóřřý, ťĥé ƒíłé ýóů ářé ťřýíɳǧ ťó ůƿłóáď íš ɳóť upload_not_authorized: '[[ Šóřřý, ťĥé ƒíłé ýóů ářé ťřýíɳǧ ťó ůƿłóáď íš ɳóť

View File

@ -656,7 +656,7 @@ pt_BR:
create: "Desculpe, houve um erro ao criar o seu post. Por favor tenta outra vez." create: "Desculpe, houve um erro ao criar o seu post. Por favor tenta outra vez."
edit: "Desculpe, houve um erro ao editar o seu post. Por favor tenta outra vez." edit: "Desculpe, houve um erro ao editar o seu post. Por favor tenta outra vez."
upload: "Desculpe, houve um erro ao enviar esse ficheiro. Por favor tenta otura vez." upload: "Desculpe, houve um erro ao enviar esse ficheiro. Por favor tenta otura vez."
upload_too_large: "Desculpe, o arquivo que você está tentando enviar é muito grande (o tamanho máximo é {{max_size_kb}}kb), por favor diminua-o e tente novamente." image_too_large: "Desculpe, o arquivo que você está tentando enviar é muito grande (o tamanho máximo é {{max_size_kb}}kb), por favor diminua-o e tente novamente."
too_many_uploads: "Desculpe, você pode enviar apenas um arquivos por vez." too_many_uploads: "Desculpe, você pode enviar apenas um arquivos por vez."
upload_not_authorized: "Desculpe, o tipo de arquivo que você está tentando enviar não está autorizado (extensões autorizadas: {{authorized_extensions}})." upload_not_authorized: "Desculpe, o tipo de arquivo que você está tentando enviar não está autorizado (extensões autorizadas: {{authorized_extensions}})."
upload_not_allowed_for_new_user: "Desculpe, novos usuários não podem enviar imagens." upload_not_allowed_for_new_user: "Desculpe, novos usuários não podem enviar imagens."

View File

@ -735,7 +735,7 @@ ru:
create: К сожалению, не удалось создать сообщение. Попробуйте еще раз. create: К сожалению, не удалось создать сообщение. Попробуйте еще раз.
edit: К сожалению, не удалось изменить сообщение. Попробуйте еще раз. edit: К сожалению, не удалось изменить сообщение. Попробуйте еще раз.
upload: К сожалению, не удалось загрузить файл. Попробуйте еще раз. upload: К сожалению, не удалось загрузить файл. Попробуйте еще раз.
upload_too_large: 'Превышен допустимый размер ({{max_size_kb}}kb) файла. Уменьшите размер изображения и повторите попытку.' image_too_large: 'Превышен допустимый размер ({{max_size_kb}}kb) файла. Уменьшите размер изображения и повторите попытку.'
too_many_uploads: К сожалению, за один раз можно загрузить только одно изображение. too_many_uploads: К сожалению, за один раз можно загрузить только одно изображение.
upload_not_authorized: 'К сожалению, вы не можете загрузить файл данного типа (список разрешенных типов файлов: {{authorized_extensions}}).' upload_not_authorized: 'К сожалению, вы не можете загрузить файл данного типа (список разрешенных типов файлов: {{authorized_extensions}}).'
upload_not_allowed_for_new_user: К сожалению, загрузка изображений недоступна новым пользователям. upload_not_allowed_for_new_user: К сожалению, загрузка изображений недоступна новым пользователям.

View File

@ -578,7 +578,7 @@ sv:
create: "Tyvärr, det uppstod ett fel under skapandet av ditt inlägg. Var god försök igen." create: "Tyvärr, det uppstod ett fel under skapandet av ditt inlägg. Var god försök igen."
edit: "Tyvärr, det uppstod ett fel under ändringen av ditt inlägg. Var god försök igen." edit: "Tyvärr, det uppstod ett fel under ändringen av ditt inlägg. Var god försök igen."
upload: "Tyvärr, det uppstod ett fel under uppladdandet av den filen. Vad god försök igen." upload: "Tyvärr, det uppstod ett fel under uppladdandet av den filen. Vad god försök igen."
upload_too_large: "Tyvärr, filen som du försöker ladda upp är för stor (maxstorlek är {{max_size_kb}}kb), var god ändra storlek och försök igen." image_too_large: "Tyvärr, filen som du försöker ladda upp är för stor (maxstorlek är {{max_size_kb}}kb), var god ändra storlek och försök igen."
too_many_uploads: "Tyvärr, du kan bara ladda upp en bild i taget." too_many_uploads: "Tyvärr, du kan bara ladda upp en bild i taget."
abandon: "Är du säker på att du vill överge ditt inlägg?" abandon: "Är du säker på att du vill överge ditt inlägg?"

View File

@ -765,7 +765,7 @@ zh_CN:
create: "抱歉,在创建你的帖子时发生了错误。请重试。" create: "抱歉,在创建你的帖子时发生了错误。请重试。"
edit: "抱歉,在编辑你的帖子时发生了错误。请重试。" edit: "抱歉,在编辑你的帖子时发生了错误。请重试。"
upload: "抱歉,在上传文件时发生了错误。请重试。" upload: "抱歉,在上传文件时发生了错误。请重试。"
upload_too_large: "抱歉,你上传的文件太大了(最大不能超过 {{max_size_kb}}kb请调整文件大小后重新上传。" image_too_large: "抱歉,你上传的文件太大了(最大不能超过 {{max_size_kb}}kb请调整文件大小后重新上传。"
too_many_uploads: "抱歉, 你只能一次上传一张图片。" too_many_uploads: "抱歉, 你只能一次上传一张图片。"
upload_not_authorized: "抱歉, 你不能上传此类型文件(可上传的文件类型有: {{authorized_extensions}})。" upload_not_authorized: "抱歉, 你不能上传此类型文件(可上传的文件类型有: {{authorized_extensions}})。"
upload_not_allowed_for_new_user: "抱歉,新用户不能上传图片。" upload_not_allowed_for_new_user: "抱歉,新用户不能上传图片。"

View File

@ -660,7 +660,7 @@ zh_TW:
create: "抱歉,在創建你的帖子時發生了錯誤。請重試。" create: "抱歉,在創建你的帖子時發生了錯誤。請重試。"
edit: "抱歉,在編輯你的帖子時發生了錯誤。請重試。" edit: "抱歉,在編輯你的帖子時發生了錯誤。請重試。"
upload: "抱歉,在上傳文件時發生了錯誤。請重試。" upload: "抱歉,在上傳文件時發生了錯誤。請重試。"
upload_too_large: "抱歉,你上傳的文件太大了(最大不能超過 {{max_size_kb}}kb請調整文件大小後重新上傳。" image_too_large: "抱歉,你上傳的文件太大了(最大不能超過 {{max_size_kb}}kb請調整文件大小後重新上傳。"
too_many_uploads: "抱歉, 你只能一次上傳一張圖片。" too_many_uploads: "抱歉, 你只能一次上傳一張圖片。"
abandon: "你確定要丟棄你的帖子嗎?" abandon: "你確定要丟棄你的帖子嗎?"

View File

@ -1100,7 +1100,7 @@ cs:
upload: upload:
pasted_image_filename: "" pasted_image_filename: ""
image: images:
fetch_failure: "Bohužel, nastala chybí při získávání obrázku." fetch_failure: "Bohužel, nastala chybí při získávání obrázku."
unknown_image_type: "Bohužel, soubor, který se snažíte nahrát, zřejmě není obrázek." unknown_image_type: "Bohužel, soubor, který se snažíte nahrát, zřejmě není obrázek."
size_not_found: "Bohužel se nepodařilo zjistit velikost obrázku. Není soubor s obrázkem poškozený?" size_not_found: "Bohužel se nepodařilo zjistit velikost obrázku. Není soubor s obrázkem poškozený?"

View File

@ -1004,7 +1004,7 @@ de:
upload: upload:
pasted_image_filename: "" pasted_image_filename: ""
image: images:
fetch_failure: "Entschuldige, beim Laden des Bildes ist ein Fehler aufgetreten." fetch_failure: "Entschuldige, beim Laden des Bildes ist ein Fehler aufgetreten."
unknown_image_type: "Entschuldige, aber die Datei die Du hochladen möchtest schein kein Bild zu sein." unknown_image_type: "Entschuldige, aber die Datei die Du hochladen möchtest schein kein Bild zu sein."
size_not_found: "Entschuldige, aber wir konnten die Grösse des Bildes nicht feststellen. Vielleicht ist das Bild defekt?" size_not_found: "Entschuldige, aber wir konnten die Grösse des Bildes nicht feststellen. Vielleicht ist das Bild defekt?"

View File

@ -1090,7 +1090,10 @@ en:
upload: upload:
unauthorized: "Sorry, the file you are trying to upload is not authorized (authorized extensions: %{authorized_extensions})." unauthorized: "Sorry, the file you are trying to upload is not authorized (authorized extensions: %{authorized_extensions})."
pasted_image_filename: "Pasted image" pasted_image_filename: "Pasted image"
image: attachments:
too_large: "Sorry, the file you are trying to upload is too big (maximum size is %{max_size_kb}%kb)."
images:
too_large: "Sorry, the image you are trying to upload is too big (maximum size is %{max_size_kb}%kb), please resize it and try again."
fetch_failure: "Sorry, there has been an error while fetching the image." fetch_failure: "Sorry, there has been an error while fetching the image."
unknown_image_type: "Sorry, but the file you tried to upload doesn't appear to be an image." unknown_image_type: "Sorry, but the file you tried to upload doesn't appear to be an image."
size_not_found: "Sorry, but we couldn't determine the size of the image. Maybe your image is corrupted?" size_not_found: "Sorry, but we couldn't determine the size of the image. Maybe your image is corrupted?"

View File

@ -962,7 +962,10 @@ fr:
upload: upload:
pasted_image_filename: "Image collée" pasted_image_filename: "Image collée"
image: attachments:
too_large: "Désolé, le fichier que vous êtes en train d'uploader est trop grand (la taille maximum est %{max_size_kb}% ko)."
images:
too_large: "Désolé, l'image que vous êtes en train d'uploader est trop grande (la taille maximum est %{max_size_kb}% ko)."
fetch_failure: "Désolé, une erreur s'est produite lorsque nous avons essayé de récupérer l'image." fetch_failure: "Désolé, une erreur s'est produite lorsque nous avons essayé de récupérer l'image."
unknown_image_type: "Désolé, mais le fichier que vous essayez d'envoyer ne semble pas être une image." unknown_image_type: "Désolé, mais le fichier que vous essayez d'envoyer ne semble pas être une image."
size_not_found: "Désolé, mais nous n'avons pas réussit à déterminer la taille de l'image. Peut-être que l'image est corrompue ?" size_not_found: "Désolé, mais nous n'avons pas réussit à déterminer la taille de l'image. Peut-être que l'image est corrompue ?"

View File

@ -917,7 +917,7 @@ it:
upload: upload:
pasted_image_filename: "" pasted_image_filename: ""
image: images:
fetch_failure: "Spiacente, si è verificato un errore nel recupero dell'immagine." fetch_failure: "Spiacente, si è verificato un errore nel recupero dell'immagine."
unknown_image_type: "Spiacente, ma il file che hai provato a caricare non sembra un'immagine." unknown_image_type: "Spiacente, ma il file che hai provato a caricare non sembra un'immagine."
size_not_found: "Spiacente, ma non riusciamo a determinare la dimensione dell'immagine. Probabilmente l'immagine è corrotta?" size_not_found: "Spiacente, ma non riusciamo a determinare la dimensione dell'immagine. Probabilmente l'immagine è corrotta?"

View File

@ -932,7 +932,7 @@ ko:
deleted: 'deleted' deleted: 'deleted'
upload: upload:
image: images:
fetch_failure: "Sorry, there has been an error while fetching the image." fetch_failure: "Sorry, there has been an error while fetching the image."
unknown_image_type: "Sorry, but the file you tried to upload doesn't appear to be an image." unknown_image_type: "Sorry, but the file you tried to upload doesn't appear to be an image."
size_not_found: "Sorry, but we couldn't determine the size of the image. Maybe your image is corrupted?" size_not_found: "Sorry, but we couldn't determine the size of the image. Maybe your image is corrupted?"

View File

@ -1075,7 +1075,7 @@ nl:
upload: upload:
pasted_image_filename: "Geplakte afbeelding" pasted_image_filename: "Geplakte afbeelding"
image: images:
fetch_failure: "Er ging iets mis bij het opvragen van de afbeelding." fetch_failure: "Er ging iets mis bij het opvragen van de afbeelding."
unknown_image_type: "Het bestand dat je wil uploaden is geen afbeelding." unknown_image_type: "Het bestand dat je wil uploaden is geen afbeelding."
size_not_found: "Het is niet gelukt de afmetingen van de afbeelding te bepalen. Misschien is het bestand corrupt?" size_not_found: "Het is niet gelukt de afmetingen van de afbeelding te bepalen. Misschien is het bestand corrupt?"

View File

@ -1273,7 +1273,7 @@ pseudo:
deleted: '[[ ďéłéťéď ]]' deleted: '[[ ďéłéťéď ]]'
upload: upload:
pasted_image_filename: '[[ Рášťéď íɱáǧé ]]' pasted_image_filename: '[[ Рášťéď íɱáǧé ]]'
image: images:
fetch_failure: '[[ Šóřřý, ťĥéřé ĥáš ƀééɳ áɳ éřřóř ŵĥíłé ƒéťčĥíɳǧ ťĥé íɱáǧé. fetch_failure: '[[ Šóřřý, ťĥéřé ĥáš ƀééɳ áɳ éřřóř ŵĥíłé ƒéťčĥíɳǧ ťĥé íɱáǧé.
]]' ]]'
unknown_image_type: '[[ Šóřřý, ƀůť ťĥé ƒíłé ýóů ťříéď ťó ůƿłóáď ďóéšɳ''ť áƿƿéář unknown_image_type: '[[ Šóřřý, ƀůť ťĥé ƒíłé ýóů ťříéď ťó ůƿłóáď ďóéšɳ''ť áƿƿéář

View File

@ -955,7 +955,7 @@ pt_BR:
upload: upload:
unauthorized: "Desculpe-nos, o arquivo que você está tentando enviar não é autorizado (extensões autorizadas: %{authorized_extensions})." unauthorized: "Desculpe-nos, o arquivo que você está tentando enviar não é autorizado (extensões autorizadas: %{authorized_extensions})."
pasted_image_filename: "Imagem colada" pasted_image_filename: "Imagem colada"
image: images:
fetch_failure: "Desculpe, houve um erro ao transferir a imagem." fetch_failure: "Desculpe, houve um erro ao transferir a imagem."
unknown_image_type: "Desculpe, mas o arquivo que você tentou enviar não parece ser uma imagem." unknown_image_type: "Desculpe, mas o arquivo que você tentou enviar não parece ser uma imagem."
size_not_found: "Desculpe, mas não conseguimos determinar o tamanho da imagem. É possível que seu arquivo de imagem esteja corrompido?" size_not_found: "Desculpe, mas não conseguimos determinar o tamanho da imagem. É possível que seu arquivo de imagem esteja corrompido?"

View File

@ -1073,7 +1073,7 @@ ru:
upload: upload:
unauthorized: 'К сожалению, вы не можете загрузить файл данного типа (список разрешенных типов файлов: %{authorized_extensions}).' unauthorized: 'К сожалению, вы не можете загрузить файл данного типа (список разрешенных типов файлов: %{authorized_extensions}).'
pasted_image_filename: Имя файла изображения pasted_image_filename: Имя файла изображения
image: images:
fetch_failure: Извините, во время извлечения изображения произошла ошибка. fetch_failure: Извините, во время извлечения изображения произошла ошибка.
unknown_image_type: Файл, который вы загружаете, не является изображением. unknown_image_type: Файл, который вы загружаете, не является изображением.
size_not_found: Извините, мы не можем определить размер изображения. Возможно, изображение повреждено? size_not_found: Извините, мы не можем определить размер изображения. Возможно, изображение повреждено?

View File

@ -934,7 +934,7 @@ zh_CN:
upload: upload:
pasted_image_filename: "" pasted_image_filename: ""
image: images:
fetch_failure: "抱歉,获取图片時发生错误。" fetch_failure: "抱歉,获取图片時发生错误。"
unknown_image_type: "抱歉,你上传的文件似乎不是一张图片。" unknown_image_type: "抱歉,你上传的文件似乎不是一张图片。"
size_not_found: "抱歉,我们无法获取图片大小,请检查你的图片是否已损坏。" size_not_found: "抱歉,我们无法获取图片大小,请检查你的图片是否已损坏。"

View File

@ -917,7 +917,7 @@ zh_TW:
upload: upload:
pasted_image_filename: "" pasted_image_filename: ""
image: images:
fetch_failure: "抱歉,獲取圖片時發生錯誤。" fetch_failure: "抱歉,獲取圖片時發生錯誤。"
unknown_image_type: "抱歉,你上傳的文件似乎不是一張圖片。" unknown_image_type: "抱歉,你上傳的文件似乎不是一張圖片。"
size_not_found: "抱歉,我們無法獲取圖片大小,請檢查你的圖片是否已損壞。" size_not_found: "抱歉,我們無法獲取圖片大小,請檢查你的圖片是否已損壞。"

View File

@ -41,13 +41,29 @@ describe UploadsController do
context 'when authorized' do context 'when authorized' do
before { SiteSetting.stubs(:authorized_extensions).returns(".txt") } before { SiteSetting.stubs(:authorized_extensions).returns(".png|.txt") }
it 'is successful' do it 'is successful with an image' do
xhr :post, :create, file: logo
response.status.should eq 200
end
it 'is successful with an attachment' do
xhr :post, :create, file: text_file xhr :post, :create, file: text_file
response.status.should eq 200 response.status.should eq 200
end end
context 'with a big file' do
before { SiteSetting.stubs(:max_attachment_size_kb).returns(1) }
it 'rejects the upload' do
xhr :post, :create, file: text_file
response.status.should eq 413
end
end
end end
context 'when not authorized' do context 'when not authorized' do

View File

@ -27,6 +27,7 @@ describe Upload do
end end
let(:image_sha1) { Digest::SHA1.file(image.tempfile).hexdigest } let(:image_sha1) { Digest::SHA1.file(image.tempfile).hexdigest }
let(:image_filesize) { File.size(image.tempfile) }
let(:attachment) do let(:attachment) do
ActionDispatch::Http::UploadedFile.new({ ActionDispatch::Http::UploadedFile.new({
@ -35,6 +36,8 @@ describe Upload do
}) })
end end
let(:attachment_filesize) { File.size(attachment.tempfile) }
context ".create_thumbnail!" do context ".create_thumbnail!" do
it "does not create a thumbnail when disabled" do it "does not create a thumbnail when disabled" do
@ -77,7 +80,7 @@ describe Upload do
it "does not create another upload if it already exists" do it "does not create another upload if it already exists" do
Upload.expects(:where).with(sha1: image_sha1).returns([upload]) Upload.expects(:where).with(sha1: image_sha1).returns([upload])
Upload.expects(:create!).never Upload.expects(:create!).never
Upload.create_for(user_id, image).should == upload Upload.create_for(user_id, image, image_filesize).should == upload
end end
it "computes width & height for images" do it "computes width & height for images" do
@ -85,24 +88,24 @@ describe Upload do
FastImage.any_instance.expects(:size).returns([100, 200]) FastImage.any_instance.expects(:size).returns([100, 200])
ImageSizer.expects(:resize) ImageSizer.expects(:resize)
ActionDispatch::Http::UploadedFile.any_instance.expects(:rewind) ActionDispatch::Http::UploadedFile.any_instance.expects(:rewind)
Upload.create_for(user_id, image) Upload.create_for(user_id, image, image_filesize)
end end
it "does not create an upload when there is an error with FastImage" do it "does not create an upload when there is an error with FastImage" do
SiteSetting.expects(:authorized_image?).returns(true) SiteSetting.expects(:authorized_image?).returns(true)
Upload.expects(:create!).never Upload.expects(:create!).never
expect { Upload.create_for(user_id, attachment) }.to raise_error(FastImage::UnknownImageType) expect { Upload.create_for(user_id, attachment, attachment_filesize) }.to raise_error(FastImage::UnknownImageType)
end end
it "does not compute width & height for non-image" do it "does not compute width & height for non-image" do
SiteSetting.expects(:authorized_image?).returns(false) SiteSetting.expects(:authorized_image?).returns(false)
FastImage.any_instance.expects(:size).never FastImage.any_instance.expects(:size).never
Upload.create_for(user_id, image) Upload.create_for(user_id, image, image_filesize)
end end
it "saves proper information" do it "saves proper information" do
Upload.expects(:store_file).returns(url) Upload.expects(:store_file).returns(url)
upload = Upload.create_for(user_id, image) upload = Upload.create_for(user_id, image, image_filesize)
upload.user_id.should == user_id upload.user_id.should == user_id
upload.original_filename.should == image.original_filename upload.original_filename.should == image.original_filename
upload.filesize.should == File.size(image.tempfile) upload.filesize.should == File.size(image.tempfile)

View File

@ -7,9 +7,9 @@ test("emailValid", function() {
ok(utils.emailValid('bob@EXAMPLE.com'), "allows upper case in the email domain"); ok(utils.emailValid('bob@EXAMPLE.com'), "allows upper case in the email domain");
}); });
var validUpload = utils.validateFilesForUpload; var validUpload = utils.validateUploadedFiles;
test("validateFilesForUpload", function() { test("validateUploadedFiles", function() {
ok(!validUpload(null), "no files are invalid"); ok(!validUpload(null), "no files are invalid");
ok(!validUpload(undefined), "undefined files are invalid"); ok(!validUpload(undefined), "undefined files are invalid");
ok(!validUpload([]), "empty array of files is invalid"); ok(!validUpload([]), "empty array of files is invalid");
@ -55,7 +55,7 @@ test("prevents files that are too big from being uploaded", function() {
this.stub(bootbox, "alert"); this.stub(bootbox, "alert");
ok(!validUpload([image])); ok(!validUpload([image]));
ok(bootbox.alert.calledWith(I18n.t('post.errors.upload_too_large', { max_size_kb: 5 }))); ok(bootbox.alert.calledWith(I18n.t('post.errors.image_too_large', { max_size_kb: 5 })));
}); });
var dummyBlob = function() { var dummyBlob = function() {
@ -83,17 +83,6 @@ test("allows valid uploads to go through", function() {
ok(!bootbox.alert.calledOnce); ok(!bootbox.alert.calledOnce);
}); });
var isAuthorized = function (filename) {
return utils.isAuthorizedUpload({ name: filename });
};
test("isAuthorizedUpload", function() {
ok(isAuthorized("image.png"));
ok(isAuthorized("image.jpg"));
ok(!isAuthorized("image.txt"));
ok(!isAuthorized(""));
});
var getUploadMarkdown = function(filename) { var getUploadMarkdown = function(filename) {
return utils.getUploadMarkdown({ return utils.getUploadMarkdown({
original_filename: filename, original_filename: filename,

View File

@ -1,3 +1,3 @@
/*jshint maxlen:10000000 */ /*jshint maxlen:10000000 */
Discourse.SiteSettingsOriginal = {"title":"Discourse Meta","logo_url":"/assets/logo.png","logo_small_url":"/assets/logo-single.png","traditional_markdown_linebreaks":false,"top_menu":"latest|new|unread|read|favorited|categories","post_menu":"like|edit|flag|delete|share|bookmark|reply","share_links":"twitter|facebook|google+|email","track_external_right_clicks":false,"must_approve_users":false,"ga_tracking_code":"UA-33736483-2","ga_domain_name":"","enable_long_polling":true,"polling_interval":3000,"anon_polling_interval":30000,"min_post_length":20,"max_post_length":16000,"min_topic_title_length":15,"max_topic_title_length":255,"min_private_message_title_length":2,"allow_uncategorized_topics":true,"min_search_term_length":3,"flush_timings_secs":5,"suppress_reply_directly_below":true,"email_domains_blacklist":"mailinator.com","email_domains_whitelist":null,"version_checks":true,"min_title_similar_length":10,"min_body_similar_length":15,"category_colors":"BF1E2E|F1592A|F7941D|9EB83B|3AB54A|12A89D|25AAE2|0E76BD|652D90|92278F|ED207B|8C6238|231F20|808281|B3B5B4|283890","max_upload_size_kb":1024,"category_featured_topics":6,"favicon_url":"/assets/favicon.ico","dynamic_favicon":false,"uncategorized_name":"uncategorized","uncategorized_color":"AB9364","uncategorized_text_color":"FFFFFF","invite_only":false,"login_required":false,"enable_local_logins":true,"enable_local_account_create":true,"enable_google_logins":true,"enable_yahoo_logins":true,"enable_twitter_logins":true,"enable_facebook_logins":true,"enable_cas_logins":false,"enable_github_logins":true,"enable_persona_logins":true,"educate_until_posts":2,"topic_views_heat_low":1000,"topic_views_heat_medium":2000,"topic_views_heat_high":5000,"min_private_message_post_length":5,"faq_url":"","tos_url":"","privacy_policy_url":"","authorized_extensions":".jpg|.jpeg|.png|.gif","relative_date_duration":14}; Discourse.SiteSettingsOriginal = {"title":"Discourse Meta","logo_url":"/assets/logo.png","logo_small_url":"/assets/logo-single.png","traditional_markdown_linebreaks":false,"top_menu":"latest|new|unread|read|favorited|categories","post_menu":"like|edit|flag|delete|share|bookmark|reply","share_links":"twitter|facebook|google+|email","track_external_right_clicks":false,"must_approve_users":false,"ga_tracking_code":"UA-33736483-2","ga_domain_name":"","enable_long_polling":true,"polling_interval":3000,"anon_polling_interval":30000,"min_post_length":20,"max_post_length":16000,"min_topic_title_length":15,"max_topic_title_length":255,"min_private_message_title_length":2,"allow_uncategorized_topics":true,"min_search_term_length":3,"flush_timings_secs":5,"suppress_reply_directly_below":true,"email_domains_blacklist":"mailinator.com","email_domains_whitelist":null,"version_checks":true,"min_title_similar_length":10,"min_body_similar_length":15,"category_colors":"BF1E2E|F1592A|F7941D|9EB83B|3AB54A|12A89D|25AAE2|0E76BD|652D90|92278F|ED207B|8C6238|231F20|808281|B3B5B4|283890","max_upload_size_kb":1024,"category_featured_topics":6,"favicon_url":"/assets/favicon.ico","dynamic_favicon":false,"uncategorized_name":"uncategorized","uncategorized_color":"AB9364","uncategorized_text_color":"FFFFFF","invite_only":false,"login_required":false,"enable_local_logins":true,"enable_local_account_create":true,"enable_google_logins":true,"enable_yahoo_logins":true,"enable_twitter_logins":true,"enable_facebook_logins":true,"enable_cas_logins":false,"enable_github_logins":true,"enable_persona_logins":true,"educate_until_posts":2,"topic_views_heat_low":1000,"topic_views_heat_medium":2000,"topic_views_heat_high":5000,"min_private_message_post_length":5,"faq_url":"","tos_url":"","privacy_policy_url":"","authorized_extensions":".jpg|.jpeg|.png|.gif|.txt","relative_date_duration":14};
Discourse.SiteSettings = jQuery.extend(true, {}, Discourse.SiteSettingsOriginal); Discourse.SiteSettings = jQuery.extend(true, {}, Discourse.SiteSettingsOriginal);