3
3
#err under Apache this is going to cause some issues
4
4
#because Apache does add "." to path
5
5
import os ,sys
6
+ CURRENT_DIR = os .path .dirname (os .path .realpath (__file__ ))
7
+ sys .path .insert (0 ,CURRENT_DIR )
8
+ import config
6
9
import logging
7
- import dolog
8
- dolog .setup_logging (logdir = "logs/" ,scrnlog = False ,loglevel = logging .INFO )
9
- logger = logging .getLogger ("" )
10
+ logger = logging .getLogger ("blogstrap" )
10
11
logger .info ("Starting blogstrap.py" )
12
+ logger .debug ("app.py DEBUG messages enabled!" )
11
13
12
- #redirect stderr to the log
13
- sys .stderr = dolog .LoggerWriter (logger , logging .DEBUG )
14
+ from dolog import LoggerWriter
15
+ #redirect stderr to stdout and the logger created above
16
+ sys .stderr = LoggerWriter (logger )
14
17
15
18
from collections import defaultdict
16
19
from datetime import datetime
19
22
import web
20
23
from web import websafe
21
24
import datetime
22
- import config
23
25
import model as m
24
26
import hashlib
27
+ import xml .etree .ElementTree as ET
25
28
26
- VERSION = "0.9.6 -BETA"
29
+ VERSION = "0.9.8 -BETA"
27
30
28
31
logger .info ("You are running version %s" % VERSION )
29
32
30
- #if you change urls, make sure url [0] is your homepage!!
33
+ #if you change urls, make sure urls [0] is your homepage!!
31
34
urls = (
32
35
r"/" , "Index" ,
36
+ r"/sitemap.xml" ,"SiteMap" ,
33
37
r"/newest" , "IndexFull" ,
34
38
r"/post" , "BlogPost" ,
35
39
r"/about" , "About" ,
39
43
r"/contactme" , "ContactMe" ,
40
44
r"/tags" , "Tags" ,
41
45
r"/search" , "Search" ,
46
+ r"/admin/preview" , "Preview" ,
42
47
r"/admin/(.*)" ,"Admin" )
43
48
44
49
app = web .application (urls , globals ())
51
56
52
57
# Allow session to be reloadable in development mode.
53
58
if web .config .get ("_session" ) is None :
54
- session = web .session .Session (app , web .session .DiskStore ("sessions" ),
59
+ session = web .session .Session (app , web .session .DiskStore ("%s/ sessions" % CURRENT_DIR ),
55
60
initializer = sinit )
56
61
57
62
web .config ._session = session
58
63
else :
59
64
session = web .config ._session
60
65
61
66
67
+ b_data = m .BlogData .get (update = True )
68
+ def blog_data (update = False ):
69
+ global b_data
70
+ if update == False :
71
+ return b_data
72
+ else :
73
+ b_data = m .BlogData .get (update = True )
74
+ return b_data
75
+
76
+
62
77
def update_db ():
63
78
global t_globals
64
79
logger .info ("Start updating blog data" )
65
80
m .BlogData .update_stats ()
81
+ blog_data (update = True )
66
82
logger .info ("Finish updating blog data" )
67
83
68
84
@@ -107,6 +123,7 @@ def csrf_protected(f):
107
123
def decorated (* args ,** kwargs ):
108
124
inp = web .input ()
109
125
if not (inp .has_key ('csrf_token' ) and inp .csrf_token == session .pop ('csrf_token' ,None )):
126
+ logger .debug ("CSRF Detected!!!: ip=%s" % web .ctx .ip )
110
127
raise web .HTTPError (
111
128
"400 Bad request" ,
112
129
{'content-type' :'text/html' },
@@ -115,22 +132,13 @@ def decorated(*args,**kwargs):
115
132
return f (* args ,** kwargs )
116
133
return decorated
117
134
118
- b_data = m .BlogData .get (update = True )
119
- def blog_data (update = False ):
120
- global b_data
121
- if update == False :
122
- return b_data
123
- else :
124
- b_data = m .BlogData .get (update = True )
125
- return b_data
126
-
127
135
#lets check if out database tables exist, if not create them
128
136
for x in [m .User ,m .Post ,m .Image ,m .Comment ,m .BlogData ]:
129
137
#this will fail silently if they already exist
130
138
x .create_table (True )
131
139
132
140
133
- render = web .template .render ("templates/" ,
141
+ render = web .template .render ("%s/ templates/" % CURRENT_DIR ,
134
142
#base="base",
135
143
cache = config .cache )
136
144
t_globals = web .template .Template .globals
@@ -158,6 +166,42 @@ def blog_data(update = False):
158
166
print "Admin page currently set to: /admin/%s" % blog_data ().adminurl
159
167
logger .info ("Admin page currently set to: /admin/%s" % blog_data ().adminurl )
160
168
169
+ #Dynamically Generated sitemap.xml
170
+ #By default simply includes links to all blog posts that are public
171
+ class SiteMap :
172
+ def GET (self ):
173
+ host = web .ctx .home
174
+ print web .ctx
175
+ #1st get all public posts
176
+ posts = m .Post .all ()
177
+ #generate opening xml
178
+ urlset = ET .Element ("urlset" ,xmlns = "http://www.sitemaps.org/schemas/sitemap/0.9" )
179
+ #add root
180
+ url = ET .SubElement (urlset ,"url" )
181
+ loc = ET .SubElement (url ,"loc" )
182
+ loc .text = "%s/" % host
183
+ lastmod = ET .SubElement (url ,"lastmod" )
184
+ lastmod .text = datetime .datetime .now ().strftime ("%Y-%m-%d" )
185
+ changefreq = ET .SubElement (url ,"changefreq" )
186
+ changefreq .text = "daily"
187
+ priority = ET .SubElement (url ,"priority" )
188
+ priority .text = "0.8"
189
+
190
+ for post in posts :
191
+ url = ET .SubElement (urlset ,"url" )
192
+ loc = ET .SubElement (url ,"loc" )
193
+ loc .text = "%s/post?pid=%d" % (host ,post .id )
194
+ lastmod = ET .SubElement (url ,"lastmod" )
195
+ lastmod .text = post .updated .strftime ("%Y-%m-%d" )
196
+ changefreq = ET .SubElement (url ,"changefreq" )
197
+ changefreq .text = "yearly"
198
+
199
+ #ok return xml
200
+ web .header ("Content-Type" , "text/xml; charset=utf-8" )
201
+ return ET .tostring (urlset , encoding = "utf-8" , method = "xml" )
202
+
203
+
204
+
161
205
162
206
#This is the main Admin handler class. All admin functions are executed through POST's
163
207
#utilizing a method=XXX variable passed by an ajax call, a form, etc.
@@ -187,7 +231,7 @@ def GET(self,url):
187
231
#show login page
188
232
return render .fullpageindex ("Please Login to Continue" ,render .login (),"" )
189
233
else :
190
- images = m .Image .get_all ()
234
+ images = m .Image .get_all (private = True )
191
235
return render .fullpageindex ("Logged in as %s" % session .dispname ,render .admin (images ),render .bottom_admin ())
192
236
193
237
def POST (self ,url ):
@@ -265,7 +309,7 @@ def POST(self,url):
265
309
resl = m .Post .all (evenprivate = True )
266
310
return render .datatable_posts (resl )
267
311
elif method == "getallimages" :
268
- images = m .Image .get_all ()
312
+ images = m .Image .get_all (private = True )
269
313
return render .datatable_images (images )
270
314
elif method == "getcomments" :
271
315
id = data .get ("id" ,"-1" )
@@ -274,7 +318,7 @@ def POST(self,url):
274
318
elif method == "getsinglepost" :
275
319
id = data .get ("id" ,"-1" )
276
320
resl = m .Post .get (m .Post .id == id )
277
- images = m .Image .get_all ()
321
+ images = m .Image .get_all (private = True )
278
322
return render .adminsinglepost (resl ,images )
279
323
elif method == "getsingleimage" :
280
324
id = data .get ("id" ,"-1" )
@@ -409,6 +453,35 @@ def GET(self):
409
453
410
454
return render .blogdetail (post ,count ,comments ,next ,prev ,session .logged_in )
411
455
456
+
457
+ class Preview :
458
+ def POST (self ):
459
+ if session .logged_in == False :
460
+ logger .info ("Attempt to get preview page while not logged in!?" )
461
+ return web .notfound ()
462
+ else :
463
+ data = web .input (nifile = {})
464
+ (resl ,msg ) = m .Post .update_from_input (data ,session .uid )
465
+ if resl == None :
466
+ flash ("There was a problem previewing: %s" % msg )
467
+ return web .seeother (urls [0 ])
468
+
469
+ post = resl
470
+ flash ("success" ,"Below is a preview of your posting. To save this switch to the other tab and click \" Update Post\" " )
471
+ count ,comments = m .Comment .get_comments (post .id ,False )
472
+ #for next and prev links
473
+ try :
474
+ next = m .Post .get_next (post .created_at ,1 ).get ()
475
+ except :
476
+ next = None
477
+ try :
478
+ prev = m .Post .get_prev (post .created_at ,1 ).get ()
479
+ except :
480
+ prev = None
481
+
482
+ return render .blogdetail (post ,count ,comments ,next ,prev ,session .logged_in )
483
+
484
+
412
485
class BlogPost :
413
486
def GET (self ):
414
487
pid = - 1
@@ -419,7 +492,7 @@ def GET(self):
419
492
raise Exception
420
493
except :
421
494
flash ("error" , "Sorry, that post doesn't exist!" )
422
- return web .seeother ("/" )
495
+ return web .seeother (urls [ 0 ] )
423
496
424
497
#for next and prev links
425
498
try :
@@ -435,7 +508,9 @@ def GET(self):
435
508
return render .blogdetail (post ,count ,comments ,next ,prev ,session .logged_in )
436
509
class About :
437
510
def GET (self ):
438
- return render .about (m .User .by_id (1 ))
511
+ #TODO: Eventually if we support multple users, fix this
512
+ user = m .User .by_id (1 )
513
+ return render .about (user )
439
514
440
515
class ContactMe :
441
516
def POST (self ):
@@ -471,7 +546,7 @@ def POST(self):
471
546
#failure, return him to homepage with a flash msg
472
547
flash ("error" ,"Sorry, you failed the spam test, post not accepted. Turn on javascript." )
473
548
print "New comment SPAM test failed by %s" % ip
474
- return web .seeother (url [0 ])
549
+ return web .seeother (urls [0 ])
475
550
476
551
postid = websafe (int (data .get ("pid" ,"-1" )))
477
552
text = websafe (data .get ("message" ,None ))
@@ -495,7 +570,7 @@ def POST(self):
495
570
user = m .User .by_id (session .uid )
496
571
author = user .name
497
572
email = user .email
498
- c1 = m .Comment .new (postid ,parentid ,title ,author ,text ,email ,session .logged_in ,ip )
573
+ c1 = m .Comment .new (postid ,parentid ,title ,author ,text ,email ,session .logged_in ,ip , web . sendmail )
499
574
if c1 != None :
500
575
flash ("success" ,"Thanks for joining the discussion!" )
501
576
else :
0 commit comments