Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

git-svn-id: http://micolog.googlecode.com/svn/trunk@75 fd139d67-4554-…

…0410-8437-97b8145f5b4d
  • Loading branch information...
commit e8e4857d6c6633571152ce8b66daba5a850f71ea 1 parent d93bf45
coolchyni authored
Showing with 1,919 additions and 442 deletions.
  1. +267 −329 admin.py
  2. +120 −2 api_rpc.py
  3. +5 −2 app.yaml
  4. +88 −0 app/gmemsess.py
  5. +290 −0 app/pngcanvas.py
  6. +197 −0 app/safecode.py
  7. +75 −0 app/trackback.py
  8. +76 −3 base.py
  9. +131 −11 blog.py
  10. +22 −0 filter.py
  11. +199 −0 micolog_plugin.py
  12. +94 −24 model.py
  13. 0  plugins/__init__.py
  14. +31 −0 plugins/googleAnalytics.py
  15. +1 −0  plugins/wordpress/__init__.py
  16. +32 −0 plugins/wordpress/wordpress.py
  17. +115 −0 plugins/wordpress/wp_import.py
  18. +73 −0 plugins/wordpress/wpimport.html
  19. +8 −0 queue.yaml
  20. +10 −1 static/admin/style.css
  21. +0 −1  theme_files.py
  22. +7 −5 themes/default/templates/base.html
  23. +19 −9 themes/default/templates/comments.html
  24. +5 −0 themes/default/templates/error.html
  25. +8 −1 themes/default/templates/single.html
  26. +1 −1  themes/xuming/templates/base.html
  27. +3 −2 views/admin/base.html
  28. +7 −2 views/admin/entry.html
  29. +9 −47 views/admin/import.html
  30. +11 −2 views/admin/setup.html
  31. +15 −0 views/admin/tools.html
