Permalink
Cannot retrieve contributors at this time
Name already in use
A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
hxWiki/src/App.hx
Go to fileThis commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
298 lines (274 sloc)
8.65 KB
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import mtwin.web.Handler; | |
@:expose | |
class App { | |
public static var database : sys.db.Connection; | |
public static var session : db.Session; | |
public static var user : db.User; | |
public static var request : mtwin.web.Request; | |
public static var context : Dynamic; | |
public static var langFlags : db.Lang -> Bool; | |
public static var langSelected : db.Lang; | |
static var template : templo.Loader; | |
static function sendNoCacheHeaders() { | |
try { | |
neko.Web.setHeader("Cache-Control", "no-store, no-cache, must-revalidate"); | |
neko.Web.setHeader("Pragma", "no-cache"); | |
neko.Web.setHeader("Expires", "-1"); | |
neko.Web.setHeader("P3P", "CP=\"ALL DSP COR NID CURa OUR STP PUR\""); | |
neko.Web.setHeader("Content-Type", "text/html; Charset=UTF-8"); | |
neko.Web.setHeader("Expires", "Mon, 26 Jul 1997 05:00:00 GMT"); | |
} catch( e : Dynamic ) { | |
} | |
} | |
public static function prepareTemplate( t : String ) { | |
templo.Loader.OPTIMIZED = Config.DEBUG == false; | |
templo.Loader.BASE_DIR = Config.TPL; | |
templo.Loader.TMP_DIR = Config.TPL + "../tmp/"; | |
sendNoCacheHeaders(); | |
template = new templo.Loader(t); | |
} | |
static function executeTemplate() { | |
var result = template.execute(context); | |
sendNoCacheHeaders(); | |
neko.Lib.print(result); | |
} | |
public static function getCurrentContent() { | |
initContext(); | |
var str = template.execute(context); | |
template = null; | |
context = {}; | |
return str; | |
} | |
static function redirect( url:String ) { | |
template = null; | |
sendNoCacheHeaders(); | |
neko.Web.redirect(url); | |
} | |
static function initLang() { | |
if( Config.get("no_auto_lang","") == "1" ) | |
return null; | |
var ldata = neko.Web.getClientHeader("Accept-Language"); | |
var ldata = if( ldata == null ) [] else ldata.split(","); | |
var r = ~/^ ?([a-z]+)(-[a-zA-Z]+)?(;.*)?$/; | |
ldata.push(Config.LANG); | |
for( l in ldata ) { | |
if( !r.match(l) ) continue; | |
var code = r.matched(1); | |
if( code == null ) continue; | |
var l = db.Lang.manager.byCode(code); | |
if( l != null ) return l.id; | |
} | |
return null; | |
} | |
static function requireHttpAuth(){ | |
neko.Web.setReturnCode( 401 ); | |
neko.Web.setHeader("status","401 Authorization Required"); | |
neko.Web.setHeader("WWW-Authenticate","Basic realm=\"Please identify yourself\""); | |
} | |
static function mainLoop() { | |
// init | |
request = new mtwin.web.Request(); | |
context = {}; | |
var sid = request.get("sid"); | |
if( sid == null ) sid = neko.Web.getCookies().get("sid"); | |
session = db.Session.initialize(sid); | |
if( session.data == null ) { | |
try { | |
session.lang = initLang(); | |
session.insert(); | |
neko.Web.setHeader("Set-Cookie", "sid="+session.sid+"; path=/"); | |
} catch( e : Dynamic ) { | |
new handler.Main().setupDatabase(); | |
database.commit(); | |
throw "Database initialized"; | |
} | |
} | |
if( session.uid == null && Config.USE_HTACCESS ) { | |
var auth = neko.Web.getAuthorization(); | |
if( auth == null ) { | |
requireHttpAuth(); | |
return; | |
} | |
var u = db.User.manager.search({ name : auth.user },false).first(); | |
if( u == null || handler.Main.encodePass(auth.pass) != u.pass ) { | |
requireHttpAuth(); | |
return; | |
} | |
App.session.setUser(u); | |
} | |
user = if( session.uid != null ) db.User.manager.get(session.uid) else null; | |
langFlags = function(l) return true; | |
langSelected = null; | |
// execute | |
var h = new handler.Main(); | |
var level = if( request.getPathInfoPart(0) == "index.n" ) 1 else 0; | |
try { | |
h.dispatch(request,level); | |
} catch( e : ActionError ) { | |
switch( e ) { | |
case ActionReservedToLoggedUsers: | |
session.setError(Text.get.err_must_login); | |
case UnknownAction(_): | |
session.setError(Text.get.err_unknown_action,{ action : StringTools.htmlEscape(neko.Web.getURI()) }); | |
default: | |
} | |
redirect("/"); | |
} catch( e : handler.Action ) { | |
switch( e ) { | |
case Goto(url): | |
redirect(url); | |
case Error(url,err,params): | |
database.rollback(); | |
sys.db.Manager.cleanup(); | |
session = db.Session.initialize(sid); | |
if( user != null ) user = db.User.manager.get(user.id); | |
session.setError(err,params); | |
session.update(); | |
redirect(url); | |
case Done(url,conf,params): | |
session.setMessage(conf,params); | |
redirect(url); | |
} | |
} | |
if( user != null ) | |
user.update(); | |
if( template != null ) | |
initContext(); | |
session.update(); | |
if( template != null ) | |
executeTemplate(); | |
} | |
static function initDatabase( params : String ) { | |
var m = ~/^mysql:\/\/(.*):(.*)@(.*):(.*)\/(.*)$/; | |
if( !m.match(params) ) | |
throw "Invalid format "+params; | |
return sys.db.Mysql.connect({ | |
user : m.matched(1), | |
pass : m.matched(2), | |
host : m.matched(3), | |
port : Std.parseInt(m.matched(4)), | |
database : m.matched(5), | |
socket : null | |
}); | |
} | |
static function initContext() { | |
var style = Config.get("style", "default"); | |
if( session != null && session.designStyle != null ) | |
style = session.designStyle; | |
context.user = user; | |
context.session = session; | |
context.request = request; | |
var config = { | |
title : Config.get("title"), | |
style : style, | |
url : Config.get("url"), | |
gsearch : Config.get("gsearch",""), | |
}; | |
if( config.gsearch == "" ) | |
config.gsearch = null; | |
if( context.config == null ) | |
context.config = config; | |
else | |
for( f in Reflect.fields(config) ) | |
Reflect.setField(context.config, f, Reflect.field(config, f)); | |
// allow database failures here | |
context.links = function(n:Int) return try db.Link.manager.search($kind == n,{ orderBy : [-priority,id] },false) catch( e : Dynamic ) new List(); | |
context.langs = try db.Lang.manager.all(false) catch( e : Dynamic ) new List(); | |
context.section = function(s) return Config.getSection(s); | |
var parts = neko.Web.getURI().split("/"); | |
context.current_url = parts[1] == "index.n" ? "/" : "/" + parts[1]; | |
// body class | |
var userClass = user == null ? "offline" : user.group.name; | |
var bodyClass = "user_" + userClass; | |
if( context.cssClass != null ) | |
bodyClass += " " + context.cssClass; | |
context.bodyClass = bodyClass; | |
// which design mtt to choose | |
if( context.design_mtt == null ) { | |
var customDesign = "design_" + style + ".mtt"; | |
context.design_mtt = if( sys.FileSystem.exists(Config.TPL+customDesign) ) customDesign else "design.mtt"; | |
} | |
// uri | |
if( request == null ) | |
context.uri = "/"; | |
else { | |
var uri = request.getURI(); | |
if( request.exists("path") ) | |
uri += "?path="+request.get("path"); | |
context.uri = uri; | |
} | |
context.dateFormat = function(d,fmt) { | |
return DateTools.format(d,fmt); | |
}; | |
context.format = { | |
postDate : function(d:Date) { | |
return DateTools.format(d, Config.getSection("post_date","<span>Posted</span> on %b %d %Y")); | |
}, | |
postAuthor : function(u:db.User) { | |
var uname = u == null ? "Anonymous" : u.realName; | |
var ulink = u == null ? "#" : "/wiki/user?name=" + u.name; | |
return Config.getSection("post_author",'by <a href="::link::">::u::</a>').split("::u::").join(uname).split("::link::").join(ulink); | |
}, | |
commentDate : function(d:Date) { | |
return DateTools.format(d, Config.getSection("comment_date","%b %d, %Y at %H:%M")); | |
}, | |
comments : function(n:Int, t:String) { | |
return Config.getSection("comments_fmt","::n:: ::t::").split("::n::").join(""+n).split("::t::").join(t); | |
}, | |
}; | |
context.lang_classes = function(l) { | |
#if php | |
return "off"; | |
#end | |
var f = if( langFlags == null ) true else langFlags(l); | |
return (f ? "on" : "off") + ((l == langSelected) ? " current" : ""); | |
}; | |
if( session != null && session.notification != null ) { | |
context.notification = session.notification; | |
session.notification = null; | |
} | |
} | |
static function errorHandler( e : Dynamic ) { | |
try { | |
prepareTemplate("error.mtt"); | |
context = {}; | |
initContext(); | |
context.error = Std.string(e); | |
context.stack = haxe.CallStack.toString(haxe.CallStack.exceptionStack()); | |
executeTemplate(); | |
} catch( e : Dynamic ) { | |
neko.Lib.rethrow(e); | |
} | |
} | |
static function cleanup() { | |
if( database != null ) { | |
database.close(); | |
database = null; | |
} | |
template = null; | |
session = null; | |
user = null; | |
request = null; | |
context = null; | |
langFlags = null; | |
langSelected = null; | |
} | |
static function main() { | |
if( !Sys.setTimeLocale(Text.get.locale1) ) | |
Sys.setTimeLocale(Text.get.locale2); | |
try { | |
database = initDatabase(Config.get("db")); | |
} catch( e : Dynamic ) { | |
errorHandler(e); | |
cleanup(); | |
return; | |
} | |
sys.db.Transaction.main(database, mainLoop, errorHandler); | |
database = null; // already closed | |
cleanup(); | |
#if neko | |
if( Config.get("cache", "0") == "1" ) | |
neko.Web.cacheModule(main); | |
#end | |
} | |
} |