diff --git a/settings.py b/settings.py index eef79a5..e5149cb 100644 --- a/settings.py +++ b/settings.py @@ -25,4 +25,8 @@ DEV_PORT= "8000" # User and group the server should run as. Set to None if it should be the # current user USER = None -GROUP = None \ No newline at end of file +GROUP = None + +# limit size of pasted text in bytes. Be carefull allowing too much size can slow down user's +# browser +MAX_SIZE = 500 * 1 \ No newline at end of file diff --git a/src/__init__.py b/src/__init__.py index 80d200b..6602367 100644 --- a/src/__init__.py +++ b/src/__init__.py @@ -16,11 +16,7 @@ def setup_path(): Add the project dir in the python path to the site to run with the source code beeing just copied/pasted and not installed. - Also try to import dependancies. If it fails, fallback on embeded libs. + Add fallback on embeded libs to path. """ sys.path.insert(0, os.path.dirname(settings.ROOT_DIR)) - - try: - import bottle - except ImportError: - sys.path.append(os.path.join(settings.ROOT_DIR, 'libs')) \ No newline at end of file + sys.path.append(os.path.join(settings.ROOT_DIR, 'libs')) \ No newline at end of file diff --git a/src/paste.py b/src/paste.py index f4d6f40..687d8b4 100644 --- a/src/paste.py +++ b/src/paste.py @@ -154,12 +154,14 @@ class Paste(object): self.expiration = self.expiration + '#%s' % datetime.now() # write the paste - with open(self.path, 'w') as f: - f.write(unicode(self.expiration) + '\n') - f.write(self.content + '\n') - if self.comments: - f.write(comments) - + try: + with open(self.path, 'w') as f: + f.write(unicode(self.expiration) + '\n') + f.write(self.content + '\n') + if self.comments: + f.write(comments) + except Exception as e: + import ipdb; ipdb.set_trace() return self diff --git a/start.py b/start.py index 6da0d85..794683d 100644 --- a/start.py +++ b/start.py @@ -12,6 +12,7 @@ import thread import time import tempfile import glob +import math from datetime import datetime, timedelta @@ -30,11 +31,14 @@ from bottle import (Bottle, route, run, abort, app = Bottle() +import settings + @app.route('/') @view('home') def index(): - return {} + max_size_kb = int(math.ceil(settings.MAX_SIZE/1024.0)) + return {'max_size': settings.MAX_SIZE, 'max_size_kb': max_size_kb} @app.route('/paste/create', method='POST') diff --git a/static/css/style.css b/static/css/style.css index 0671396..5a991c8 100644 --- a/static/css/style.css +++ b/static/css/style.css @@ -2,14 +2,13 @@ .brand { -font-size: 38px !important; -padding: 0px 55px 3px !important; - -text-shadow: 0 1px 0 rgba(255, 255, 255, .1), 0 0 30px rgba(255, 255, 255, .125); --webkit-transition: all .2s linear; --moz-transition: all .2s linear; -transition: all .2s linear; + font-size: 38px !important; + padding: 0px 55px 3px !important; + text-shadow: 0 1px 0 rgba(255, 255, 255, .1), 0 0 30px rgba(255, 255, 255, .125); + -webkit-transition: all .2s linear; + -moz-transition: all .2s linear; + transition: all .2s linear; } .brand span { @@ -34,15 +33,6 @@ body { padding: 9px 0; } -.btn-group { - float:left; -} - -.paste-option { - float:right; -} - - select { width: 135px; } @@ -61,7 +51,7 @@ ul, ol { } li { - margin-left: -4px; + margin-left: -9px; } @@ -73,24 +63,174 @@ p { color: #999; } -.items { - text-align: center; -} - .nav-list { padding-right: 0px !important; font-size: 12px; } -.form-options li{ +blockquote { + width: 630px; float: left; - list-style-type: none; +} + +h4 p { + float: left; + font-size: 80px; + text-shadow: 1px 3px 1px #DDD, 0 0 4px #333; + -webkit-transition: all 0.2s linear; + -moz-transition: all .2s linear; + transition: all .2s linear; + margin-right: 7px; + margin-top: 3px; +} + +h4#pixels-total { + position: relative; + width: 166px; + float: right; + margin: 8px 0 0 0; + padding: 0 0 0 54px; + font-size: 1.1em; + line-height: 1.4; + font-weight: normal; + color: #777; + -webkit-border-top-right-radius: 6px; + -webkit-border-top-left-radius: 20px; + -moz-border-top-right-radius: 6px; + -moz-border-top-left-radius: 20px; + border-top-right-radius: 6px; + border-top-left-radius: 20px; +} + +.greetings { + clear: both; + margin: 0 auto; + text-align: center; + margin-top: 40px; +} + +/* Home */ + +.btn-group { + float:left; +} + +.file-upload { + float: left; + margin: 22px 0px 0px 21px; + display: none; +} + +input.btn-upload { + position: relative; + left: -6px; + width: 100px; + z-index: 1; + margin-top: -13px; +} + +input.hide-upload { + position: relative; + left: -110px; + -moz-opacity: 0; + filter: alpha(opacity: 0); + opacity: 0 ; + z-index: 2; + width: 100px; + margin-top: -20px; + cursor: pointer; + cursor: hand; + height: 49px; +} + +.max-size-reached { + display: none; +} + +/* Paste Page */ + +.items { + text-align: center; } #paste-content { background-color: white; } +#copy-success, +#short-url-success, +.submit-form { + display:none; +} + +.paste-option { + float:right; +} + +a#clip-button.hover{ + cursor:pointer; + text-decoration:underline; +} + +li.L0, li.L1, li.L2, li.L3, li.L4, +li.L5, li.L6, li.L7, li.L8, li.L9 +{ + list-style-type: decimal; + background: inherit; +} + +.prettyprint.linenums { + -webkit-box-shadow: inset 40px 0 0 #fbfbfc, inset 41px 0 0 #ececf0; + -moz-box-shadow: inset 40px 0 0 #fbfbfc, inset 41px 0 0 #ececf0; + box-shadow: inset 40px 0 0 #fbfbfc, inset 41px 0 0 #ececf0; +} + +/* Specify class=linenums on a pre to get line numbering */ +ol.linenums { + margin: 0 0 0 55px; /* IE indents via margin-left */ +} +ol.linenums li { + color: #bebec5; + line-height: 18px; + text-shadow: 0 1px 0 #fff; +} + +.prettyprint { + padding: 8px; + background-color: #f7f7f9; + border: 1px solid #e1e1e8; +} + +pre { + font-family: Consolas, Menlo, Monaco, Lucida Console, Liberation Mono, DejaVu Sans Mono, Bitstream Vera Sans Mono, monospace, serif; + line-height: 21px; + font-size: 12px; + +} + +.kwd { +color: #66F; +} + +.pun, .opn, .clo { +color: #0A0; +} + +.lit { +color: #933; +} + +.com { +color: #C0C; +} + + +/* Common css */ + +form { + padding-bottom:3em !important; + padding-right: 17px; +} form textarea { overflow-y:auto; @@ -100,10 +240,6 @@ button.btn, input[type="submit"].btn { margin-left: 5px; } -.submit-form { - display: none; -} - .well { padding-bottom: 40px; padding-right: 17px; @@ -120,51 +256,11 @@ button.btn, input[type="submit"].btn { margin-left: 5px; } -form { - padding-bottom:3em !important; - padding-right: 17px; -} - .btn-primary { position:relative; top:-4px; } - -pre { - padding:1em 20px !important; -} - -.linenums { - padding-left: 35px; -} - - -ol.linenums li { - line-height:14px; -} - -ol.linenums span:first-child { - border-left: solid 1px #999; - padding-left:1em; -} - -li.L0, li.L1, li.L2, li.L3, li.L4, -li.L5, li.L6, li.L7, li.L8, li.L9 -{ - list-style-type: decimal; - background: inherit; -} - -a#clip-button.hover{ -cursor:pointer; -text-decoration:underline; -} - -#copy-success, #short-url-success { - display:none; -} - /** Progress bar */ .progress { @@ -181,4 +277,4 @@ text-decoration:underline; -moz-transition: width 0.1s ease; -ms-transition: width 0.1s ease; -o-transition: width 0.1s ease; -transition: width 0.1s ease; \ No newline at end of file +transition: width 0.1s ease; diff --git a/static/js/behavior.js b/static/js/behavior.js index d928821..6d29e96 100644 --- a/static/js/behavior.js +++ b/static/js/behavior.js @@ -5,7 +5,6 @@ sjcl.random.startCollectors(); /* Ensure jquery use cache for ajax requests */ $.ajaxSetup({ cache: true }); -zerobin = { /** Base64 + compress + encrypt, with callbacks before each operation, and all of them are executed in a timed continuation to give @@ -141,7 +140,6 @@ zerobin = { } return keys.sort(zerobin.numOrdA); }, - /** Get a tinyurl using JSONP */ getTinyURL: function(longURL, success) { @@ -212,6 +210,19 @@ zerobin = { content_clone = content_clone + $(this).text() + '\n'; }); return content_clone; + }, + count: function(text, options) { + // Set option defaults + var crlf = /(\r?\n|\r)/g; + var whitespace = /(\r?\n|\r|\s+)/g; + options = options || {}; + options.lineBreaks = options.lineBreaks || 1; + + var length = text.length, + nonAscii = length - text.replace(/[\u0100-\uFFFF]/g, '').length, + lineBreaks = length - text.replace(crlf, '').length; + + return length + nonAscii + Math.max(0, options.lineBreaks * (lineBreaks - 1)); } }; @@ -229,7 +240,14 @@ $('button[type=submit]').live("click", function(e){ e.preventDefault(); var paste = $('textarea').val(); - if (paste.trim()) { + var sizebytes = zerobin.count($('#content').val(), { }); + var oversized = sizebytes > zerobin.max_size; + if (oversized){ + $('.max-size-reached').show(); + $('.file-size').text(Math.round(sizebytes/1024)); + } + + if (!oversized && paste.trim()) { $('form.well p').hide(); $loading = $('form.well .progress').show(); @@ -281,7 +299,7 @@ $('button[type=submit]').live("click", function(e){ }); -/** +** DECRYPTION: On the display paste page, decrypt and decompress the paste content, add syntax coloration then setup the copy to clipboard button. @@ -361,16 +379,17 @@ if (content && key) { } /* End of "DECRYPTION" */ - /* Synchronize expiration select boxes value */ $('.paste-option select').live('change', function(){ var value = $(this).val(); $('.paste-option select').val(value); }); + /* Resize Textarea according to content */ $('#content').elastic(); + /* Display bottom paste option buttons when needed */ $('#content').live('keyup change', function(){ if($('#content').height() < 400 ){ @@ -381,6 +400,7 @@ $('#content').live('keyup change', function(){ $('.paste-option').clone().addClass('down').appendTo('form.well'); } } + }); /* Display previous pastes */ @@ -394,6 +414,48 @@ $('.btn-clone').click(function(e){ $('.paste-form').remove(); $('#content').val(content_clone); $('#content').trigger('change'); + +}); + + +/* Upload file using HTML5 File API */ + +if (window.File && window.FileReader && window.FileList && window.Blob) { + $('.file-upload').show(); +} + +var file_upload = function(file) { + var reader = new FileReader(); + reader.onload = function(event) { + var content = event.target.result; + $('#content').val(content); + $('#content').trigger('change'); + }; + + reader.readAsText(file[0]); +} + +try { + $('#file-upload').change(function() { + file_upload(this.files); + }); +} +catch (e) { + alert(e); +} + +$('#file-upload').mouseover(function(){ + $(this).css( 'cursor', 'pointer' ); +}); + + +/* Alerts */ + +$(".close").click(function(){ + $(this).parent().fadeOut(); }); }); /* End of "document ready" jquery callback */ + + + diff --git a/views/base.tpl b/views/base.tpl index 1eb3ae0..0f43bd4 100644 --- a/views/base.tpl +++ b/views/base.tpl @@ -22,6 +22,9 @@ + @@ -75,12 +78,18 @@

«Few persons can be made to believe that it is not quite an easy thing to invent a method of secret writing which shall baffle investigation. Yet it may be roundly asserted that human ingenuity cannot concoct a cipher which human ingenuity cannot resolve...»

Edgar Allan Poe -
-

- Based on an original idea from - sebsauvage.net -

+

+

ø

+ 41,017,923,819 pastes øbinned +

+ +
+

+ Based on an original idea from + sebsauvage.net
+ Sam & Max +

diff --git a/views/home.tpl b/views/home.tpl index 48bd6bc..15b4eaa 100644 --- a/views/home.tpl +++ b/views/home.tpl @@ -1,3 +1,14 @@ +
+ × + Warning!
+ Your file is KB You have reached the maximum size limit of {{ max_size_kb }}KB. +
+ +

+ + +

+

@@ -20,4 +31,4 @@

-%rebase base \ No newline at end of file +%rebase base max_size=max_size diff --git a/views/paste.tpl b/views/paste.tpl index 057d6c2..3602f9a 100644 --- a/views/paste.tpl +++ b/views/paste.tpl @@ -21,12 +21,11 @@
-

- Copy To Clipboard - | - Get short url - +

+ Copy To Clipboard + | + Get short url