View
596 admin.py
@@ -2,7 +2,7 @@
import wsgiref.handlers
import settings
-
+from micolog_plugin import *
from google.appengine.ext.webapp import template, \
WSGIApplication
@@ -11,13 +11,17 @@
from google.appengine.ext import db
from google.appengine.ext import zipserve
from google.appengine.api import urlfetch
+from google.appengine.api import memcache
+from google.appengine.api.labs import taskqueue
from base import *
from datetime import datetime ,timedelta
import base64,random,math
from django.utils import simplejson
-
-
-
+import pickle
+from model import *
+from app.trackback import TrackBack
+import xmlrpclib
+from xmlrpclib import Fault
class Error404(BaseRequestHandler):
#@printinfo
def get(self,slug=None):
@@ -53,11 +57,20 @@ def get(self):
## self.write(cookiestr)
#self.response.headers.add_header('Set-Cookie', cookiestr)
-
-
+class admin_do_import(BaseRequestHandler):
+ def get(self,slug=None):
+ try:
+ func=getattr(self,'action_'+slug)
+ if func and callable(func):
+ func()
+ else:
+ self.render2('views/admin/error.html',{'message':'This operate has not defined!'})
+ except:
+ self.render2('views/admin/error.html',{'message':'This operate has not defined!'})
+ def action_wordpress(self):
+ self.write("wordpress")
class admin_do_action(BaseRequestHandler):
- @requires_admin
def get(self,slug=None):
try:
func=getattr(self,'action_'+slug)
@@ -67,7 +80,7 @@ def get(self,slug=None):
self.render2('views/admin/error.html',{'message':'This operate has not defined!'})
except:
self.render2('views/admin/error.html',{'message':'This operate has not defined!'})
- @requires_admin
+
def post(self,slug=None):
try:
func=getattr(self,'action_'+slug)
@@ -150,89 +163,147 @@ def action_update_archives(self,slug=None):
entry.update_archive()
self.write('"All entries have been updated."')
-class admin_import_next(BaseRequestHandler):
- @requires_admin
- def get(self,slug=None):
- if self.blog.import_wp:
- categories_list,entries=self.blog.import_wp
- if categories_list:
- next=categories_list.pop(0)
- if next:
- nicename=next['nicename']
- cat=Category.get_by_key_name('cat_'+nicename)
- if not cat:
- cat=Category(key_name='cat_'+nicename)
- cat.name=next['name']
- cat.slug=nicename
- cat.put()
- self.write(simplejson.dumps(('category',next['name'],True)))
- return
-
- if entries:
- next=entries.pop(0)
- if next:
- entry=Entry()
- entry.title=next['title']
- entry.author=self.login_user
- entry.is_wp=True
- #entry.date=datetime.strptime( next['pubDate'],"%a, %d %b %Y %H:%M:%S +0000")
- try:
- entry.date=datetime.strptime( next['pubDate'][:-6],"%a, %d %b %Y %H:%M:%S")
- except:
- try:
- entry.date=datetime.strptime( next['pubDate'][0:19],"%Y-%m-%d %H:%M:%S")
- except:
- entry.date=datetime.now()
- entry.entrytype=next['post_type']
- entry.content=next['content']
+ def action_stop_import(self):
+ memcache.delete("imt")
+ self.write('"ok"')
- entry.excerpt=next['excerpt']
- entry.post_id=next['post_id']
- entry.slug=next['post_name']
- entry.entry_parent=next['post_parent']
- entry.menu_order=next['menu_order']
+ def action_trackback_ping(self):
+ tbUrl=self.param('tbUrl')
+ title=self.param('title')
+ excerpt=self.param('excerpt')
+ url=self.param('url')
+ blog_name=self.param('blog_name')
+ tb=TrackBack(tbUrl,title,excerpt,url,blog_name)
+ tb.ping()
+
+ def action_pingback_ping(self):
+ """Try to notify the server behind `target_uri` that `source_uri`
+ points to `target_uri`. If that fails an `PingbackError` is raised.
+ """
+ source_uri=self.param('source')
+ target_uri=self.param('target')
+ try:
+ response =urlfetch.fetch(target_uri)
+ except:
+ raise PingbackError(32)
+ try:
+ pingback_uri = response.headers['X-Pingback']
+ except KeyError:
+ _pingback_re = re.compile(r'<link rel="pingback" href="([^"]+)" ?/?>(?i)')
+ match = _pingback_re.search(response.data)
+ if match is None:
+ raise PingbackError(33)
+ pingback_uri =urldecode(match.group(1))
+
+ rpc = xmlrpclib.ServerProxy(pingback_uri)
+ try:
+ return rpc.pingback.ping(source_uri, target_uri)
+ except Fault, e:
+ raise PingbackError(e.faultCode)
+ except:
+ raise PingbackError(32)
- for cat in next['categories']:
- nicename=cat
- c=Category.get_by_key_name('cat_'+nicename)
- if c:
- entry.categorie_keys.append(c.key())
- entry.settags(','.join(next['tags']))
-## for tag in next['tags']:
-## entry.tags.append(tag)
+class admin_import_next(BaseRequestHandler):
+ def post(self):
+ try:
+ #global imt
+ imt=memcache.get("imt")
+ import_data=imt.pop()
+ memcache.set('imt',imt)
+ if import_data:
+ try:
+ if import_data[0]=='cat':
+
+ _cat=import_data[1]
+ logging.info("\n1\n%s",_cat)
+ nicename=_cat['slug']
+ cat=Category.get_by_key_name('cat_'+nicename)
+ if not cat:
+ cat=Category(key_name='cat_'+nicename)
+ cat.name=_cat['name']
+ cat.slug=nicename
+ cat.put()
+ elif import_data[0]=='entry':
+ _entry=import_data[1]
+ logging.debug('importing:'+_entry['title'])
+ hashkey=str(hash(_entry['title']))
+ entry=Entry.get_by_key_name(hashkey)
+ if not entry:
+ entry=Entry(key_name=hashkey)
+
+ entry.title=_entry['title']
+ entry.author=self.login_user
+ entry.is_wp=True
+ #entry.date=datetime.strptime( _entry['pubDate'],"%a, %d %b %Y %H:%M:%S +0000")
+ try:
+ entry.date=datetime.strptime( _entry['pubDate'][:-6],"%a, %d %b %Y %H:%M:%S")
+ except:
+ try:
+ entry.date=datetime.strptime( _entry['pubDate'][0:19],"%Y-%m-%d %H:%M:%S")
+ except:
+ entry.date=datetime.now()
+ entry.entrytype=_entry['post_type']
+ entry.content=_entry['content']
+
+ entry.excerpt=_entry['excerpt']
+ entry.post_id=_entry['post_id']
+ entry.slug=_entry['post_name']
+ entry.entry_parent=_entry['post_parent']
+ entry.menu_order=_entry['menu_order']
+
+ for cat in _entry['categories']:
+ c=Category.get_by_key_name('cat_'+cat['slug'])
+ if c:
+ entry.categorie_keys.append(c.key())
+ entry.settags(','.join(_entry['tags']))
+ ## for tag in _entry['tags']:
+ ## entry.tags.append(tag)
+ if _entry['published']:
+ entry.publish(True)
+ else:
+ entry.save()
+ for com in _entry['comments']:
+ try:
+ date=datetime.strptime(com['date'][0:19],"%Y-%m-%d %H:%M:%S")
+ except:
+ date=datetime.now()
+ comment=Comment(author=com['author'],
+ content=com['content'],
+ entry=entry,
+ date=date
+ )
+ try:
+ comment.email=com['email']
+ comment.weburl=com['weburl']
+ except:
+ pass
+ comment.save()
+ finally:
+ queue=taskqueue.Queue("import")
+ queue.add(taskqueue.Task( url="/admin/import_next"))
+ except:
+ logging.info("import error")
- if next['published']:
- entry.publish(True)
- else:
- entry.save()
+ def get(self,slug=None):
+ imt=memcache.get('imt')
+ if imt and imt.cur_do:
+ process=100-math.ceil(imt.count()*100/imt.total)
+ if imt.cur_do[0]=='cat':
+ msg="importing category '%s'"%imt.cur_do[1]['name']
+ elif imt.cur_do[0]=='entry':
+ msg="importing entry '%s'"%imt.cur_do[1]['title']
+ else:
+ msg="start importing..."
+ self.write(simplejson.dumps((process,msg,not process==100)))
+ else:
+ self.write(simplejson.dumps((-1,"Have no data to import!",False)))
- for com in next['comments']:
- try:
- date=datetime.strptime(com['date'][0:19],"%Y-%m-%d %H:%M:%S")
- except:
- date=datetime.now()
- comment=Comment(author=com['author'],
- content=com['content'],
- entry=entry,
- date=date
- )
- try:
- comment.email=com['email']
- comment.weburl=com['weburl']
- except:
- pass
- comment.save()
- self.write(simplejson.dumps(('entry',next['title'],True)))
- return
- self.blog.import_wp=None
- self.write(simplejson.dumps(('Ok','Finished',False)))
class admin_tools(BaseRequestHandler):
def __init__(self):
self.current="config"
- @requires_admin
def get(self,slug=None):
self.render2('views/admin/tools.html')
@@ -241,12 +312,10 @@ class admin_sitemap(BaseRequestHandler):
def __init__(self):
self.current="config"
- @requires_admin
def get(self,slug=None):
self.render2('views/admin/sitemap.html')
- @requires_admin
def post(self):
str_options= self.param('str_options').split(',')
for name in str_options:
@@ -281,232 +350,56 @@ class admin_import(BaseRequestHandler):
def __init__(self):
self.current='config'
- @requires_admin
def get(self,slug=None):
gblog_init()
- self.render2('views/admin/import.html')
-
- @requires_admin
- def post(self):
-
-
- import xml.etree.ElementTree as et
-
-
- link_format=self.param('link_format')
-
- if link_format:
- g_blog.link_format=link_format.strip()
- g_blog.save()
-
- try:
-
- wpfile=self.param('wpfile')
-
- doc=et.fromstring(wpfile)
- #use namespace
- wpns='{http://wordpress.org/export/1.0/}'
-
- contentns="{http://purl.org/rss/1.0/modules/content/}"
- excerptns="{http://wordpress.org/export/1.0/excerpt/}"
- et._namespace_map[wpns]='wp'
- et._namespace_map[contentns]='content'
- et._namespace_map[excerptns]='excerpt'
- channel=doc.find('channel')
- #self.write('Blog:'+channel.findtext('title')+'<br>')
- categories=channel.findall(wpns+'category')
- categories_list=[]
- for cate in categories:
- #self.write('cate:'+cate.findtext(wpns+'cat_name')+'<br>')
-
- nicename=cate.findtext(wpns+'category_nicename')
- name=cate.findtext(wpns+'cat_name')
- categories_list.append({'nicename':nicename,'name':name})
- import time
- items=channel.findall('item')
- entries=[]
- for item in items:
- title=item.findtext('title')
- try:
- #self.write(title+'<br>')
-
- entry={}
- entry['title']=item.findtext('title')
- logging.info(title)
- #entry['author']=self.login_user
- #entry.is_wp=True
- entry['pubDate']=item.findtext('pubDate')
- entry['post_type']=item.findtext(wpns+'post_type')
- entry['content']= item.findtext(contentns+'encoded')
-
- entry['excerpt']= item.findtext(excerptns+'encoded')
- entry['post_id']=int(item.findtext(wpns+'post_id'))
- entry['post_name']=item.findtext(wpns+'post_name')
- entry['post_parent']=int(item.findtext(wpns+'post_parent'))
- entry['menu_order']=int(item.findtext(wpns+'menu_order'))
-
- entry['tags']=[]
- entry['categories']=[]
-
-
- cats=item.findall('category')
-
-
- for cat in cats:
- if cat.attrib.has_key('nicename'):
- cat_type=cat.attrib['domain']
- if cat_type=='tag':
- entry['tags'].append(cat.text)
- else:
- nicename=cat.attrib['nicename']
- entry['categories'].append(nicename)
-
- pub_status=item.findtext(wpns+'status')
- if pub_status=='publish':
- entry['published']=True
- else:
- entry['published']=False
-
- entry['comments']=[]
-
- comments=item.findall(wpns+'comment')
-
- for com in comments:
- try:
- comment_approved=int(com.findtext(wpns+'comment_approved'))
- except:
- comment_approved=0
- if comment_approved:
-
-
- comment=dict(author=com.findtext(wpns+'comment_author'),
- content=com.findtext(wpns+'comment_content'),
- email=com.findtext(wpns+'comment_author_email'),
- weburl=com.findtext(wpns+'comment_author_url'),
- date=com.findtext(wpns+'comment_date')
- )
-
- entry['comments'].append(comment)
- entries.append(entry)
- except :
- import traceback
-
- logging.error('Import ''%s'' error.'%traceback.format_exc(10))
- self.blog.import_wp=(categories_list,entries)
- self.render2('views/admin/import.html',
- {'postback':True})
- except:
- self.render2('views/admin/import.html',{'error':'import faiure.'})
-
-
-
- @requires_admin
- def post_old(self):
- import xml.etree.ElementTree as et
- wpfile=self.param('wpfile')
- doc=et.fromstring(wpfile)
- #use namespace
- wpns='{http://wordpress.org/export/1.0/}'
-
- contentns="{http://purl.org/rss/1.0/modules/content/}"
- et._namespace_map[wpns]='wp'
- et._namespace_map[contentns]='content'
-
- channel=doc.find('channel')
- self.write('Blog:'+channel.findtext('title')+'<br>')
- categories=channel.findall(wpns+'category')
- for cate in categories:
- self.write('cate:'+cate.findtext(wpns+'cat_name')+'<br>')
-
- nicename=cate.findtext(wpns+'category_nicename')
- cat=Category.get_by_key_name('cat_'+nicename)
- if not cat:
- cat=Category(key_name='cat_'+nicename)
- cat.name=cate.findtext(wpns+'cat_name')
- cat.slug=nicename
- cat.put()
-
-## tags=channel.findall(wpns+'tag')
-## for tag in tags:
-## self.write('tag:'+tag.findtext(wpns+'tag_name')+'<br>')
-## ntag=Tag()
-## ntag.tag=tag.findtext(wpns+'tag_name')
-## ntag.put()
- import time
- items=channel.findall('item')
- for item in items:
- title=item.findtext('title')
- try:
- self.write(title+'<br>')
-
- entry=Entry()
- entry.title=item.findtext('title')
- logging.info(title)
- entry.author=self.login_user
- entry.is_wp=True
- entry.date=datetime.strptime( item.findtext('pubDate'),"%a, %d %b %Y %H:%M:%S +0000")
- entry.entrytype=item.findtext(wpns+'post_type')
- entry.content=item.findtext(contentns+'encoded')
- entry.post_id=int(item.findtext(wpns+'post_id'))
- entry.slug=item.findtext(wpns+'post_name')
- entry.entry_parent=int(item.findtext(wpns+'post_parent'))
- entry.menu_order=int(item.findtext(wpns+'menu_order'))
-
-
- cats=item.findall('category')
-
- for cat in cats:
- if cat.attrib.has_key('nicename'):
- cat_type=cat.attrib['domain']
- if cat_type=='tag':
- entry.tags.append(cat.text)
- else:
- nicename=cat.attrib['nicename']
- c=Category.get_by_key_name('cat_'+nicename)
- if c:
- entry.categorie_keys.append(c.key())
-
- pub_status=item.findtext(wpns+'status')
- if pub_status=='publish':
- entry.publish(True)
- else:
- entry.save()
-
- comments=item.findall(wpns+'comment')
-
- for com in comments:
- try:
- comment_approved=int(com.findtext(wpns+'comment_approved'))
- except:
- comment_approved=0
- if comment_approved:
-
- comment=Comment(author=com.findtext(wpns+'comment_author'),
- content=com.findtext(wpns+'comment_content'),
- entry=entry,
- )
- try:
- comment.email=com.findtext(wpns+'comment_author_email')
- comment.weburl=com.findtext(wpns+'comment_author_url')
- except:
- pass
- comment.put()
- except :
- import traceback
-
- self.write('Import ''%s'' error.<br>'%title)
- logging.error('Import ''%s'' error.'%traceback.format_exc(10))
+ self.render2('views/admin/import.html',{'importitems':
+ self.blog.plugins.filter('is_import_plugin',True)})
+
+## def post(self):
+## try:
+## queue=taskqueue.Queue("import")
+## wpfile=self.param('wpfile')
+## #global imt
+## imt=import_wordpress(wpfile)
+## imt.parse()
+## memcache.set("imt",imt)
+##
+#### import_data=OptionSet.get_or_insert(key_name="import_data")
+#### import_data.name="import_data"
+#### import_data.bigvalue=pickle.dumps(imt)
+#### import_data.put()
+##
+## queue.add(taskqueue.Task( url="/admin/import_next"))
+## self.render2('views/admin/import.html',
+## {'postback':True})
+## return
+## memcache.set("import_info",{'count':len(imt.entries),'msg':'Begin import...','index':1})
+## #self.blog.import_info={'count':len(imt.entries),'msg':'Begin import...','index':1}
+## if imt.categories:
+## queue.add(taskqueue.Task( url="/admin/import_next",params={'cats': pickle.dumps(imt.categories),'index':1}))
+##
+## return
+## index=0
+## if imt.entries:
+## for entry in imt.entries :
+## try:
+## index=index+1
+## queue.add(taskqueue.Task(url="/admin/import_next",params={'entry':pickle.dumps(entry),'index':index}))
+## except:
+## pass
+##
+## except:
+## self.render2('views/admin/import.html',{'error':'import faiure.'})
class admin_setup(BaseRequestHandler):
def __init__(self):
self.current='config'
- @requires_admin
+ #@requires_admin
def get(self,slug=None):
vals={'themes':ThemeIterator()}
self.render2('views/admin/setup.html',vals)
- @requires_admin
def post(self):
old_theme=g_blog.theme_name
str_options= self.param('str_options').split(',')
@@ -550,7 +443,6 @@ def __init__(self):
self.current='write'
- @requires_admin
def get(self,slug='post'):
action=self.param("action")
entry=None
@@ -571,7 +463,6 @@ def mapit(cat):
vals={'action':action,'entry':entry,'entrytype':slug,'cats':map(mapit,cats)}
self.render2('views/admin/entry.html',vals)
- @requires_admin
def post(self,slug='post'):
action=self.param("action")
title=self.param("post_title")
@@ -580,7 +471,8 @@ def post(self,slug='post'):
cats=self.request.get_all('cats')
key=self.param('key')
published=self.param('publish')
- allow_comment=self.param('allow_comment')
+ allow_comment=self.parambool('allow_comment')
+ allow_trackback=self.parambool('allow_trackback')
entry_slug=self.param('slug')
entry_parent=self.paramint('entry_parent')
menu_order=self.paramint('menu_order')
@@ -595,7 +487,9 @@ def mapit(cat):
vals={'action':action,'postback':True,'cats':Category.all(),'entrytype':slug,
'cats':map(mapit,Category.all()),
- 'entry':{ 'title':title,'content':content,'strtags':tags,'key':key,'published':published,'allow_comment':allow_comment,
+ 'entry':{ 'title':title,'content':content,'strtags':tags,'key':key,'published':published,
+ 'allow_comment':allow_comment,
+ 'allow_trackback':allow_trackback,
'slug':entry_slug,
'entry_parent':entry_parent,
'excerpt':entry_excerpt,
@@ -620,10 +514,8 @@ def mapit(cat):
entry.target=target
entry.external_page_address=external_page_address
newcates=[]
- if allow_comment:
- entry.allow_comment= True
- else:
- entry.allow_comment = False
+ entry.allow_comment=allow_comment
+ entry.allow_trackback=allow_trackback
if cats:
@@ -661,10 +553,8 @@ def mapit(cat):
if c:
newcates.append(c[0].key())
entry.categorie_keys=newcates;
- if allow_comment:
- entry.allow_comment= True
- else:
- entry.allow_comment = False
+ entry.allow_comment=allow_comment
+ entry.allow_trackback=allow_trackback
if published:
entry.publish()
@@ -680,7 +570,6 @@ def mapit(cat):
class admin_entries(BaseRequestHandler):
- @requires_admin
def get(self,slug='post'):
try:
page_index=int(self.param('page'))
@@ -701,7 +590,6 @@ def get(self,slug='post'):
}
)
- @requires_admin
def post(self,slug='post'):
try:
linkcheck= self.request.get_all('checks')
@@ -721,7 +609,6 @@ def post(self,slug='post'):
class admin_categories(BaseRequestHandler):
- @requires_admin
def get(self,slug=None):
try:
page_index=int(self.param('page'))
@@ -742,7 +629,6 @@ def get(self,slug=None):
}
)
- @requires_admin
def post(self,slug=None):
try:
linkcheck= self.request.get_all('checks')
@@ -754,7 +640,6 @@ def post(self,slug=None):
self.redirect('/admin/categories')
class admin_comments(BaseRequestHandler):
- @requires_admin
def get(self,slug=None):
try:
page_index=int(self.param('page'))
@@ -775,7 +660,6 @@ def get(self,slug=None):
}
)
- @requires_admin
def post(self,slug=None):
try:
linkcheck= self.request.get_all('checks')
@@ -787,7 +671,6 @@ def post(self,slug=None):
self.redirect('/admin/comments')
class admin_links(BaseRequestHandler):
- @requires_admin
def get(self,slug=None):
self.render2('views/admin/links.html',
{
@@ -804,7 +687,6 @@ def post(self):
self.redirect('/admin/links')
class admin_link(BaseRequestHandler):
- @requires_admin
def get(self,slug=None):
action=self.param("action")
vals={'current':'links'}
@@ -855,7 +737,7 @@ def post(self):
class admin_category(BaseRequestHandler):
def __init__(self):
self.current='categories'
- @requires_admin
+
def get(self,slug=None):
action=self.param("action")
category=None
@@ -871,7 +753,6 @@ def get(self,slug=None):
vals={'action':action,'category':category}
self.render2('views/admin/category.html',vals)
- @requires_admin
def post(self):
action=self.param("action")
name=self.param("name")
@@ -901,11 +782,9 @@ def post(self):
self.render2('views/admin/category.html',vals)
class admin_status(BaseRequestHandler):
- @requires_admin
def get(self):
self.render2('views/admin/status.html',{'cache':memcache.get_stats(),'current':'status','environ':os.environ})
class admin_authors(BaseRequestHandler):
- @requires_admin
def get(self):
try:
page_index=int(self.param('page'))
@@ -927,7 +806,6 @@ def get(self):
)
- @requires_admin
def post(self,slug=None):
try:
linkcheck= self.request.get_all('checks')
@@ -941,7 +819,6 @@ class admin_author(BaseRequestHandler):
def __init__(self):
self.current='authors'
- @requires_admin
def get(self,slug=None):
action=self.param("action")
author=None
@@ -957,7 +834,6 @@ def get(self,slug=None):
vals={'action':action,'author':author}
self.render2('views/admin/author.html',vals)
- @requires_admin
def post(self):
action=self.param("action")
name=self.param("name")
@@ -985,10 +861,71 @@ def post(self):
except:
vals.update({'result':False,'msg':'Error:Author can''t been saved.'})
self.render2('views/admin/author.html',vals)
+class admin_plugins(BaseRequestHandler):
+ def __init__(self):
+ self.current='plugins'
-class WpHandler(BaseRequestHandler):
+ def get(self,slug=None):
+ vals={'plugins':self.blog.plugins}
+ self.render2('views/admin/plugins.html',vals)
+
+ def post(self):
+ action=self.param("action")
+ name=self.param("plugin")
+ ret=self.param("return")
+ self.blog.plugins.activate(name,action=="activate")
+ if ret:
+ self.redirect(ret)
+ else:
+ vals={'plugins':self.blog.plugins}
+ self.render2('views/admin/plugins.html',vals)
+
+class admin_plugins_action(BaseRequestHandler):
+ def __init__(self):
+ self.current='plugins'
+
+ def get(self,slug=None):
+ plugin=self.blog.plugins.getPluginByName(slug)
+ if not plugin :
+ self.error(404)
+ return
+ plugins=self.blog.plugins.filter('active',True)
+ if not plugin.active:
+ pcontent='''<div>Plugin '%s' havn't actived!</div><br><form method="post" action="/admin/plugins?action=activate&amp;plugin=%s&amp;return=/admin/plugins/%s">
+<input type="submit" value="Activate Now"/></form>'''%(plugin.name,plugin.iname,plugin.iname)
+ plugins.insert(0,plugin)
+ else:
+ pcontent=plugin.get(self)
- @requires_admin
+
+ vals={'plugins':plugins,
+ 'plugin':plugin,
+ 'pcontent':pcontent}
+
+ self.render2('views/admin/plugin_action.html',vals)
+
+ def post(self,slug=None):
+
+ plugin=self.blog.plugins.getPluginByName(slug)
+ if not plugin :
+ self.error(404)
+ return
+ plugins=self.blog.plugins.filter('active',True)
+ if not plugin.active:
+ pcontent='''<div>Plugin '%s' havn't actived!</div><br><form method="post" action="/admin/plugins?action=activate&amp;plugin=%s&amp;return=/admin/plugins/%s">
+<input type="submit" value="Activate Now"/></form>'''%(plugin.name,plugin.iname,plugin.iname)
+ plugins.insert(0,plugin)
+ else:
+ pcontent=plugin.post(self)
+
+
+ vals={'plugins':plugins,
+ 'plugin':plugin,
+ 'pcontent':pcontent}
+
+ self.render2('views/admin/plugin_action.html',vals)
+
+class WpHandler(BaseRequestHandler):
def get(self,tags=None):
try:
all=self.param('all')
@@ -1034,10 +971,11 @@ def main():
('/admin/status',admin_status),
('/admin/authors',admin_authors),
('/admin/author',admin_author),
-
('/admin/import',admin_import),
+ ('/admin/import/(\w+)',admin_do_import),
('/admin/tools',admin_tools),
-
+ ('/admin/plugins',admin_plugins),
+ ('/admin/plugins/(\w+)',admin_plugins_action),
('/admin/sitemap',admin_sitemap),
('/admin/export/micolog.xml',WpHandler),
('/admin/import_next',admin_import_next),
View
122 api_rpc.py
@@ -1,16 +1,19 @@
# -*- coding: utf-8 -*-
import wsgiref.handlers
import xmlrpclib
+from xmlrpclib import Fault
import sys
import cgi
import base64
from datetime import datetime
from SimpleXMLRPCServer import SimpleXMLRPCDispatcher
from functools import wraps
-
+from django.utils.html import strip_tags
sys.path.append('modules')
from base import *
from model import *
+from micolog_plugin import *
+from urlparse import urlparse
def checkauth(pos=1):
def _decorate(method):
@@ -106,8 +109,14 @@ def metaWeblog_newPost(blogid, struct, publish):
if struct.has_key('mt_excerpt'):
entry.excerpt=struct['mt_excerpt']
+ if struct.has_key('wp_password'):
+ entry.password=struct['wp_password']
+
if publish:
entry.publish(True)
+ if struct.has_key('mt_tb_ping_urls'):
+ for url in struct['mt_tb_ping_urls']:
+ util.do_trackback(url,entry.title,entry.get_content_excerpt(more='')[:60],entry.fullurl(),g_blog.title)
else:
entry.save()
postid =entry.key().id()
@@ -145,6 +154,9 @@ def metaWeblog_editPost(postid, struct, publish):
if struct.has_key('mt_excerpt'):
entry.excerpt=struct['mt_excerpt']
+ if struct.has_key('wp_password'):
+ entry.password=struct['wp_password']
+
entry.title = struct['title']
entry.content = struct['description']
@@ -220,6 +232,8 @@ def wp_newPage(blogid,struct,publish):
entry.slug=struct['wp_slug']
if struct.has_key('wp_page_order'):
entry.menu_order=int(struct['wp_page_order'])
+ if struct.has_key('wp_password'):
+ entry.password=struct['wp_password']
entry.entrytype='page'
if publish:
entry.publish(True)
@@ -254,6 +268,8 @@ def wp_editPage(blogid,pageid,struct,publish):
if struct.has_key('wp_page_order'):
entry.menu_order=int(struct['wp_page_order'])
+ if struct.has_key('wp_password'):
+ entry.password=struct['wp_password']
entry.title = struct['title']
entry.content = struct['description']
@@ -298,8 +314,107 @@ def mt_getPostCategories(blogid):
def mt_setPostCategories(*arg):
return True
-#-------------------------------------------------------------------------------
+#------------------------------------------------------------------------------
+#pingback
+#------------------------------------------------------------------------------
+_title_re = re.compile(r'<title>(.*?)</title>(?i)')
+_pingback_re = re.compile(r'<link rel="pingback" href="([^"]+)" ?/?>(?i)')
+_chunk_re = re.compile(r'\n\n|<(?:p|div|h\d)[^>]*>')
+def pingback_ping(source_uri, target_uri):
+ # next we check if the source URL does indeed exist
+ if not g_blog.allow_pingback:
+ raise Fault(49,"Access denied.")
+ try:
+
+ g_blog.tigger_action("pre_ping",source_uri,target_uri)
+ response = urlfetch.fetch(source_uri)
+ except Exception ,e :
+ #logging.info(e.message)
+ raise Fault(16, 'The source URL does not exist.%s'%source_uri)
+ # we only accept pingbacks for links below our blog URL
+ blog_url = g_blog.baseurl
+ if not blog_url.endswith('/'):
+ blog_url += '/'
+ if not target_uri.startswith(blog_url):
+ raise Fault(32, 'The specified target URL does not exist.')
+ path_info = target_uri[len(blog_url):]
+
+ pingback_post(response,source_uri,target_uri,path_info)
+ try:
+
+ return "Micolog pingback succeed!"
+ except:
+ raise Fault(49,"Access denied.")
+
+
+def get_excerpt(response, url_hint, body_limit=1024 * 512):
+ """Get an excerpt from the given `response`. `url_hint` is the URL
+ which will be used as anchor for the excerpt. The return value is a
+ tuple in the form ``(title, body)``. If one of the two items could
+ not be calculated it will be `None`.
+ """
+ contents = response.content[:body_limit]
+
+ title_match = _title_re.search(contents)
+ title = title_match and strip_tags(title_match.group(1)) or None
+
+ link_re = re.compile(r'<a[^>]+?"\s*%s\s*"[^>]*>(.*?)</a>(?is)' %
+ re.escape(url_hint))
+ for chunk in _chunk_re.split(contents):
+ match = link_re.search(chunk)
+ if not match:
+ continue
+ before = chunk[:match.start()]
+ after = chunk[match.end():]
+ raw_body = '%s\0%s' % (strip_tags(before).replace('\0', ''),
+ strip_tags(after).replace('\0', ''))
+ body_match = re.compile(r'(?:^|\b)(.{0,120})\0(.{0,120})(?:\b|$)') \
+ .search(raw_body)
+ if body_match:
+ break
+ else:
+ return title, None
+
+
+ before, after = body_match.groups()
+ link_text = strip_tags(match.group(1))
+ if len(link_text) > 60:
+ link_text = link_text[:60] + u''
+
+ bits = before.split()
+ bits.append(link_text)
+ bits.extend(after.split())
+ return title, u'[…] %s […]' % u' '.join(bits)
+
+def pingback_post(response,source_uri, target_uri, slug):
+ """This is the pingback handler for posts."""
+ entry = Entry.all().filter("published =", True).filter('link =', slug).get()
+ #use allow_trackback as allow_pingback
+ if entry is None or not entry.allow_trackback:
+ raise Fault(33, 'no such post')
+ title, excerpt = get_excerpt(response, target_uri)
+ if not title:
+ raise Fault(17, 'no title provided')
+ elif not excerpt:
+ raise Fault(17, 'no useable link to target')
+
+ comment = Comment.all().filter("entry =", entry).filter("weburl =", source_uri).get()
+ if comment:
+ raise Fault(48, 'pingback has already been registered')
+ return
+
+ comment=Comment(author=urlparse(source_uri).hostname,
+ content="<strong>"+title[:250]+"...</strong><br/>" +
+ excerpt[:250] + '...',
+ weburl=source_uri,
+ entry=entry)
+ comment.ctype=COMMENT_PINGBACK
+ comment.save()
+ g_blog.tigger_action("pingback_post",comment)
+ memcache.delete("/"+entry.link)
+ return True
+##------------------------------------------------------------------------------
class PlogXMLRPCDispatcher(SimpleXMLRPCDispatcher):
def __init__(self, funcs):
SimpleXMLRPCDispatcher.__init__(self, True, 'utf-8')
@@ -329,6 +444,9 @@ def __init__(self, funcs):
'mt.setPostCategories':mt_setPostCategories,
'mt.getPostCategories':mt_getPostCategories,
+ ##pingback
+ 'pingback.ping':pingback_ping,
+
})
View
7 app.yaml
@@ -1,4 +1,4 @@
-application: mlog
+application: micolog
version: 1
runtime: python
api_version: 1
@@ -9,7 +9,7 @@ handlers:
static_files: static/images/favicon.ico
upload: static/images/favicon.ico
mime_type: image/x-icon
-
+
- url: /robots\.txt
static_files: static/robots.txt
upload: static/robots.txt
@@ -32,9 +32,12 @@ handlers:
- url: /admin/.*
script: admin.py
+ login: admin
+
- url: /admin
script: admin.py
+ login: admin
- url: /.*
script: blog.py
View
88 app/gmemsess.py
@@ -0,0 +1,88 @@
+# gmemsess.py - memcache-backed session Class for Google Appengine
+# Version 1.4
+# Copyright 2008 Greg Fawcett <greg@vig.co.nz>
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+import random
+from google.appengine.api import memcache
+
+_sidChars='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
+_defaultTimeout=30*60 # 30 min
+_defaultCookieName='gsid'
+
+#----------------------------------------------------------------------
+class Session(dict):
+ """A secure lightweight memcache-backed session Class for Google Appengine."""
+
+ #----------------------------------------------------------
+ def __init__(self,rh,name=_defaultCookieName,timeout=_defaultTimeout):
+ """Create a session object.
+
+ Keyword arguments:
+ rh -- the parent's request handler (usually self)
+ name -- the cookie name (defaults to "gsid")
+ timeout -- the number of seconds the session will last between
+ requests (defaults to 1800 secs - 30 minutes)
+ """
+ self.rh=rh # request handler
+ self._timeout=timeout
+ self._name=name
+ self._new=True
+ self._invalid=False
+ dict.__init__(self)
+
+ if name in rh.request.str_cookies:
+ self._sid=rh.request.str_cookies[name]
+ data=memcache.get(self._sid)
+ if data!=None:
+ self.update(data)
+ # memcache timeout is absolute, so we need to reset it on each access
+ memcache.set(self._sid,data,self._timeout)
+ self._new=False
+ return
+
+ # Create a new session ID
+ # There are about 10^14 combinations, so guessing won't work
+ self._sid=random.choice(_sidChars)+random.choice(_sidChars)+\
+ random.choice(_sidChars)+random.choice(_sidChars)+\
+ random.choice(_sidChars)+random.choice(_sidChars)+\
+ random.choice(_sidChars)+random.choice(_sidChars)
+ # Added path so session works with any path
+ rh.response.headers.add_header('Set-Cookie','%s=%s; path=/;'%(name,self._sid))
+
+ #----------------------------------------------------------
+ def save(self):
+ """Save session data."""
+ if not self._invalid:
+ memcache.set(self._sid,self.copy(),self._timeout)
+
+ #----------------------------------------------------------
+ def is_new(self):
+ """Returns True if session was created during this request."""
+ return self._new
+
+ #----------------------------------------------------------
+ def get_id(self):
+ """Returns session id string."""
+ return self._sid
+
+ #----------------------------------------------------------
+ def invalidate(self):
+ """Delete session data and cookie."""
+ self.rh.response.headers.add_header('Set-Cookie',
+ '%s=; expires=Sat, 1-Jan-2000 00:00:00 GMT;'%(self._name))
+ memcache.delete(self._sid)
+ self.clear()
+ self._invalid=True
View
290 app/pngcanvas.py
@@ -0,0 +1,290 @@
+#!/usr/bin/env python
+
+"""Simple PNG Canvas for Python"""
+__version__ = "0.8"
+__author__ = "Rui Carmo (http://the.taoofmac.com)"
+__copyright__ = "CC Attribution-NonCommercial-NoDerivs 2.0 Rui Carmo"
+__contributors__ = ["http://collaboa.weed.rbse.com/repository/file/branches/pgsql/lib/spark_pr.rb"], ["Eli Bendersky"]
+
+import zlib, struct
+
+signature = struct.pack("8B", 137, 80, 78, 71, 13, 10, 26, 10)
+
+# alpha blends two colors, using the alpha given by c2
+def blend(c1, c2):
+ return [c1[i]*(0xFF-c2[3]) + c2[i]*c2[3] >> 8 for i in range(3)]
+
+# calculate a new alpha given a 0-0xFF intensity
+def intensity(c,i):
+ return [c[0],c[1],c[2],(c[3]*i) >> 8]
+
+# calculate perceptive grayscale value
+def grayscale(c):
+ return int(c[0]*0.3 + c[1]*0.59 + c[2]*0.11)
+
+# calculate gradient colors
+def gradientList(start,end,steps):
+ delta = [end[i] - start[i] for i in range(4)]
+ grad = []
+ for i in range(steps+1):
+ grad.append([start[j] + (delta[j]*i)/steps for j in range(4)])
+ return grad
+
+class PNGCanvas:
+ def __init__(self, width, height,bgcolor=[0xff,0xff,0xff,0xff],color=[0,0,0,0xff]):
+ self.canvas = []
+ self.width = width
+ self.height = height
+ self.color = color #rgba
+ bgcolor = bgcolor[0:3] # we don't need alpha for background
+ for i in range(height):
+ self.canvas.append([bgcolor] * width)
+
+ def point(self,x,y,color=None):
+ if x<0 or y<0 or x>self.width-1 or y>self.height-1: return
+ if color == None: color = self.color
+ self.canvas[y][x] = blend(self.canvas[y][x],color)
+
+ def _rectHelper(self,x0,y0,x1,y1):
+ x0, y0, x1, y1 = int(x0), int(y0), int(x1), int(y1)
+ if x0 > x1: x0, x1 = x1, x0
+ if y0 > y1: y0, y1 = y1, y0
+ return [x0,y0,x1,y1]
+
+ def verticalGradient(self,x0,y0,x1,y1,start,end):
+ x0, y0, x1, y1 = self._rectHelper(x0,y0,x1,y1)
+ grad = gradientList(start,end,y1-y0)
+ for x in range(x0, x1+1):
+ for y in range(y0, y1+1):
+ self.point(x,y,grad[y-y0])
+
+ def rectangle(self,x0,y0,x1,y1):
+ x0, y0, x1, y1 = self._rectHelper(x0,y0,x1,y1)
+ self.polyline([[x0,y0],[x1,y0],[x1,y1],[x0,y1],[x0,y0]])
+
+ def filledRectangle(self,x0,y0,x1,y1):
+ x0, y0, x1, y1 = self._rectHelper(x0,y0,x1,y1)
+ for x in range(x0, x1+1):
+ for y in range(y0, y1+1):
+ self.point(x,y,self.color)
+
+ def copyRect(self,x0,y0,x1,y1,dx,dy,destination):
+ x0, y0, x1, y1 = self._rectHelper(x0,y0,x1,y1)
+ for x in range(x0, x1+1):
+ for y in range(y0, y1+1):
+ destination.canvas[dy+y-y0][dx+x-x0] = self.canvas[y][x]
+
+ def blendRect(self,x0,y0,x1,y1,dx,dy,destination,alpha=0xff):
+ x0, y0, x1, y1 = self._rectHelper(x0,y0,x1,y1)
+ for x in range(x0, x1+1):
+ for y in range(y0, y1+1):
+ rgba = self.canvas[y][x] + [alpha]
+ destination.point(dx+x-x0,dy+y-y0,rgba)
+
+ # draw a line using Xiaolin Wu's antialiasing technique
+ def line(self,x0, y0, x1, y1):
+ # clean params
+ x0, y0, x1, y1 = int(x0), int(y0), int(x1), int(y1)
+ if y0>y1:
+ y0, y1, x0, x1 = y1, y0, x1, x0
+ dx = x1-x0
+ if dx < 0:
+ sx = -1
+ else:
+ sx = 1
+ dx *= sx
+ dy = y1-y0
+
+ # 'easy' cases
+ if dy == 0:
+ for x in range(x0,x1,sx):
+ self.point(x, y0)
+ return
+ if dx == 0:
+ for y in range(y0,y1):
+ self.point(x0, y)
+ self.point(x1, y1)
+ return
+ if dx == dy:
+ for x in range(x0,x1,sx):
+ self.point(x, y0)
+ y0 = y0 + 1
+ return
+
+ # main loop
+ self.point(x0, y0)
+ e_acc = 0
+ if dy > dx: # vertical displacement
+ e = (dx << 16) / dy
+ for i in range(y0,y1-1):
+ e_acc_temp, e_acc = e_acc, (e_acc + e) & 0xFFFF
+ if (e_acc <= e_acc_temp):
+ x0 = x0 + sx
+ w = 0xFF-(e_acc >> 8)
+ self.point(x0, y0, intensity(self.color,(w)))
+ y0 = y0 + 1
+ self.point(x0 + sx, y0, intensity(self.color,(0xFF-w)))
+ self.point(x1, y1)
+ return
+
+ # horizontal displacement
+ e = (dy << 16) / dx
+ for i in range(x0,x1-sx,sx):
+ e_acc_temp, e_acc = e_acc, (e_acc + e) & 0xFFFF
+ if (e_acc <= e_acc_temp):
+ y0 = y0 + 1
+ w = 0xFF-(e_acc >> 8)
+ self.point(x0, y0, intensity(self.color,(w)))
+ x0 = x0 + sx
+ self.point(x0, y0 + 1, intensity(self.color,(0xFF-w)))
+ self.point(x1, y1)
+
+ def polyline(self,arr):
+ for i in range(0,len(arr)-1):
+ self.line(arr[i][0],arr[i][1],arr[i+1][0], arr[i+1][1])
+
+ def dump(self):
+ raw_list = []
+ for y in range(self.height):
+ raw_list.append(chr(0)) # filter type 0 (None)
+ for x in range(self.width):
+ raw_list.append(struct.pack("!3B",*self.canvas[y][x]))
+ raw_data = ''.join(raw_list)
+
+ # 8-bit image represented as RGB tuples
+ # simple transparency, alpha is pure white
+ return signature + \
+ self.pack_chunk('IHDR', struct.pack("!2I5B",self.width,self.height,8,2,0,0,0)) + \
+ self.pack_chunk('tRNS', struct.pack("!6B",0xFF,0xFF,0xFF,0xFF,0xFF,0xFF)) + \
+ self.pack_chunk('IDAT', zlib.compress(raw_data,9)) + \
+ self.pack_chunk('IEND', '')
+
+ def pack_chunk(self,tag,data):
+ to_check = tag + data
+ return struct.pack("!I",len(data)) + to_check + struct.pack("!I", zlib.crc32(to_check) & 0xFFFFFFFF)
+
+ def load(self,f):
+ assert f.read(8) == signature
+ self.canvas=[]
+ for tag, data in self.chunks(f):
+ if tag == "IHDR":
+ ( width,
+ height,
+ bitdepth,
+ colortype,
+ compression, filter, interlace ) = struct.unpack("!2I5B",data)
+ self.width = width
+ self.height = height
+ if (bitdepth,colortype,compression, filter, interlace) != (8,2,0,0,0):
+ raise TypeError('Unsupported PNG format')
+ # we ignore tRNS because we use pure white as alpha anyway
+ elif tag == 'IDAT':
+ raw_data = zlib.decompress(data)
+ rows = []
+ i = 0
+ for y in range(height):
+ filtertype = ord(raw_data[i])
+ i = i + 1
+ cur = [ord(x) for x in raw_data[i:i+width*3]]
+ if y == 0:
+ rgb = self.defilter(cur,None,filtertype)
+ else:
+ rgb = self.defilter(cur,prev,filtertype)
+ prev = cur
+ i = i+width*3
+ row = []
+ j = 0
+ for x in range(width):
+ pixel = rgb[j:j+3]
+ row.append(pixel)
+ j = j + 3
+ self.canvas.append(row)
+
+ def defilter(self,cur,prev,filtertype,bpp=3):
+ if filtertype == 0: # No filter
+ return cur
+ elif filtertype == 1: # Sub
+ xp = 0
+ for xc in range(bpp,len(cur)):
+ cur[xc] = (cur[xc] + cur[xp]) % 256
+ xp = xp + 1
+ elif filtertype == 2: # Up
+ for xc in range(len(cur)):
+ cur[xc] = (cur[xc] + prev[xc]) % 256
+ elif filtertype == 3: # Average
+ xp = 0
+ for xc in range(len(cur)):
+ cur[xc] = (cur[xc] + (cur[xp] + prev[xc])/2) % 256
+ xp = xp + 1
+ elif filtertype == 4: # Paeth
+ xp = 0
+ for i in range(bpp):
+ cur[i] = (cur[i] + prev[i]) % 256
+ for xc in range(bpp,len(cur)):
+ a = cur[xp]
+ b = prev[xc]
+ c = prev[xp]
+ p = a + b - c
+ pa = abs(p - a)
+ pb = abs(p - b)
+ pc = abs(p - c)
+ if pa <= pb and pa <= pc:
+ value = a
+ elif pb <= pc:
+ value = b
+ else:
+ value = c
+ cur[xc] = (cur[xc] + value) % 256
+ xp = xp + 1
+ else:
+ raise TypeError('Unrecognized scanline filter type')
+ return cur
+
+ def chunks(self,f):
+ while 1:
+ try:
+ length = struct.unpack("!I",f.read(4))[0]
+ tag = f.read(4)
+ data = f.read(length)
+ crc = struct.unpack("!i",f.read(4))[0]
+ except:
+ return
+ if zlib.crc32(tag + data) != crc:
+ raise IOError
+ yield [tag,data]
+
+if __name__ == '__main__':
+ width = 128
+ height = 64
+ print "Creating Canvas..."
+ c = PNGCanvas(width,height)
+ c.color = [0xff,0,0,0xff]
+ c.rectangle(0,0,width-1,height-1)
+ print "Generating Gradient..."
+ c.verticalGradient(1,1,width-2, height-2,[0xff,0,0,0xff],[0x20,0,0xff,0x80])
+ print "Drawing Lines..."
+ c.color = [0,0,0,0xff]
+ c.line(0,0,width-1,height-1)
+ c.line(0,0,width/2,height-1)
+ c.line(0,0,width-1,height/2)
+ # Copy Rect to Self
+ print "Copy Rect"
+ c.copyRect(1,1,width/2-1,height/2-1,0,height/2,c)
+ # Blend Rect to Self
+ print "Blend Rect"
+ c.blendRect(1,1,width/2-1,height/2-1,width/2,0,c)
+ # Write test
+ print "Writing to file..."
+ f = open("test.png", "wb")
+ f.write(c.dump())
+ f.close()
+ # Read test
+ print "Reading from file..."
+ f = open("test.png", "rb")
+ c.load(f)
+ f.close()
+ # Write back
+ print "Writing to new file..."
+ f = open("recycle.png","wb")
+ f.write(c.dump())
+ f.close()
View
197 app/safecode.py
@@ -0,0 +1,197 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+#
+# Copyright(C) 2008 SupDo.com
+# Licensed under the GUN License, Version 3.0 (the "License");
+#
+# File: safecode.py
+# Author: KuKei
+# Create Date: 2008-07-16
+# Description: 负责验证码生成。
+# Modify Date: 2008-08-06
+
+import md5
+import random
+from pngcanvas import PNGCanvas
+
+class Image():
+ text = None
+ md5Text = None
+ img = None
+ width = 0
+ height = 0
+ #长度
+ textX = 10
+ textY = 10
+ beginX = 5
+ endX = 5
+ beginY = 5
+ endY = 5
+ spare = 4
+
+ def __init__(self,text=None):
+ if(text==None):
+ self.text = self.getRandom()
+ else:
+ self.text = text
+ #self.getMd5Text()
+ self.width = len(str(self.text))*(self.spare+self.textX)+self.beginX+self.endX
+ self.height = self.textY + self.beginY + self.endY
+
+ def create(self):
+ self.img = PNGCanvas(self.width,self.height)
+ self.img.color = [0xff,0xff,0xff,0xff]
+ #self.img.color = [0x39,0x9e,0xff,0xff]
+ #self.img.verticalGradient(1,1,self.width-2, self.height-2,[0xff,0,0,0xff],[0x60,0,0xff,0x80])
+ self.img.verticalGradient(1,1,self.width-2, self.height-2,[0xff,0x45,0x45,0xff],[0xff,0xcb,0x44,0xff])
+
+ for i in range(4):
+ a = str(self.text)[i]
+ self.writeText(a,i)
+
+ return self.img.dump()
+
+ def getRandom(self):
+ intRand = random.randrange(1000,9999)
+ return intRand
+
+ def getMd5Text(self):
+ m = md5.new()
+ m.update(str(self.text))
+ self.md5Text = m.hexdigest()
+
+ def writeText(self,text,pos=0):
+ if(text=="1"):
+ self.writeLine(pos, "avc")
+ elif(text=="2"):
+ self.writeLine(pos, "aht")
+ self.writeLine(pos, "hvtr")
+ self.writeLine(pos, "ahc")
+ self.writeLine(pos, "hvbl")
+ self.writeLine(pos, "ahb")
+ elif(text=="3"):
+ self.writeLine(pos, "aht")
+ self.writeLine(pos, "ahc")
+ self.writeLine(pos, "ahb")
+ self.writeLine(pos, "avr")
+ elif(text=="4"):
+ self.writeLine(pos, "hvtl")
+ self.writeLine(pos, "ahc")
+ self.writeLine(pos, "avc")
+ elif(text=="5"):
+ self.writeLine(pos, "aht")
+ self.writeLine(pos, "hvtl")
+ self.writeLine(pos, "ahc")
+ self.writeLine(pos, "hvbr")
+ self.writeLine(pos, "ahb")
+ elif(text=="6"):
+ self.writeLine(pos, "aht")
+ self.writeLine(pos, "avl")
+ self.writeLine(pos, "ahc")
+ self.writeLine(pos, "hvbr")
+ self.writeLine(pos, "ahb")
+ elif(text=="7"):
+ self.writeLine(pos, "aht")
+ self.writeLine(pos, "avr")
+ elif(text=="8"):
+ self.writeLine(pos, "aht")
+ self.writeLine(pos, "avl")
+ self.writeLine(pos, "ahc")
+ self.writeLine(pos, "avr")
+ self.writeLine(pos, "ahb")
+ elif(text=="9"):
+ self.writeLine(pos, "aht")
+ self.writeLine(pos, "avr")
+ self.writeLine(pos, "ahc")
+ self.writeLine(pos, "ahb")
+ self.writeLine(pos, "hvtl")
+ elif(text=="0"):
+ self.writeLine(pos, "aht")
+ self.writeLine(pos, "avl")
+ self.writeLine(pos, "avr")
+ self.writeLine(pos, "ahb")
+
+ '''
+ type解释
+ a:全部,部分上下
+ h:一半
+ h:横
+ v:竖
+ l:左,上
+ c:中间
+ r:右,下
+ t:上
+ b:下
+ '''
+ def writeLine(self,pos,type):
+ if(type=="avl"):
+ self.img.line(
+ self.beginX+(self.textX+self.spare)*pos,
+ self.beginY,
+ self.beginX+(self.textX+self.spare)*pos,
+ self.beginY+self.textY
+ )
+ elif(type=="avc"):
+ self.img.line(
+ self.beginX+(self.textX+self.spare)*pos+self.textX/2,
+ self.beginY,
+ self.beginX+(self.textX+self.spare)*pos+self.textX/2,
+ self.beginY+self.textY
+ )
+ elif(type=="avr"):
+ self.img.line(
+ self.beginX+(self.textX+self.spare)*pos+self.textX,
+ self.beginY,
+ self.beginX+(self.textX+self.spare)*pos+self.textX,
+ self.beginY+self.textY
+ )
+ elif(type=="aht"):
+ self.img.line(
+ self.beginX+(self.textX+self.spare)*pos,
+ self.beginY,
+ self.beginX+(self.textX+self.spare)*pos+self.textX,
+ self.beginY,
+ )
+ elif(type=="ahc"):
+ self.img.line(
+ self.beginX+(self.textX+self.spare)*pos,
+ self.beginY+self.textY/2,
+ self.beginX+(self.textX+self.spare)*pos+self.textX,
+ self.beginY+self.textY/2
+ )
+ elif(type=="ahb"):
+ self.img.line(
+ self.beginX+(self.textX+self.spare)*pos,
+ self.beginY+self.textY,
+ self.beginX+(self.textX+self.spare)*pos+self.textX,
+ self.beginY+self.textY
+ )
+ elif(type=="hvtl"):
+ self.img.line(
+ self.beginX+(self.textX+self.spare)*pos,
+ self.beginY,
+ self.beginX+(self.textX+self.spare)*pos,
+ self.beginY+self.textY/2
+ )
+ elif(type=="hvtr"):
+ self.img.line(
+ self.beginX+(self.textX+self.spare)*pos+self.textX,
+ self.beginY,
+ self.beginX+(self.textX+self.spare)*pos+self.textX,
+ self.beginY+self.textY/2
+ )
+ elif(type=="hvbl"):
+ self.img.line(
+ self.beginX+(self.textX+self.spare)*pos,
+ self.beginY+self.textY/2,
+ self.beginX+(self.textX+self.spare)*pos,
+ self.beginY+self.textY
+ )
+ elif(type=="hvbr"):
+ self.img.line(
+ self.beginX+(self.textX+self.spare)*pos+self.textX,
+ self.beginY+self.textY/2,
+ self.beginX+(self.textX+self.spare)*pos+self.textX,
+ self.beginY+self.textY
+ )
+
View
75 app/trackback.py
@@ -0,0 +1,75 @@
+"""tblib.py: A Trackback (client) implementation in Python
+"""
+__author__ = "Matt Croydon <matt@ooiio.com>"
+__copyright__ = "Copyright 2003, Matt Croydon"
+__license__ = "GPL"
+__version__ = "0.1.0"
+__history__ = """
+0.1.0: 1/29/03 - Code cleanup, release. It can send pings, and autodiscover a URL to ping.
+0.0.9: 1/29/03 - Basic error handling and autodiscovery works!
+0.0.5: 1/29/03 - Internal development version. Working on autodiscovery and error handling.
+0.0.4: 1/22/03 - First public release, code cleanup.
+0.0.3: 1/22/03 - Removed hard coding that was used for testing.
+0.0.2: 1/21/03 - First working version.
+0.0.1: 1/21/03 - Initial version. Thanks to Mark Pilgrim for helping me figure some module basics out.
+"""
+import httplib, urllib, urlparse, re
+from google.appengine.api import urlfetch
+import logging
+"""Everything I needed to know about trackback I learned from the trackback tech specs page
+http://www.movabletype.org/docs/mttrackback.html. All arguments are optional. This allows us to create an empty TrackBack object,
+then use autodiscovery to populate its attributes.
+"""
+class TrackBack:
+
+ def __init__(self, tbUrl=None, title=None, excerpt=None, url=None, blog_name=None):
+ self.tbUrl = tbUrl
+ self.title = title
+ self.excerpt = excerpt
+ self.url = url
+ self.blog_name = blog_name
+ self.tbErrorCode = None
+ self.tbErrorMessage = None
+
+ def ping(self):
+
+ # Only execute if a trackback url has been defined.
+ if self.tbUrl:
+ # Create paramaters and make them play nice with HTTP
+ # Python's httplib example helps a lot:
+ # http://python.org/doc/current/lib/httplib-examples.html
+ params = urllib.urlencode({'title': self.title, 'url': self.url, 'excerpt': self.excerpt, 'blog_name': self.blog_name})
+ headers = ({"Content-type": "application/x-www-form-urlencoded",
+ "User-Agent": "micolog"})
+ # urlparse is my hero
+ # http://www.python.org/doc/current/lib/module-urlparse.html
+ logging.info("ping...%s",params)
+ response=urlfetch.fetch(self.tbUrl,method=urlfetch.POST,payload=params,headers=headers)
+
+ self.httpResponse = response.status_code
+ data = response.content
+ self.tbResponse = data
+ logging.info("ping...%s"%data)
+ # Thanks to Steve Holden's book: _Python Web Programming_ (http://pydish.holdenweb.com/pwp/)
+ # Why parse really simple XML when you can just use regular expressions? Rawk.
+ errorpattern = r'<error>(.*?)</error>'
+ reg = re.search(errorpattern, self.tbResponse)
+ if reg:
+ self.tbErrorCode = reg.group(1)
+ if int(self.tbErrorCode) == 1:
+ errorpattern2 = r'<message>(.*?)</message>'
+ reg2 = re.search(errorpattern2, self.tbResponse)
+ if reg2:
+ self.tbErrorMessage = reg2.group(1)
+
+ else:
+ return 1
+
+ def autodiscover(self, urlToCheck):
+
+ response=urlfetch.fetch(urlToCheck)
+ data = response.read()
+ tbpattern = r'trackback:ping="(.*?)"'
+ reg = re.search(tbpattern, data)
+ if reg:
+ self.tbUrl = reg.group(1)
View
79 base.py
@@ -7,6 +7,7 @@
from google.appengine.ext import db
from google.appengine.ext.webapp import template
from google.appengine.api import memcache
+from google.appengine.api import urlfetch
##import app.webapp as webapp2
os.environ['DJANGO_SETTINGS_MODULE'] = 'settings'
from django.utils.translation import activate
@@ -14,6 +15,7 @@
from django.conf import settings
settings._target = None
from model import *
+from google.appengine.api.labs import taskqueue
activate(g_blog.language)
@@ -24,6 +26,7 @@
import traceback
import micolog_template
+
logging.info('module base reloaded')
def urldecode(value):
return urllib.unquote(urllib.unquote(value)).decode('utf8')
@@ -96,12 +99,15 @@ def _wrapper(*args, **kwargs):
if html:
logging.info('cache:'+skey)
+ logging.debug(html[2])
+ logging.debug(html[3])
response.last_modified =html[1]
ilen=len(html)
if ilen>=3:
response.set_status(html[2])
if ilen>=4:
- response.headers['Content-Type']=html[3]
+ for skey,value in html[3].items():
+ response.headers[skey]=value
response.out.write(html[0])
else:
if 'last-modified' not in response.headers:
@@ -110,11 +116,78 @@ def _wrapper(*args, **kwargs):
method(*args, **kwargs)
result=response.out.getvalue()
status_code = response._Response__status[0]
- memcache.set(skey,(result,response.last_modified,status_code,response.headers['Content-Type']),time)
+ logging.debug("Cache:%s"%status_code)
+ memcache.set(skey,(result,response.last_modified,status_code,response.headers),time)
return _wrapper
return _decorate
+#-------------------------------------------------------------------------------
+class PingbackError(Exception):
+ """Raised if the remote server caused an exception while pingbacking.
+ This is not raised if the pingback function is unable to locate a
+ remote server.
+ """
+
+ _ = lambda x: x
+ default_messages = {
+ 16: _(u'source URL does not exist'),
+ 17: _(u'The source URL does not contain a link to the target URL'),
+ 32: _(u'The specified target URL does not exist'),
+ 33: _(u'The specified target URL cannot be used as a target'),
+ 48: _(u'The pingback has already been registered'),
+ 49: _(u'Access Denied')
+ }
+ del _
+
+ def __init__(self, fault_code, internal_message=None):
+ Exception.__init__(self)
+ self.fault_code = fault_code
+ self._internal_message = internal_message
+
+ def as_fault(self):
+ """Return the pingback errors XMLRPC fault."""
+ return Fault(self.fault_code, self.internal_message or
+ 'unknown server error')
+
+ @property
+ def ignore_silently(self):
+ """If the error can be ignored silently."""
+ return self.fault_code in (17, 33, 48, 49)
+
+ @property
+ def means_missing(self):
+ """If the error means that the resource is missing or not
+ accepting pingbacks.
+ """
+ return self.fault_code in (32, 33)
+
+ @property
+ def internal_message(self):
+ if self._internal_message is not None:
+ return self._internal_message
+ return self.default_messages.get(self.fault_code) or 'server error'
+
+ @property
+ def message(self):
+ msg = self.default_messages.get(self.fault_code)
+ if msg is not None:
+ return _(msg)
+ return _(u'An unknown server error (%s) occurred') % self.fault_code
+
+class util:
+ @classmethod
+ def do_trackback(cls, tbUrl=None, title=None, excerpt=None, url=None, blog_name=None):
+ taskqueue.add(url='/admin/do/trackback_ping',
+ params={'tbUrl': tbUrl,'title':title,'excerpt':excerpt,'url':url,'blog_name':blog_name})
+
+ #pingback ping
+ @classmethod
+ def do_pingback(cls,source_uri, target_uri):
+ taskqueue.add(url='/admin/do/pingback_ping',
+ params={'source': source_uri,'target':target_uri})
+
+
##cache variable
@@ -309,7 +382,7 @@ def initialize(self, request, response):
.filter('entry_parent =',0)\
.order('menu_order')
blogroll=Link.all().filter('linktype =','blogroll')
- archives=Archive.all()
+ archives=Archive.all().order('-date')
alltags=Tag.all()
self.template_vals.update({
'menu_pages':m_pages,
View
142 blog.py
@@ -28,13 +28,20 @@
##settings.configure(LANGUAGE_CODE = 'zh-cn')
# Must set this env var before importing any part of Django
+from app.safecode import Image
+from app.gmemsess import Session
+from micolog_plugin import *
+
+
def doRequestHandle(old_handler,new_handler,**args):
new_handler.initialize(old_handler.request,old_handler.response)
return new_handler.get(**args)
+def doRequestPostHandle(old_handler,new_handler,**args):
+ new_handler.initialize(old_handler.request,old_handler.response)
+ return new_handler.post(**args)
class MainPage(BasePublicPage):
-
def get(self,page=1):
postid=self.param('p')
if postid:
@@ -45,6 +52,16 @@ def get(self,page=1):
return self.error(404)
self.doget(page)
+ def post(self):
+ postid=self.param('p')
+ if postid:
+ try:
+ postid=int(postid)
+ return doRequestPostHandle(self,SinglePost(),postid=postid) #singlepost.get(postid=postid)
+ except:
+ return self.error(404)
+
+
@cache()
def doget(self,page):
@@ -148,7 +165,9 @@ def get(self,slug=None,postid=None):
entry=entries[0]
if entry.is_external_page:
- self.redirect(entry.external_page_address,True)
+ return self.redirect(entry.external_page_address,True)
+ if g_blog.allow_pingback and entry.allow_trackback:
+ self.response.headers['X-Pingback']="%s/rpc"%str(g_blog.baseurl)
entry.readtimes += 1
entry.put()
self.entry=entry
@@ -193,6 +212,84 @@ def get(self,slug=None,postid=None):
'comments_nav':comments_nav,
})
+ def post(self,slug=None,postid=None):
+ '''handle trackback'''
+ error = '''
+<?xml version="1.0" encoding="utf-8"?>
+<response>
+<error>1</error>
+<message>%s</message>
+</response>
+'''
+ success = '''
+<?xml version="1.0" encoding="utf-8"?>
+<response>
+<error>0</error>
+</response>
+'''
+ if not g_blog.allow_trackback:
+ self.response.out.write(self.error % "Trackback denied.")
+ return
+ self.response.headers['Content-Type'] = "text/xml"
+ if postid:
+ entries = Entry.all().filter("published =", True).filter('post_id =', postid).fetch(1)
+ else:
+ slug=urldecode(slug)
+ entries = Entry.all().filter("published =", True).filter('link =', slug).fetch(1)
+
+ if not entries or len(entries) == 0 :#or (postid and not entries[0].link.endswith(g_blog.default_link_format%{'post_id':postid})):
+ self.response.out.write(error % "empty slug/postid")
+ return
+ #check code ,rejest spam
+ entry=entries[0]
+ #key=self.param("code")
+ if (self.request.uri!=entry.trackbackurl) or entry.is_external_page or not entry.allow_trackback:
+ self.response.out.write(error % "Invalid trackback url.")
+ return
+ coming_url = self.param('url')
+ blog_name = myfilter.do_filter(self.param('blog_name'))
+ excerpt = myfilter.do_filter(self.param('excerpt'))
+ title = myfilter.do_filter(self.param('title'))
+
+ if not coming_url or not blog_name or not excerpt or not title:
+ self.response.out.write(error % "not enough post info")
+ return
+
+ import time
+ #wait for half second in case otherside hasn't been published
+ time.sleep(0.5)
+
+## #also checking the coming url is valid and contains our link
+## #this is not standard trackback behavior
+## try:
+##
+## result = urlfetch.fetch(coming_url)
+## if result.status_code != 200 :
+## #or ((g_blog.baseurl + '/' + slug) not in result.content.decode('ascii','ignore')):
+## self.response.out.write(error % "probably spam")
+## return
+## except Exception, e:
+## logging.info("urlfetch error")
+## self.response.out.write(error % "urlfetch error")
+## return
+
+ comment = Comment.all().filter("entry =", entry).filter("weburl =", coming_url).get()
+ if comment:
+ self.response.out.write(error % "has pinged before")
+ return
+
+ comment=Comment(author=blog_name,
+ content="<strong>"+title[:250]+"...</strong><br/>" +
+ excerpt[:250] + '...',
+ weburl=coming_url,
+ entry=entry)
+ comment.ip=self.request.remote_addr
+ comment.ctype=COMMENT_TRACKBACK
+ comment.save()
+
+ memcache.delete("/"+entry.link)
+ self.write(success)
+
def get_comments_nav(self,pindex,count):
maxpage=count / g_blog.comments_per_page + ( count % g_blog.comments_per_page and 1 or 0 )
@@ -293,11 +390,10 @@ def addurl(loc,lastmod=None,changefreq=None,priority=None):
self.render2('views/sitemap.xml',{'urlset':urls})
-
class Error404(BaseRequestHandler):
@cache(time=36000)
def get(self,slug=None):
- self.error(404)
+ self.error(404)
class Post_comment(BaseRequestHandler):
#@printinfo
@@ -316,8 +412,10 @@ def post(self,slug=None):
content=self.param('comment')
checknum=self.param('checknum')
checkret=self.param('checkret')
+ reply_notify_mail=self.parambool('reply_notify_mail')
## if useajax:
## name=urldecode(name)
+
## email=urldecode(email)
## url=urldecode(url)
## key=urldecode(key)
@@ -325,26 +423,29 @@ def post(self,slug=None):
## checknum=urldecode(checknum)
## checkret=urldecode(checkret)
+ sess=Session(self,timeout=180)
if not self.is_login:
if not (self.request.cookies.get('comment_user', '')):
try:
- import app.gbtools as gb
- if eval(checknum)<>int(gb.stringQ2B( checkret)):
+ #import app.gbtools as gb
+ #if eval(checknum)<>int(gb.stringQ2B( checkret)):
+ if sess.is_new() or (int(checkret) != sess['code']):
+ sess.invalidate()
if useajax:
self.write(simplejson.dumps((False,-102,_('Your check code is invalid .'))))
else:
self.error(-102,_('Your check code is invalid .'))
return
except:
+ sess.invalidate()
if useajax:
self.write(simplejson.dumps((False,-102,_('Your check code is invalid .'))))
else:
self.error(-102,_('Your check code is invalid .'))
return
-
-
+ sess.invalidate()
content=content.replace('\n','<br>')
content=myfilter.do_filter(content)
name=cgi.escape(name)[:20]
@@ -359,6 +460,7 @@ def post(self,slug=None):
comment=Comment(author=name,
content=content,
email=email,
+ reply_notify_mail=reply_notify_mail,
entry=Entry.get(key))
if url:
try:
@@ -377,6 +479,7 @@ def post(self,slug=None):
(datetime.now()+timedelta(days=100)).strftime("%a, %d-%b-%Y %H:%M:%S GMT"),
''
)
+ comment.ip=self.request.remote_addr
comment.save()
memcache.delete("/"+comment.entry.link)
@@ -387,6 +490,11 @@ def post(self,slug=None):
else:
self.redirect(self.referer+"#comment-"+str(comment.key().id()))
+ comment.notify()
+ comment.entry.removecache()
+ memcache.delete("/feed/comments")
+ logging.info("cookie:"+str(self.request.cookies))
+
class ChangeTheme(BaseRequestHandler):
@requires_admin
def get(self,slug=None):
@@ -555,11 +663,24 @@ def post(self, slug=None):
memcache.delete("/"+entry.link)
self.response.out.write(self.success)
+class CheckImg(BaseRequestHandler):
+ def get(self):
+ img = Image()
+ imgdata = img.create()
+ sess=Session(self,timeout=180)
+ if not sess.is_new():
+ sess.invalidate()
+ sess=Session(self,timeout=180)
+ sess['code']=img.text
+ sess.save()
+ self.response.headers['Content-Type'] = "image/png"
+ self.response.out.write(imgdata)
def main():
webapp.template.register_template_library('filter')
application = webapp.WSGIApplication(
[('/media/(.*)',getMedia),
+ ('/checkimg/', CheckImg),
('/skin',ChangeTheme),
('/feed', FeedHandler),
('/feed/comments',CommentsFeedHandler),
@@ -569,11 +690,10 @@ def main():
('/category/(.*)',entriesByCategory),
('/(\d{4})/(\d{2})',archive_by_month),
('/tag/(.*)',entriesByTag),
-## ('/\?p=(?P<postid>\d+)',SinglePost),
+ #('/\?p=(?P<postid>\d+)',SinglePost),
('/', MainPage),
('/do/(\w+)', do_action),
-
- ('/([\\w\\-\\./]+)', SinglePost),
+ ('/([\\w\\-\\./%]+)', SinglePost),
('.*',Error404),
],debug=True)
wsgiref.handlers.CGIHandler().run(application)
View
22 filter.py
@@ -76,3 +76,25 @@ def dict_value(v1,v2):
@register.filter
def do_filter(data):
return plog_filter.go(data)
+
+'''
+tag like {%mf header%}xxx xxx{%endmf%}
+'''