[Jifty-commit] r2734 - in jifty: . branches/schema-plugins branches/schema-plugins/bin branches/schema-plugins/debian branches/schema-plugins/doc branches/schema-plugins/doc/examples branches/schema-plugins/doc/examples/CounterDemo branches/schema-plugins/doc/examples/CounterDemo/bin branches/schema-plugins/doc/examples/CounterDemo/doc branches/schema-plugins/doc/examples/CounterDemo/etc branches/schema-plugins/doc/examples/CounterDemo/lib branches/schema-plugins/doc/examples/CounterDemo/lib/CounterDemo branches/schema-plugins/doc/examples/CounterDemo/lib/CounterDemo/Action branches/schema-plugins/doc/examples/CounterDemo/lib/CounterDemo/Model branches/schema-plugins/doc/examples/CounterDemo/log branches/schema-plugins/doc/examples/CounterDemo/share branches/schema-plugins/doc/examples/CounterDemo/share/po branches/schema-plugins/doc/examples/CounterDemo/share/web branches/schema-plugins/doc/examples/CounterDemo/share/web/static branches/schema-plugins/doc/examples/CounterDemo/share/web/templates branches/schema-plugins/doc/examples/CounterDemo/t branches/schema-plugins/doc/examples/CounterDemo/var branches/schema-plugins/doc/examples/CounterDemo/var/mason branches/schema-plugins/doc/examples/CounterDemo/var/mason/cache branches/schema-plugins/doc/examples/CounterDemo/var/mason/obj branches/schema-plugins/doc/pubsub branches/schema-plugins/doc/talks branches/schema-plugins/doc/talks/npw.2006 branches/schema-plugins/doc/talks/npw.2006/Blog branches/schema-plugins/doc/talks/npw.2006/Blog/bin branches/schema-plugins/doc/talks/npw.2006/Blog/doc branches/schema-plugins/doc/talks/npw.2006/Blog/etc branches/schema-plugins/doc/talks/npw.2006/Blog/lib branches/schema-plugins/doc/talks/npw.2006/Blog/lib/Blog branches/schema-plugins/doc/talks/npw.2006/Blog/lib/Blog/Action branches/schema-plugins/doc/talks/npw.2006/Blog/lib/Blog/Model branches/schema-plugins/doc/talks/npw.2006/Blog/log branches/schema-plugins/doc/talks/npw.2006/Blog/share branches/schema-plugins/doc/talks/npw.2006/Blog/share/po branches/schema-plugins/doc/talks/npw.2006/Blog/share/web branches/schema-plugins/doc/talks/npw.2006/Blog/share/web/static branches/schema-plugins/doc/talks/npw.2006/Blog/share/web/templates branches/schema-plugins/doc/talks/npw.2006/Blog/t branches/schema-plugins/doc/talks/npw.2006/Blog/var branches/schema-plugins/etc branches/schema-plugins/examples branches/schema-plugins/examples/Chat branches/schema-plugins/examples/Chat/bin branches/schema-plugins/examples/Chat/doc branches/schema-plugins/examples/Chat/etc branches/schema-plugins/examples/Chat/lib branches/schema-plugins/examples/Chat/lib/Chat branches/schema-plugins/examples/Chat/lib/Chat/Action branches/schema-plugins/examples/Chat/lib/Chat/Event branches/schema-plugins/examples/Chat/lib/Chat/Model branches/schema-plugins/examples/Chat/log branches/schema-plugins/examples/Chat/share branches/schema-plugins/examples/Chat/share/po branches/schema-plugins/examples/Chat/share/web branches/schema-plugins/examples/Chat/share/web/static branches/schema-plugins/examples/Chat/share/web/templates branches/schema-plugins/examples/Chat/share/web/templates/fragments branches/schema-plugins/examples/Chat/t branches/schema-plugins/examples/Chat/var branches/schema-plugins/examples/Clock branches/schema-plugins/examples/Clock/bin branches/schema-plugins/examples/Clock/doc branches/schema-plugins/examples/Clock/etc branches/schema-plugins/examples/Clock/lib branches/schema-plugins/examples/Clock/lib/Clock branches/schema-plugins/examples/Clock/lib/Clock/Action branches/schema-plugins/examples/Clock/lib/Clock/Model branches/schema-plugins/examples/Clock/log branches/schema-plugins/examples/Clock/share branches/schema-plugins/examples/Clock/share/po branches/schema-plugins/examples/Clock/share/web branches/schema-plugins/examples/Clock/share/web/templates branches/schema-plugins/examples/Clock/share/web/templates/fragments branches/schema-plugins/examples/Clock/t branches/schema-plugins/examples/Clock/var branches/schema-plugins/examples/MyWeblog branches/schema-plugins/examples/MyWeblog/bin branches/schema-plugins/examples/MyWeblog/doc branches/schema-plugins/examples/MyWeblog/etc branches/schema-plugins/examples/MyWeblog/lib branches/schema-plugins/examples/MyWeblog/lib/MyWeblog branches/schema-plugins/examples/MyWeblog/lib/MyWeblog/Action branches/schema-plugins/examples/MyWeblog/lib/MyWeblog/Model branches/schema-plugins/examples/MyWeblog/share branches/schema-plugins/examples/MyWeblog/share/po branches/schema-plugins/examples/MyWeblog/share/web branches/schema-plugins/examples/MyWeblog/share/web/static branches/schema-plugins/examples/MyWeblog/share/web/templates branches/schema-plugins/examples/MyWeblog/share/web/templates/_elements branches/schema-plugins/examples/MyWeblog/share/web/templates/fragments branches/schema-plugins/examples/MyWeblog/t branches/schema-plugins/examples/MyWeblog/var branches/schema-plugins/examples/MyWeblog/var/mason branches/schema-plugins/examples/MyWeblog/var/mason/cache branches/schema-plugins/examples/Ping branches/schema-plugins/examples/Ping/bin branches/schema-plugins/examples/Ping/doc branches/schema-plugins/examples/Ping/etc branches/schema-plugins/examples/Ping/lib branches/schema-plugins/examples/Ping/lib/Ping branches/schema-plugins/examples/Ping/lib/Ping/Action branches/schema-plugins/examples/Ping/lib/Ping/Event branches/schema-plugins/examples/Ping/lib/Ping/Model branches/schema-plugins/examples/Ping/log branches/schema-plugins/examples/Ping/share branches/schema-plugins/examples/Ping/share/po branches/schema-plugins/examples/Ping/share/web branches/schema-plugins/examples/Ping/share/web/static branches/schema-plugins/examples/Ping/share/web/templates branches/schema-plugins/examples/Ping/share/web/templates/fragments branches/schema-plugins/examples/Ping/t branches/schema-plugins/inc branches/schema-plugins/inc/Module branches/schema-plugins/inc/Module/Install branches/schema-plugins/lib branches/schema-plugins/lib/Email branches/schema-plugins/lib/Email/Send branches/schema-plugins/lib/Email/Send/Jifty branches/schema-plugins/lib/Jifty branches/schema-plugins/lib/Jifty/Action branches/schema-plugins/lib/Jifty/Action/Devel branches/schema-plugins/lib/Jifty/Action/Record branches/schema-plugins/lib/Jifty/Event branches/schema-plugins/lib/Jifty/Filter branches/schema-plugins/lib/Jifty/Manual branches/schema-plugins/lib/Jifty/Mason branches/schema-plugins/lib/Jifty/Model branches/schema-plugins/lib/Jifty/Module branches/schema-plugins/lib/Jifty/Param branches/schema-plugins/lib/Jifty/Plugin branches/schema-plugins/lib/Jifty/Plugin/REST branches/schema-plugins/lib/Jifty/Request branches/schema-plugins/lib/Jifty/Script branches/schema-plugins/lib/Jifty/Subs branches/schema-plugins/lib/Jifty/Test branches/schema-plugins/lib/Jifty/Test/WWW branches/schema-plugins/lib/Jifty/Upgrade branches/schema-plugins/lib/Jifty/View branches/schema-plugins/lib/Jifty/View/Mason branches/schema-plugins/lib/Jifty/View/Static branches/schema-plugins/lib/Jifty/Web branches/schema-plugins/lib/Jifty/Web/Form branches/schema-plugins/lib/Jifty/Web/Form/Field branches/schema-plugins/lib/Jifty/Web/Session branches/schema-plugins/lib/auto branches/schema-plugins/plugins branches/schema-plugins/plugins/AuthCASLogin branches/schema-plugins/plugins/AuthCASLogin/debian branches/schema-plugins/plugins/AuthCASLogin/doc branches/schema-plugins/plugins/AuthCASLogin/lib branches/schema-plugins/plugins/AuthCASLogin/lib/Jifty branches/schema-plugins/plugins/AuthCASLogin/lib/Jifty/Plugin branches/schema-plugins/plugins/AuthCASLogin/lib/Jifty/Plugin/AuthCASLogin branches/schema-plugins/plugins/AuthCASLogin/lib/Jifty/Plugin/AuthCASLogin/Action branches/schema-plugins/plugins/AuthCASLogin/lib/Jifty/Plugin/AuthCASLogin/Model branches/schema-plugins/plugins/AuthCASLogin/share branches/schema-plugins/plugins/AuthCASLogin/share/po branches/schema-plugins/plugins/AuthCASLogin/share/web branches/schema-plugins/plugins/AuthCASLogin/share/web/static branches/schema-plugins/plugins/AuthCASLogin/share/web/templates branches/schema-plugins/plugins/AuthCASLogin/t branches/schema-plugins/plugins/AuthCASOnly branches/schema-plugins/plugins/AuthCASOnly/debian branches/schema-plugins/plugins/AuthCASOnly/doc branches/schema-plugins/plugins/AuthCASOnly/lib branches/schema-plugins/plugins/AuthCASOnly/lib/Jifty branches/schema-plugins/plugins/AuthCASOnly/lib/Jifty/Plugin branches/schema-plugins/plugins/AuthCASOnly/lib/Jifty/Plugin/AuthCASOnly branches/schema-plugins/plugins/AuthCASOnly/lib/Jifty/Plugin/AuthCASOnly/Action branches/schema-plugins/plugins/AuthCASOnly/lib/Jifty/Plugin/AuthCASOnly/Model branches/schema-plugins/plugins/AuthCASOnly/share branches/schema-plugins/plugins/AuthCASOnly/share/po branches/schema-plugins/plugins/AuthCASOnly/share/web branches/schema-plugins/plugins/AuthCASOnly/share/web/static branches/schema-plugins/plugins/AuthCASOnly/share/web/templates branches/schema-plugins/plugins/AuthCASOnly/t branches/schema-plugins/plugins/AuthLDAPLogin branches/schema-plugins/plugins/AuthLDAPLogin/debian branches/schema-plugins/plugins/AuthLDAPLogin/doc branches/schema-plugins/plugins/AuthLDAPLogin/lib branches/schema-plugins/plugins/AuthLDAPLogin/lib/Jifty branches/schema-plugins/plugins/AuthLDAPLogin/lib/Jifty/Plugin branches/schema-plugins/plugins/AuthLDAPLogin/lib/Jifty/Plugin/AuthLDAPLogin branches/schema-plugins/plugins/AuthLDAPLogin/lib/Jifty/Plugin/AuthLDAPLogin/Action branches/schema-plugins/plugins/AuthLDAPLogin/lib/Jifty/Plugin/AuthLDAPLogin/Model branches/schema-plugins/plugins/AuthLDAPLogin/share branches/schema-plugins/plugins/AuthLDAPLogin/share/po branches/schema-plugins/plugins/AuthLDAPLogin/share/web branches/schema-plugins/plugins/AuthLDAPLogin/share/web/static branches/schema-plugins/plugins/AuthLDAPLogin/share/web/templates branches/schema-plugins/plugins/AuthLDAPLogin/t branches/schema-plugins/plugins/AuthLDAPOnly branches/schema-plugins/plugins/AuthLDAPOnly/debian branches/schema-plugins/plugins/AuthLDAPOnly/doc branches/schema-plugins/plugins/AuthLDAPOnly/lib branches/schema-plugins/plugins/AuthLDAPOnly/lib/Jifty branches/schema-plugins/plugins/AuthLDAPOnly/lib/Jifty/Plugin branches/schema-plugins/plugins/AuthLDAPOnly/lib/Jifty/Plugin/AuthLDAPOnly branches/schema-plugins/plugins/AuthLDAPOnly/lib/Jifty/Plugin/AuthLDAPOnly/Action branches/schema-plugins/plugins/AuthLDAPOnly/lib/Jifty/Plugin/AuthLDAPOnly/Model branches/schema-plugins/plugins/AuthLDAPOnly/share branches/schema-plugins/plugins/AuthLDAPOnly/share/po branches/schema-plugins/plugins/AuthLDAPOnly/share/web branches/schema-plugins/plugins/AuthLDAPOnly/share/web/static branches/schema-plugins/plugins/AuthLDAPOnly/share/web/templates branches/schema-plugins/plugins/AuthLDAPOnly/t branches/schema-plugins/plugins/AuthzLDAP branches/schema-plugins/plugins/AuthzLDAP/doc branches/schema-plugins/plugins/AuthzLDAP/lib branches/schema-plugins/plugins/AuthzLDAP/lib/Jifty branches/schema-plugins/plugins/AuthzLDAP/lib/Jifty/Plugin branches/schema-plugins/plugins/AuthzLDAP/lib/Jifty/Plugin/AuthzLDAP branches/schema-plugins/plugins/AuthzLDAP/lib/Jifty/Plugin/AuthzLDAP/Action branches/schema-plugins/plugins/AuthzLDAP/lib/Jifty/Plugin/AuthzLDAP/Model branches/schema-plugins/plugins/AuthzLDAP/share branches/schema-plugins/plugins/AuthzLDAP/share/po branches/schema-plugins/plugins/AuthzLDAP/share/web branches/schema-plugins/plugins/AuthzLDAP/share/web/static branches/schema-plugins/plugins/AuthzLDAP/share/web/templates branches/schema-plugins/plugins/AuthzLDAP/share/web/templates/error branches/schema-plugins/plugins/AuthzLDAP/t branches/schema-plugins/plugins/EditInPlace branches/schema-plugins/plugins/EditInPlace/debian branches/schema-plugins/plugins/EditInPlace/inc branches/schema-plugins/plugins/EditInPlace/inc/Module branches/schema-plugins/plugins/EditInPlace/inc/Module/Install branches/schema-plugins/plugins/EditInPlace/inc/Module/Install/Makefile branches/schema-plugins/plugins/EditInPlace/lib branches/schema-plugins/plugins/EditInPlace/lib/Jifty branches/schema-plugins/plugins/EditInPlace/lib/Jifty/Plugin branches/schema-plugins/plugins/EditInPlace/lib/Jifty/Plugin/EditInPlace branches/schema-plugins/plugins/EditInPlace/lib/Jifty/Plugin/EditInPlace/Action branches/schema-plugins/plugins/EditInPlace/share branches/schema-plugins/plugins/EditInPlace/share/web branches/schema-plugins/plugins/EditInPlace/share/web/templates branches/schema-plugins/plugins/EditInPlace/share/web/templates/__jifty branches/schema-plugins/plugins/EmailErrors branches/schema-plugins/plugins/EmailErrors/doc branches/schema-plugins/plugins/EmailErrors/lib branches/schema-plugins/plugins/EmailErrors/lib/Jifty branches/schema-plugins/plugins/EmailErrors/lib/Jifty/Plugin branches/schema-plugins/plugins/EmailErrors/lib/Jifty/Plugin/EmailErrors branches/schema-plugins/plugins/EmailErrors/lib/Jifty/Plugin/EmailErrors/Action branches/schema-plugins/plugins/EmailErrors/lib/Jifty/Plugin/EmailErrors/Model branches/schema-plugins/plugins/EmailErrors/lib/Jifty/Plugin/EmailErrors/Notification branches/schema-plugins/plugins/EmailErrors/share branches/schema-plugins/plugins/EmailErrors/share/web branches/schema-plugins/plugins/EmailErrors/share/web/templates branches/schema-plugins/plugins/LetMe branches/schema-plugins/plugins/LetMe/doc branches/schema-plugins/plugins/LetMe/lib branches/schema-plugins/plugins/LetMe/lib/Jifty branches/schema-plugins/plugins/LetMe/lib/Jifty/Plugin branches/schema-plugins/plugins/LetMe/lib/Jifty/Plugin/LetMe branches/schema-plugins/plugins/LetMe/lib/Jifty/Plugin/LetMe/Action branches/schema-plugins/plugins/LetMe/lib/Jifty/Plugin/LetMe/Model branches/schema-plugins/plugins/LetMe/share branches/schema-plugins/plugins/LetMe/share/po branches/schema-plugins/plugins/LetMe/share/web branches/schema-plugins/plugins/LetMe/share/web/static branches/schema-plugins/plugins/LetMe/share/web/templates branches/schema-plugins/plugins/LetMe/t branches/schema-plugins/plugins/Login branches/schema-plugins/plugins/Login/debian branches/schema-plugins/plugins/Login/doc branches/schema-plugins/plugins/Login/inc branches/schema-plugins/plugins/Login/inc/Module branches/schema-plugins/plugins/Login/inc/Module/Install branches/schema-plugins/plugins/Login/lib branches/schema-plugins/plugins/Login/lib/Jifty branches/schema-plugins/plugins/Login/lib/Jifty/Plugin branches/schema-plugins/plugins/Login/lib/Jifty/Plugin/Login branches/schema-plugins/plugins/Login/lib/Jifty/Plugin/Login/Action branches/schema-plugins/plugins/Login/lib/Jifty/Plugin/Login/Model branches/schema-plugins/plugins/Login/lib/Jifty/Plugin/Login/Notification branches/schema-plugins/plugins/Login/share branches/schema-plugins/plugins/Login/share/po branches/schema-plugins/plugins/Login/share/web branches/schema-plugins/plugins/Login/share/web/static branches/schema-plugins/plugins/Login/share/web/templates branches/schema-plugins/plugins/Login/share/web/templates/let branches/schema-plugins/plugins/Login/t branches/schema-plugins/plugins/Nothing branches/schema-plugins/plugins/Nothing/doc branches/schema-plugins/plugins/Nothing/lib branches/schema-plugins/plugins/Nothing/lib/Jifty branches/schema-plugins/plugins/Nothing/lib/Jifty/Plugin branches/schema-plugins/plugins/Nothing/lib/Jifty/Plugin/Nothing branches/schema-plugins/plugins/Nothing/lib/Jifty/Plugin/Nothing/Action branches/schema-plugins/plugins/Nothing/lib/Jifty/Plugin/Nothing/Model branches/schema-plugins/plugins/Nothing/share branches/schema-plugins/plugins/Nothing/share/po branches/schema-plugins/plugins/Nothing/share/web branches/schema-plugins/plugins/Nothing/share/web/static branches/schema-plugins/plugins/Nothing/share/web/templates branches/schema-plugins/plugins/ProfileBehaviour branches/schema-plugins/plugins/ProfileBehaviour/doc branches/schema-plugins/plugins/ProfileBehaviour/lib branches/schema-plugins/plugins/ProfileBehaviour/lib/Jifty branches/schema-plugins/plugins/ProfileBehaviour/lib/Jifty/Plugin branches/schema-plugins/plugins/ProfileBehaviour/lib/Jifty/Plugin/ProfileBehaviour branches/schema-plugins/plugins/ProfileBehaviour/lib/Jifty/Plugin/ProfileBehaviour/Action branches/schema-plugins/plugins/ProfileBehaviour/lib/Jifty/Plugin/ProfileBehaviour/Model branches/schema-plugins/plugins/ProfileBehaviour/share branches/schema-plugins/plugins/ProfileBehaviour/share/po branches/schema-plugins/plugins/ProfileBehaviour/share/web branches/schema-plugins/plugins/ProfileBehaviour/share/web/static branches/schema-plugins/plugins/ProfileBehaviour/share/web/static/css branches/schema-plugins/plugins/ProfileBehaviour/share/web/static/js branches/schema-plugins/plugins/ProfileBehaviour/share/web/templates branches/schema-plugins/plugins/ProfileBehaviour/t branches/schema-plugins/plugins/Users branches/schema-plugins/plugins/Users-Identity-File branches/schema-plugins/plugins/Users-Identity-File/doc branches/schema-plugins/plugins/Users-Identity-File/lib branches/schema-plugins/plugins/Users-Identity-File/lib/Jifty branches/schema-plugins/plugins/Users-Identity-File/lib/Jifty/Plugin branches/schema-plugins/plugins/Users-Identity-File/lib/Jifty/Plugin/Users branches/schema-plugins/plugins/Users-Identity-File/lib/Jifty/Plugin/Users/Identity branches/schema-plugins/plugins/Users-Identity-File/lib/Jifty/Plugin/Users/Identity/File branches/schema-plugins/plugins/Users-Identity-File/lib/Jifty/Plugin/Users/Identity/File/Action branches/schema-plugins/plugins/Users-Identity-File/lib/Jifty/Plugin/Users/Identity/File/Model branches/schema-plugins/plugins/Users-Identity-File/share branches/schema-plugins/plugins/Users-Identity-File/share/po branches/schema-plugins/plugins/Users-Identity-File/share/web branches/schema-plugins/plugins/Users-Identity-File/share/web/static branches/schema-plugins/plugins/Users-Identity-File/share/web/templates branches/schema-plugins/plugins/Users-Identity-File/t branches/schema-plugins/plugins/Users/doc branches/schema-plugins/plugins/Users/lib branches/schema-plugins/plugins/Users/lib/Jifty branches/schema-plugins/plugins/Users/lib/Jifty/Plugin branches/schema-plugins/plugins/Users/lib/Jifty/Plugin/Users branches/schema-plugins/plugins/Users/lib/Jifty/Plugin/Users/Action branches/schema-plugins/plugins/Users/lib/Jifty/Plugin/Users/Model branches/schema-plugins/plugins/Users/share branches/schema-plugins/plugins/Users/share/po branches/schema-plugins/plugins/Users/share/web branches/schema-plugins/plugins/Users/share/web/static branches/schema-plugins/plugins/Users/share/web/templates branches/schema-plugins/plugins/Users/t branches/schema-plugins/share branches/schema-plugins/share/dtd branches/schema-plugins/share/po branches/schema-plugins/share/web branches/schema-plugins/share/web/static branches/schema-plugins/share/web/static/css branches/schema-plugins/share/web/static/css/yui branches/schema-plugins/share/web/static/css/yui/calendar branches/schema-plugins/share/web/static/css/yui/tabview branches/schema-plugins/share/web/static/images branches/schema-plugins/share/web/static/images/css branches/schema-plugins/share/web/static/images/iepngfix branches/schema-plugins/share/web/static/images/silk branches/schema-plugins/share/web/static/images/yui branches/schema-plugins/share/web/static/images/yui/us branches/schema-plugins/share/web/static/images/yui/us/my branches/schema-plugins/share/web/static/images/yui/us/my/bn branches/schema-plugins/share/web/static/images/yui/us/tr branches/schema-plugins/share/web/static/js branches/schema-plugins/share/web/static/js/cssquery branches/schema-plugins/share/web/static/js/jsan branches/schema-plugins/share/web/static/js/jsan/DOM branches/schema-plugins/share/web/static/js/jsan/Upgrade branches/schema-plugins/share/web/static/js/jsan/Upgrade/Array branches/schema-plugins/share/web/static/js/jsan/Upgrade/Function branches/schema-plugins/share/web/static/js/scriptaculous branches/schema-plugins/share/web/static/js/yui branches/schema-plugins/share/web/templates branches/schema-plugins/share/web/templates/= branches/schema-plugins/share/web/templates/__jifty branches/schema-plugins/share/web/templates/__jifty/admin branches/schema-plugins/share/web/templates/__jifty/admin/_elements branches/schema-plugins/share/web/templates/__jifty/admin/action branches/schema-plugins/share/web/templates/__jifty/admin/fragments branches/schema-plugins/share/web/templates/__jifty/admin/fragments/list branches/schema-plugins/share/web/templates/__jifty/admin/model branches/schema-plugins/share/web/templates/__jifty/css branches/schema-plugins/share/web/templates/__jifty/error branches/schema-plugins/share/web/templates/__jifty/error/_elements branches/schema-plugins/share/web/templates/__jifty/js branches/schema-plugins/share/web/templates/__jifty/online_docs branches/schema-plugins/share/web/templates/__jifty/webservices branches/schema-plugins/share/web/templates/_elements branches/schema-plugins/share/web/templates/helpers branches/schema-plugins/t branches/schema-plugins/t/Continuations branches/schema-plugins/t/Continuations/bin branches/schema-plugins/t/Continuations/lib branches/schema-plugins/t/Continuations/lib/Continuations branches/schema-plugins/t/Continuations/lib/Continuations/Action branches/schema-plugins/t/Continuations/share branches/schema-plugins/t/Continuations/share/web branches/schema-plugins/t/Continuations/share/web/templates branches/schema-plugins/t/Continuations/t branches/schema-plugins/t/Mapper branches/schema-plugins/t/Mapper/bin branches/schema-plugins/t/Mapper/lib branches/schema-plugins/t/Mapper/lib/Mapper branches/schema-plugins/t/Mapper/lib/Mapper/Action branches/schema-plugins/t/Mapper/share branches/schema-plugins/t/Mapper/share/web branches/schema-plugins/t/Mapper/share/web/templates branches/schema-plugins/t/Mapper/t branches/schema-plugins/t/TestApp branches/schema-plugins/t/TestApp-Plugin-REST branches/schema-plugins/t/TestApp-Plugin-REST/bin branches/schema-plugins/t/TestApp-Plugin-REST/etc branches/schema-plugins/t/TestApp-Plugin-REST/lib branches/schema-plugins/t/TestApp-Plugin-REST/lib/TestApp branches/schema-plugins/t/TestApp-Plugin-REST/lib/TestApp/Plugin branches/schema-plugins/t/TestApp-Plugin-REST/lib/TestApp/Plugin/REST branches/schema-plugins/t/TestApp-Plugin-REST/lib/TestApp/Plugin/REST/Action branches/schema-plugins/t/TestApp-Plugin-REST/lib/TestApp/Plugin/REST/Model branches/schema-plugins/t/TestApp-Plugin-REST/share branches/schema-plugins/t/TestApp-Plugin-REST/t branches/schema-plugins/t/TestApp/bin branches/schema-plugins/t/TestApp/lib branches/schema-plugins/t/TestApp/lib/TestApp branches/schema-plugins/t/TestApp/lib/TestApp/Action branches/schema-plugins/t/TestApp/lib/TestApp/Model branches/schema-plugins/t/TestApp/share branches/schema-plugins/t/TestApp/share/web branches/schema-plugins/t/TestApp/share/web/static branches/schema-plugins/t/TestApp/share/web/static/images branches/schema-plugins/t/TestApp/share/web/templates branches/schema-plugins/t/TestApp/share/web/templates/dispatch branches/schema-plugins/t/TestApp/share/web/templates/regions branches/schema-plugins/t/TestApp/share/web/templates/somedir branches/schema-plugins/t/TestApp/t branches/schema-plugins/t/lib branches/schema-plugins/t/lib/Jifty

jifty-commit at lists.jifty.org jifty-commit at lists.jifty.org
Mon Jan 29 21:05:31 EST 2007


Author: sterling
Date: Mon Jan 29 21:05:02 2007
New Revision: 2734

Added:
   jifty/branches/schema-plugins/   (props changed)
   jifty/branches/schema-plugins/AUTHORS
   jifty/branches/schema-plugins/Changelog
   jifty/branches/schema-plugins/MANIFEST
   jifty/branches/schema-plugins/MANIFEST.SKIP
   jifty/branches/schema-plugins/META.yml
   jifty/branches/schema-plugins/Makefile.PL
   jifty/branches/schema-plugins/README
   jifty/branches/schema-plugins/SIGNATURE
   jifty/branches/schema-plugins/bin/
   jifty/branches/schema-plugins/bin/build_par
   jifty/branches/schema-plugins/bin/jifty   (contents, props changed)
   jifty/branches/schema-plugins/bin/runcover   (contents, props changed)
   jifty/branches/schema-plugins/bin/service   (contents, props changed)
   jifty/branches/schema-plugins/bin/xgettext
   jifty/branches/schema-plugins/debian/
   jifty/branches/schema-plugins/debian/README
   jifty/branches/schema-plugins/debian/changelog
   jifty/branches/schema-plugins/debian/compat
   jifty/branches/schema-plugins/debian/control
   jifty/branches/schema-plugins/debian/rules   (contents, props changed)
   jifty/branches/schema-plugins/doc/
   jifty/branches/schema-plugins/doc/ajax-upgraded-links
   jifty/branches/schema-plugins/doc/building_a_par
   jifty/branches/schema-plugins/doc/client_side_continuations
   jifty/branches/schema-plugins/doc/command_naming
   jifty/branches/schema-plugins/doc/declarative-test-design
   jifty/branches/schema-plugins/doc/edit-in-place
   jifty/branches/schema-plugins/doc/examples/
   jifty/branches/schema-plugins/doc/examples/CounterDemo/
   jifty/branches/schema-plugins/doc/examples/CounterDemo/Makefile.PL
   jifty/branches/schema-plugins/doc/examples/CounterDemo/bin/
   jifty/branches/schema-plugins/doc/examples/CounterDemo/bin/jifty   (contents, props changed)
   jifty/branches/schema-plugins/doc/examples/CounterDemo/doc/
   jifty/branches/schema-plugins/doc/examples/CounterDemo/etc/
   jifty/branches/schema-plugins/doc/examples/CounterDemo/etc/config.yml
   jifty/branches/schema-plugins/doc/examples/CounterDemo/lib/
   jifty/branches/schema-plugins/doc/examples/CounterDemo/lib/CounterDemo/
   jifty/branches/schema-plugins/doc/examples/CounterDemo/lib/CounterDemo/Action/
   jifty/branches/schema-plugins/doc/examples/CounterDemo/lib/CounterDemo/Model/
   jifty/branches/schema-plugins/doc/examples/CounterDemo/log/
   jifty/branches/schema-plugins/doc/examples/CounterDemo/share/
   jifty/branches/schema-plugins/doc/examples/CounterDemo/share/po/
   jifty/branches/schema-plugins/doc/examples/CounterDemo/share/web/
   jifty/branches/schema-plugins/doc/examples/CounterDemo/share/web/static/
   jifty/branches/schema-plugins/doc/examples/CounterDemo/share/web/templates/
   jifty/branches/schema-plugins/doc/examples/CounterDemo/share/web/templates/index.html
   jifty/branches/schema-plugins/doc/examples/CounterDemo/t/
   jifty/branches/schema-plugins/doc/examples/CounterDemo/t/00-counter-test.t   (contents, props changed)
   jifty/branches/schema-plugins/doc/examples/CounterDemo/var/
   jifty/branches/schema-plugins/doc/examples/CounterDemo/var/mason/
   jifty/branches/schema-plugins/doc/examples/CounterDemo/var/mason/cache/
   jifty/branches/schema-plugins/doc/examples/CounterDemo/var/mason/obj/
   jifty/branches/schema-plugins/doc/jifty-action-record-search
   jifty/branches/schema-plugins/doc/jifty-dispatcher.graffle
   jifty/branches/schema-plugins/doc/jifty-dispatcher.svg
   jifty/branches/schema-plugins/doc/jifty-model-svk
   jifty/branches/schema-plugins/doc/jifty-plugins-2.0
   jifty/branches/schema-plugins/doc/jifty-web-form-etc
   jifty/branches/schema-plugins/doc/packaging
   jifty/branches/schema-plugins/doc/plugin-requirements
   jifty/branches/schema-plugins/doc/plugin-syntax
   jifty/branches/schema-plugins/doc/plugins-restated-assumptions
   jifty/branches/schema-plugins/doc/pubsub/
   jifty/branches/schema-plugins/doc/pubsub/backend_message_types
   jifty/branches/schema-plugins/doc/pubsub/subscriptions
   jifty/branches/schema-plugins/doc/pubsub/system_architecture.graffle
   jifty/branches/schema-plugins/doc/pubsub/system_architecture.png   (contents, props changed)
   jifty/branches/schema-plugins/doc/talks/
   jifty/branches/schema-plugins/doc/talks/amazon-jifty.pdf   (contents, props changed)
   jifty/branches/schema-plugins/doc/talks/blogdemo.png   (contents, props changed)
   jifty/branches/schema-plugins/doc/talks/component-tree.png   (contents, props changed)
   jifty/branches/schema-plugins/doc/talks/edit.png   (contents, props changed)
   jifty/branches/schema-plugins/doc/talks/error.png   (contents, props changed)
   jifty/branches/schema-plugins/doc/talks/euroscon.css
   jifty/branches/schema-plugins/doc/talks/halo-overview.png   (contents, props changed)
   jifty/branches/schema-plugins/doc/talks/halo.png   (contents, props changed)
   jifty/branches/schema-plugins/doc/talks/lpw_intro_jifty_2006.key.tgz   (contents, props changed)
   jifty/branches/schema-plugins/doc/talks/lpw_intro_jifty_2006.pdf   (contents, props changed)
   jifty/branches/schema-plugins/doc/talks/lpw_scary_jifty.key.tgz   (contents, props changed)
   jifty/branches/schema-plugins/doc/talks/lpw_scary_jifty.pdf   (contents, props changed)
   jifty/branches/schema-plugins/doc/talks/new-entry.png   (contents, props changed)
   jifty/branches/schema-plugins/doc/talks/npw.2006/
   jifty/branches/schema-plugins/doc/talks/npw.2006.xul   (contents, props changed)
   jifty/branches/schema-plugins/doc/talks/npw.2006/Blog/
   jifty/branches/schema-plugins/doc/talks/npw.2006/Blog/Makefile.PL
   jifty/branches/schema-plugins/doc/talks/npw.2006/Blog/bin/
   jifty/branches/schema-plugins/doc/talks/npw.2006/Blog/bin/jifty   (contents, props changed)
   jifty/branches/schema-plugins/doc/talks/npw.2006/Blog/doc/
   jifty/branches/schema-plugins/doc/talks/npw.2006/Blog/etc/
   jifty/branches/schema-plugins/doc/talks/npw.2006/Blog/etc/config.yml
   jifty/branches/schema-plugins/doc/talks/npw.2006/Blog/lib/
   jifty/branches/schema-plugins/doc/talks/npw.2006/Blog/lib/Blog/
   jifty/branches/schema-plugins/doc/talks/npw.2006/Blog/lib/Blog/Action/
   jifty/branches/schema-plugins/doc/talks/npw.2006/Blog/lib/Blog/Dispatcher.pm
   jifty/branches/schema-plugins/doc/talks/npw.2006/Blog/lib/Blog/Model/
   jifty/branches/schema-plugins/doc/talks/npw.2006/Blog/lib/Blog/Model/Entry.pm
   jifty/branches/schema-plugins/doc/talks/npw.2006/Blog/log/
   jifty/branches/schema-plugins/doc/talks/npw.2006/Blog/share/
   jifty/branches/schema-plugins/doc/talks/npw.2006/Blog/share/po/
   jifty/branches/schema-plugins/doc/talks/npw.2006/Blog/share/web/
   jifty/branches/schema-plugins/doc/talks/npw.2006/Blog/share/web/static/
   jifty/branches/schema-plugins/doc/talks/npw.2006/Blog/share/web/templates/
   jifty/branches/schema-plugins/doc/talks/npw.2006/Blog/share/web/templates/index.html
   jifty/branches/schema-plugins/doc/talks/npw.2006/Blog/share/web/templates/new_entry
   jifty/branches/schema-plugins/doc/talks/npw.2006/Blog/t/
   jifty/branches/schema-plugins/doc/talks/npw.2006/Blog/t/00-model-Entry.t
   jifty/branches/schema-plugins/doc/talks/npw.2006/Blog/var/
   jifty/branches/schema-plugins/doc/talks/npw.2006/blog.png   (contents, props changed)
   jifty/branches/schema-plugins/doc/talks/npw.2006/canonicalize_entry.png   (contents, props changed)
   jifty/branches/schema-plugins/doc/talks/npw.2006/halo.png   (contents, props changed)
   jifty/branches/schema-plugins/doc/talks/npw.2006/halo2.png   (contents, props changed)
   jifty/branches/schema-plugins/doc/talks/npw.2006/hello.png   (contents, props changed)
   jifty/branches/schema-plugins/doc/talks/npw.2006/hello_jesse.png   (contents, props changed)
   jifty/branches/schema-plugins/doc/talks/npw.2006/jifty_3_files.png   (contents, props changed)
   jifty/branches/schema-plugins/doc/talks/npw.2006/jifty_app.png   (contents, props changed)
   jifty/branches/schema-plugins/doc/talks/npw.2006/jifty_edit_model.png   (contents, props changed)
   jifty/branches/schema-plugins/doc/talks/npw.2006/jifty_model.png   (contents, props changed)
   jifty/branches/schema-plugins/doc/talks/npw.2006/jifty_schema_setup.png   (contents, props changed)
   jifty/branches/schema-plugins/doc/talks/npw.2006/jifty_server.png   (contents, props changed)
   jifty/branches/schema-plugins/doc/talks/npw.2006/jifty_web_1.png   (contents, props changed)
   jifty/branches/schema-plugins/doc/talks/npw.2006/jifty_web_crud.png   (contents, props changed)
   jifty/branches/schema-plugins/doc/talks/npw.2006/jifty_web_crud_create_2.png   (contents, props changed)
   jifty/branches/schema-plugins/doc/talks/npw.2006/jifty_web_crud_edit.png   (contents, props changed)
   jifty/branches/schema-plugins/doc/talks/npw.2006/jifty_web_crud_edited.png   (contents, props changed)
   jifty/branches/schema-plugins/doc/talks/npw.2006/jifty_web_crud_new.png   (contents, props changed)
   jifty/branches/schema-plugins/doc/talks/npw.2006/jifty_web_dbadmin.png   (contents, props changed)
   jifty/branches/schema-plugins/doc/talks/npw.2006/makefile_pl.png   (contents, props changed)
   jifty/branches/schema-plugins/doc/talks/npw.2006/new_entry.png   (contents, props changed)
   jifty/branches/schema-plugins/doc/talks/npw.2006/online_docs.png   (contents, props changed)
   jifty/branches/schema-plugins/doc/talks/npw.2006/tests.png   (contents, props changed)
   jifty/branches/schema-plugins/doc/talks/npw.2006/validate_entry.png   (contents, props changed)
   jifty/branches/schema-plugins/doc/talks/npw2005.xul   (contents, props changed)
   jifty/branches/schema-plugins/doc/talks/oscon-europe.2006.xul   (contents, props changed)
   jifty/branches/schema-plugins/doc/talks/oscon.2006.xul   (contents, props changed)
   jifty/branches/schema-plugins/doc/talks/pony.jpg   (contents, props changed)
   jifty/branches/schema-plugins/doc/talks/pony.png   (contents, props changed)
   jifty/branches/schema-plugins/doc/talks/takahashi.css
   jifty/branches/schema-plugins/doc/talks/takahashi.js
   jifty/branches/schema-plugins/doc/talks/yapc.asia.2006.xul   (contents, props changed)
   jifty/branches/schema-plugins/doc/talks/yapc.na.2006.xul   (contents, props changed)
   jifty/branches/schema-plugins/etc/
   jifty/branches/schema-plugins/etc/config.yml
   jifty/branches/schema-plugins/etc/site_config.yml
   jifty/branches/schema-plugins/examples/
   jifty/branches/schema-plugins/examples/Chat/
   jifty/branches/schema-plugins/examples/Chat/Makefile.PL
   jifty/branches/schema-plugins/examples/Chat/bin/
   jifty/branches/schema-plugins/examples/Chat/bin/jifty   (contents, props changed)
   jifty/branches/schema-plugins/examples/Chat/doc/
   jifty/branches/schema-plugins/examples/Chat/etc/
   jifty/branches/schema-plugins/examples/Chat/etc/config.yml
   jifty/branches/schema-plugins/examples/Chat/lib/
   jifty/branches/schema-plugins/examples/Chat/lib/Chat/
   jifty/branches/schema-plugins/examples/Chat/lib/Chat/Action/
   jifty/branches/schema-plugins/examples/Chat/lib/Chat/Action/Send.pm
   jifty/branches/schema-plugins/examples/Chat/lib/Chat/Event/
   jifty/branches/schema-plugins/examples/Chat/lib/Chat/Event/Message.pm
   jifty/branches/schema-plugins/examples/Chat/lib/Chat/Model/
   jifty/branches/schema-plugins/examples/Chat/lib/Chat/Server.pm
   jifty/branches/schema-plugins/examples/Chat/log/
   jifty/branches/schema-plugins/examples/Chat/share/
   jifty/branches/schema-plugins/examples/Chat/share/po/
   jifty/branches/schema-plugins/examples/Chat/share/web/
   jifty/branches/schema-plugins/examples/Chat/share/web/static/
   jifty/branches/schema-plugins/examples/Chat/share/web/templates/
   jifty/branches/schema-plugins/examples/Chat/share/web/templates/fragments/
   jifty/branches/schema-plugins/examples/Chat/share/web/templates/fragments/message
   jifty/branches/schema-plugins/examples/Chat/share/web/templates/fragments/sender
   jifty/branches/schema-plugins/examples/Chat/share/web/templates/index.html
   jifty/branches/schema-plugins/examples/Chat/t/
   jifty/branches/schema-plugins/examples/Chat/t/00compile.t
   jifty/branches/schema-plugins/examples/Chat/t/01startup.t
   jifty/branches/schema-plugins/examples/Chat/var/
   jifty/branches/schema-plugins/examples/Clock/
   jifty/branches/schema-plugins/examples/Clock/Makefile.PL
   jifty/branches/schema-plugins/examples/Clock/bin/
   jifty/branches/schema-plugins/examples/Clock/bin/jifty   (contents, props changed)
   jifty/branches/schema-plugins/examples/Clock/clockserv.pl
   jifty/branches/schema-plugins/examples/Clock/doc/
   jifty/branches/schema-plugins/examples/Clock/etc/
   jifty/branches/schema-plugins/examples/Clock/etc/config.yml
   jifty/branches/schema-plugins/examples/Clock/lib/
   jifty/branches/schema-plugins/examples/Clock/lib/Clock/
   jifty/branches/schema-plugins/examples/Clock/lib/Clock/Action/
   jifty/branches/schema-plugins/examples/Clock/lib/Clock/Event/
   jifty/branches/schema-plugins/examples/Clock/lib/Clock/Event/Tick.pm
   jifty/branches/schema-plugins/examples/Clock/lib/Clock/Model/
   jifty/branches/schema-plugins/examples/Clock/lib/Clock/Server.pm
   jifty/branches/schema-plugins/examples/Clock/log/
   jifty/branches/schema-plugins/examples/Clock/share/
   jifty/branches/schema-plugins/examples/Clock/share/po/
   jifty/branches/schema-plugins/examples/Clock/share/web/
   jifty/branches/schema-plugins/examples/Clock/share/web/templates/
   jifty/branches/schema-plugins/examples/Clock/share/web/templates/fragments/
   jifty/branches/schema-plugins/examples/Clock/share/web/templates/fragments/time
   jifty/branches/schema-plugins/examples/Clock/share/web/templates/index.html
   jifty/branches/schema-plugins/examples/Clock/t/
   jifty/branches/schema-plugins/examples/Clock/var/
   jifty/branches/schema-plugins/examples/MyWeblog/
   jifty/branches/schema-plugins/examples/MyWeblog/Makefile.PL
   jifty/branches/schema-plugins/examples/MyWeblog/bin/
   jifty/branches/schema-plugins/examples/MyWeblog/bin/jifty   (contents, props changed)
   jifty/branches/schema-plugins/examples/MyWeblog/doc/
   jifty/branches/schema-plugins/examples/MyWeblog/etc/
   jifty/branches/schema-plugins/examples/MyWeblog/etc/config.yml
   jifty/branches/schema-plugins/examples/MyWeblog/lib/
   jifty/branches/schema-plugins/examples/MyWeblog/lib/MyWeblog/
   jifty/branches/schema-plugins/examples/MyWeblog/lib/MyWeblog/Action/
   jifty/branches/schema-plugins/examples/MyWeblog/lib/MyWeblog/Model/
   jifty/branches/schema-plugins/examples/MyWeblog/lib/MyWeblog/Model/Post.pm
   jifty/branches/schema-plugins/examples/MyWeblog/share/
   jifty/branches/schema-plugins/examples/MyWeblog/share/po/
   jifty/branches/schema-plugins/examples/MyWeblog/share/web/
   jifty/branches/schema-plugins/examples/MyWeblog/share/web/static/
   jifty/branches/schema-plugins/examples/MyWeblog/share/web/templates/
   jifty/branches/schema-plugins/examples/MyWeblog/share/web/templates/_elements/
   jifty/branches/schema-plugins/examples/MyWeblog/share/web/templates/_elements/nav
   jifty/branches/schema-plugins/examples/MyWeblog/share/web/templates/fragments/
   jifty/branches/schema-plugins/examples/MyWeblog/share/web/templates/fragments/page_of_posts
   jifty/branches/schema-plugins/examples/MyWeblog/share/web/templates/index.html
   jifty/branches/schema-plugins/examples/MyWeblog/share/web/templates/post
   jifty/branches/schema-plugins/examples/MyWeblog/t/
   jifty/branches/schema-plugins/examples/MyWeblog/t/00-model-Post.t
   jifty/branches/schema-plugins/examples/MyWeblog/var/
   jifty/branches/schema-plugins/examples/MyWeblog/var/mason/
   jifty/branches/schema-plugins/examples/MyWeblog/var/mason/cache/
   jifty/branches/schema-plugins/examples/Ping/
   jifty/branches/schema-plugins/examples/Ping/Makefile.PL
   jifty/branches/schema-plugins/examples/Ping/bin/
   jifty/branches/schema-plugins/examples/Ping/bin/jifty   (contents, props changed)
   jifty/branches/schema-plugins/examples/Ping/doc/
   jifty/branches/schema-plugins/examples/Ping/etc/
   jifty/branches/schema-plugins/examples/Ping/etc/config.yml
   jifty/branches/schema-plugins/examples/Ping/lib/
   jifty/branches/schema-plugins/examples/Ping/lib/Ping/
   jifty/branches/schema-plugins/examples/Ping/lib/Ping/Action/
   jifty/branches/schema-plugins/examples/Ping/lib/Ping/Action/AddPing.pm
   jifty/branches/schema-plugins/examples/Ping/lib/Ping/Action/CancelPing.pm
   jifty/branches/schema-plugins/examples/Ping/lib/Ping/Event/
   jifty/branches/schema-plugins/examples/Ping/lib/Ping/Event/Pong.pm
   jifty/branches/schema-plugins/examples/Ping/lib/Ping/Model/
   jifty/branches/schema-plugins/examples/Ping/lib/Ping/PingServer.pm
   jifty/branches/schema-plugins/examples/Ping/lib/Ping/Server.pm
   jifty/branches/schema-plugins/examples/Ping/log/
   jifty/branches/schema-plugins/examples/Ping/share/
   jifty/branches/schema-plugins/examples/Ping/share/po/
   jifty/branches/schema-plugins/examples/Ping/share/web/
   jifty/branches/schema-plugins/examples/Ping/share/web/static/
   jifty/branches/schema-plugins/examples/Ping/share/web/templates/
   jifty/branches/schema-plugins/examples/Ping/share/web/templates/fragments/
   jifty/branches/schema-plugins/examples/Ping/share/web/templates/fragments/pong
   jifty/branches/schema-plugins/examples/Ping/share/web/templates/index.html
   jifty/branches/schema-plugins/examples/Ping/t/
   jifty/branches/schema-plugins/examples/Ping/t/00compile.t
   jifty/branches/schema-plugins/examples/Ping/t/01startup.t
   jifty/branches/schema-plugins/inc/   (props changed)
   jifty/branches/schema-plugins/inc/Module/
   jifty/branches/schema-plugins/inc/Module/AutoInstall.pm
   jifty/branches/schema-plugins/inc/Module/Install/
   jifty/branches/schema-plugins/inc/Module/Install.pm
   jifty/branches/schema-plugins/inc/Module/Install/AutoInstall.pm
   jifty/branches/schema-plugins/inc/Module/Install/Base.pm
   jifty/branches/schema-plugins/inc/Module/Install/Can.pm
   jifty/branches/schema-plugins/inc/Module/Install/Fetch.pm
   jifty/branches/schema-plugins/inc/Module/Install/Include.pm
   jifty/branches/schema-plugins/inc/Module/Install/Makefile.pm
   jifty/branches/schema-plugins/inc/Module/Install/Metadata.pm
   jifty/branches/schema-plugins/inc/Module/Install/Scripts.pm
   jifty/branches/schema-plugins/inc/Module/Install/Share.pm
   jifty/branches/schema-plugins/inc/Module/Install/Win32.pm
   jifty/branches/schema-plugins/inc/Module/Install/WriteAll.pm
   jifty/branches/schema-plugins/lib/
   jifty/branches/schema-plugins/lib/Email/
   jifty/branches/schema-plugins/lib/Email/Send/
   jifty/branches/schema-plugins/lib/Email/Send/Jifty/
   jifty/branches/schema-plugins/lib/Email/Send/Jifty/Test.pm
   jifty/branches/schema-plugins/lib/Jifty/
   jifty/branches/schema-plugins/lib/Jifty.pm
   jifty/branches/schema-plugins/lib/Jifty/API.pm
   jifty/branches/schema-plugins/lib/Jifty/Action/
   jifty/branches/schema-plugins/lib/Jifty/Action.pm
   jifty/branches/schema-plugins/lib/Jifty/Action/Autocomplete.pm
   jifty/branches/schema-plugins/lib/Jifty/Action/Devel/
   jifty/branches/schema-plugins/lib/Jifty/Action/Record/
   jifty/branches/schema-plugins/lib/Jifty/Action/Record.pm
   jifty/branches/schema-plugins/lib/Jifty/Action/Record/Create.pm
   jifty/branches/schema-plugins/lib/Jifty/Action/Record/Delete.pm
   jifty/branches/schema-plugins/lib/Jifty/Action/Record/Search.pm
   jifty/branches/schema-plugins/lib/Jifty/Action/Record/Update.pm
   jifty/branches/schema-plugins/lib/Jifty/Action/Redirect.pm
   jifty/branches/schema-plugins/lib/Jifty/Bootstrap.pm
   jifty/branches/schema-plugins/lib/Jifty/ClassLoader.pm
   jifty/branches/schema-plugins/lib/Jifty/Client.pm
   jifty/branches/schema-plugins/lib/Jifty/Collection.pm
   jifty/branches/schema-plugins/lib/Jifty/Config.pm
   jifty/branches/schema-plugins/lib/Jifty/Continuation.pm
   jifty/branches/schema-plugins/lib/Jifty/CurrentUser.pm
   jifty/branches/schema-plugins/lib/Jifty/DateTime.pm
   jifty/branches/schema-plugins/lib/Jifty/Dispatcher.pm
   jifty/branches/schema-plugins/lib/Jifty/Event/
   jifty/branches/schema-plugins/lib/Jifty/Event.pm
   jifty/branches/schema-plugins/lib/Jifty/Event/Model.pm
   jifty/branches/schema-plugins/lib/Jifty/Everything.pm
   jifty/branches/schema-plugins/lib/Jifty/Filter/
   jifty/branches/schema-plugins/lib/Jifty/Filter/DateTime.pm
   jifty/branches/schema-plugins/lib/Jifty/Handle.pm
   jifty/branches/schema-plugins/lib/Jifty/Handler.pm
   jifty/branches/schema-plugins/lib/Jifty/I18N.pm
   jifty/branches/schema-plugins/lib/Jifty/JSON.pm
   jifty/branches/schema-plugins/lib/Jifty/LetMe.pm   (contents, props changed)
   jifty/branches/schema-plugins/lib/Jifty/Logger.pm
   jifty/branches/schema-plugins/lib/Jifty/Manual/
   jifty/branches/schema-plugins/lib/Jifty/Manual/AccessControl.pod
   jifty/branches/schema-plugins/lib/Jifty/Manual/Actions.pod
   jifty/branches/schema-plugins/lib/Jifty/Manual/Continuations.pod
   jifty/branches/schema-plugins/lib/Jifty/Manual/Cookbook.pod
   jifty/branches/schema-plugins/lib/Jifty/Manual/FAQ.pod
   jifty/branches/schema-plugins/lib/Jifty/Manual/Glossary.pod
   jifty/branches/schema-plugins/lib/Jifty/Manual/Models.pod
   jifty/branches/schema-plugins/lib/Jifty/Manual/ObjectModel.pod
   jifty/branches/schema-plugins/lib/Jifty/Manual/PageRegions.pod
   jifty/branches/schema-plugins/lib/Jifty/Manual/RequestHandling.pod
   jifty/branches/schema-plugins/lib/Jifty/Manual/Style.pod
   jifty/branches/schema-plugins/lib/Jifty/Manual/Tutorial.pod
   jifty/branches/schema-plugins/lib/Jifty/Manual/Tutorial_de.pod
   jifty/branches/schema-plugins/lib/Jifty/Manual/Tutorial_ja.pod
   jifty/branches/schema-plugins/lib/Jifty/Manual/Upgrading.pod
   jifty/branches/schema-plugins/lib/Jifty/Manual/UsingCSSandJS.pod
   jifty/branches/schema-plugins/lib/Jifty/Mason/
   jifty/branches/schema-plugins/lib/Jifty/Mason/Halo.pm
   jifty/branches/schema-plugins/lib/Jifty/Model/
   jifty/branches/schema-plugins/lib/Jifty/Model/Metadata.pm
   jifty/branches/schema-plugins/lib/Jifty/Model/Session.pm
   jifty/branches/schema-plugins/lib/Jifty/Model/SessionCollection.pm
   jifty/branches/schema-plugins/lib/Jifty/Module/
   jifty/branches/schema-plugins/lib/Jifty/Module/Pluggable.pm
   jifty/branches/schema-plugins/lib/Jifty/Notification.pm
   jifty/branches/schema-plugins/lib/Jifty/Object.pm
   jifty/branches/schema-plugins/lib/Jifty/Param/
   jifty/branches/schema-plugins/lib/Jifty/Param.pm
   jifty/branches/schema-plugins/lib/Jifty/Param/Schema.pm
   jifty/branches/schema-plugins/lib/Jifty/Plugin/
   jifty/branches/schema-plugins/lib/Jifty/Plugin.pm
   jifty/branches/schema-plugins/lib/Jifty/Plugin/ClassLoader.pm
   jifty/branches/schema-plugins/lib/Jifty/Plugin/REST/
   jifty/branches/schema-plugins/lib/Jifty/Plugin/REST.pm
   jifty/branches/schema-plugins/lib/Jifty/Plugin/REST/Dispatcher.pm
   jifty/branches/schema-plugins/lib/Jifty/Record.pm
   jifty/branches/schema-plugins/lib/Jifty/Request/
   jifty/branches/schema-plugins/lib/Jifty/Request.pm
   jifty/branches/schema-plugins/lib/Jifty/Request/Mapper.pm
   jifty/branches/schema-plugins/lib/Jifty/Response.pm
   jifty/branches/schema-plugins/lib/Jifty/Result.pm
   jifty/branches/schema-plugins/lib/Jifty/RightsFrom.pm
   jifty/branches/schema-plugins/lib/Jifty/Script/
   jifty/branches/schema-plugins/lib/Jifty/Script.pm
   jifty/branches/schema-plugins/lib/Jifty/Script/Action.pm
   jifty/branches/schema-plugins/lib/Jifty/Script/App.pm
   jifty/branches/schema-plugins/lib/Jifty/Script/Deps.pm
   jifty/branches/schema-plugins/lib/Jifty/Script/FastCGI.pm   (contents, props changed)
   jifty/branches/schema-plugins/lib/Jifty/Script/Help.pm
   jifty/branches/schema-plugins/lib/Jifty/Script/Model.pm
   jifty/branches/schema-plugins/lib/Jifty/Script/Plugin.pm
   jifty/branches/schema-plugins/lib/Jifty/Script/Po.pm
   jifty/branches/schema-plugins/lib/Jifty/Script/Schema.pm   (contents, props changed)
   jifty/branches/schema-plugins/lib/Jifty/Script/Server.pm   (contents, props changed)
   jifty/branches/schema-plugins/lib/Jifty/Server.pm
   jifty/branches/schema-plugins/lib/Jifty/Subs/
   jifty/branches/schema-plugins/lib/Jifty/Subs.pm   (contents, props changed)
   jifty/branches/schema-plugins/lib/Jifty/Subs/Render.pm   (contents, props changed)
   jifty/branches/schema-plugins/lib/Jifty/Test/
   jifty/branches/schema-plugins/lib/Jifty/Test.pm
   jifty/branches/schema-plugins/lib/Jifty/Test/WWW/
   jifty/branches/schema-plugins/lib/Jifty/Test/WWW/Mechanize.pm
   jifty/branches/schema-plugins/lib/Jifty/TestServer.pm   (contents, props changed)
   jifty/branches/schema-plugins/lib/Jifty/Upgrade/
   jifty/branches/schema-plugins/lib/Jifty/Upgrade.pm
   jifty/branches/schema-plugins/lib/Jifty/Upgrade/Internal.pm
   jifty/branches/schema-plugins/lib/Jifty/Util.pm
   jifty/branches/schema-plugins/lib/Jifty/View/
   jifty/branches/schema-plugins/lib/Jifty/View/Mason/
   jifty/branches/schema-plugins/lib/Jifty/View/Mason/Handler.pm
   jifty/branches/schema-plugins/lib/Jifty/View/Static/
   jifty/branches/schema-plugins/lib/Jifty/View/Static/Handler.pm
   jifty/branches/schema-plugins/lib/Jifty/Web/
   jifty/branches/schema-plugins/lib/Jifty/Web.pm
   jifty/branches/schema-plugins/lib/Jifty/Web/Form/
   jifty/branches/schema-plugins/lib/Jifty/Web/Form.pm
   jifty/branches/schema-plugins/lib/Jifty/Web/Form/Clickable.pm
   jifty/branches/schema-plugins/lib/Jifty/Web/Form/Element.pm
   jifty/branches/schema-plugins/lib/Jifty/Web/Form/Field/
   jifty/branches/schema-plugins/lib/Jifty/Web/Form/Field.pm
   jifty/branches/schema-plugins/lib/Jifty/Web/Form/Field/Button.pm
   jifty/branches/schema-plugins/lib/Jifty/Web/Form/Field/Checkbox.pm
   jifty/branches/schema-plugins/lib/Jifty/Web/Form/Field/Combobox.pm
   jifty/branches/schema-plugins/lib/Jifty/Web/Form/Field/Date.pm
   jifty/branches/schema-plugins/lib/Jifty/Web/Form/Field/Hidden.pm
   jifty/branches/schema-plugins/lib/Jifty/Web/Form/Field/InlineButton.pm
   jifty/branches/schema-plugins/lib/Jifty/Web/Form/Field/Password.pm
   jifty/branches/schema-plugins/lib/Jifty/Web/Form/Field/Radio.pm
   jifty/branches/schema-plugins/lib/Jifty/Web/Form/Field/ResetButton.pm
   jifty/branches/schema-plugins/lib/Jifty/Web/Form/Field/Select.pm
   jifty/branches/schema-plugins/lib/Jifty/Web/Form/Field/Text.pm
   jifty/branches/schema-plugins/lib/Jifty/Web/Form/Field/Textarea.pm
   jifty/branches/schema-plugins/lib/Jifty/Web/Form/Field/Unrendered.pm
   jifty/branches/schema-plugins/lib/Jifty/Web/Form/Field/Upload.pm
   jifty/branches/schema-plugins/lib/Jifty/Web/Form/Link.pm
   jifty/branches/schema-plugins/lib/Jifty/Web/Menu.pm
   jifty/branches/schema-plugins/lib/Jifty/Web/PageRegion.pm
   jifty/branches/schema-plugins/lib/Jifty/Web/Session/
   jifty/branches/schema-plugins/lib/Jifty/Web/Session.pm
   jifty/branches/schema-plugins/lib/Jifty/Web/Session/ClientSide.pm
   jifty/branches/schema-plugins/lib/Jifty/YAML.pm
   jifty/branches/schema-plugins/lib/auto/
   jifty/branches/schema-plugins/plugins/
   jifty/branches/schema-plugins/plugins/AuthCASLogin/
   jifty/branches/schema-plugins/plugins/AuthCASLogin/MANIFEST
   jifty/branches/schema-plugins/plugins/AuthCASLogin/Makefile.PL
   jifty/branches/schema-plugins/plugins/AuthCASLogin/debian/
   jifty/branches/schema-plugins/plugins/AuthCASLogin/debian/changelog
   jifty/branches/schema-plugins/plugins/AuthCASLogin/debian/compat
   jifty/branches/schema-plugins/plugins/AuthCASLogin/debian/control
   jifty/branches/schema-plugins/plugins/AuthCASLogin/debian/copyright
   jifty/branches/schema-plugins/plugins/AuthCASLogin/debian/files
   jifty/branches/schema-plugins/plugins/AuthCASLogin/debian/rules   (contents, props changed)
   jifty/branches/schema-plugins/plugins/AuthCASLogin/doc/
   jifty/branches/schema-plugins/plugins/AuthCASLogin/lib/
   jifty/branches/schema-plugins/plugins/AuthCASLogin/lib/Jifty/
   jifty/branches/schema-plugins/plugins/AuthCASLogin/lib/Jifty/Plugin/
   jifty/branches/schema-plugins/plugins/AuthCASLogin/lib/Jifty/Plugin/AuthCASLogin/
   jifty/branches/schema-plugins/plugins/AuthCASLogin/lib/Jifty/Plugin/AuthCASLogin.pm
   jifty/branches/schema-plugins/plugins/AuthCASLogin/lib/Jifty/Plugin/AuthCASLogin/Action/
   jifty/branches/schema-plugins/plugins/AuthCASLogin/lib/Jifty/Plugin/AuthCASLogin/Action/CASLogin.pm
   jifty/branches/schema-plugins/plugins/AuthCASLogin/lib/Jifty/Plugin/AuthCASLogin/Action/CASLogout.pm
   jifty/branches/schema-plugins/plugins/AuthCASLogin/lib/Jifty/Plugin/AuthCASLogin/Dispatcher.pm
   jifty/branches/schema-plugins/plugins/AuthCASLogin/lib/Jifty/Plugin/AuthCASLogin/Model/
   jifty/branches/schema-plugins/plugins/AuthCASLogin/share/
   jifty/branches/schema-plugins/plugins/AuthCASLogin/share/po/
   jifty/branches/schema-plugins/plugins/AuthCASLogin/share/web/
   jifty/branches/schema-plugins/plugins/AuthCASLogin/share/web/static/
   jifty/branches/schema-plugins/plugins/AuthCASLogin/share/web/templates/
   jifty/branches/schema-plugins/plugins/AuthCASLogin/share/web/templates/caslogin
   jifty/branches/schema-plugins/plugins/AuthCASLogin/share/web/templates/caslogout
   jifty/branches/schema-plugins/plugins/AuthCASLogin/t/
   jifty/branches/schema-plugins/plugins/AuthCASLogin/t/00-load.t
   jifty/branches/schema-plugins/plugins/AuthCASOnly/
   jifty/branches/schema-plugins/plugins/AuthCASOnly/MANIFEST
   jifty/branches/schema-plugins/plugins/AuthCASOnly/MANIFEST.bak
   jifty/branches/schema-plugins/plugins/AuthCASOnly/META.yml
   jifty/branches/schema-plugins/plugins/AuthCASOnly/Makefile
   jifty/branches/schema-plugins/plugins/AuthCASOnly/Makefile.PL
   jifty/branches/schema-plugins/plugins/AuthCASOnly/debian/
   jifty/branches/schema-plugins/plugins/AuthCASOnly/debian/changelog
   jifty/branches/schema-plugins/plugins/AuthCASOnly/debian/compat
   jifty/branches/schema-plugins/plugins/AuthCASOnly/debian/control
   jifty/branches/schema-plugins/plugins/AuthCASOnly/debian/copyright
   jifty/branches/schema-plugins/plugins/AuthCASOnly/debian/files
   jifty/branches/schema-plugins/plugins/AuthCASOnly/debian/rules   (contents, props changed)
   jifty/branches/schema-plugins/plugins/AuthCASOnly/doc/
   jifty/branches/schema-plugins/plugins/AuthCASOnly/lib/
   jifty/branches/schema-plugins/plugins/AuthCASOnly/lib/Jifty/
   jifty/branches/schema-plugins/plugins/AuthCASOnly/lib/Jifty/Plugin/
   jifty/branches/schema-plugins/plugins/AuthCASOnly/lib/Jifty/Plugin/AuthCASOnly/
   jifty/branches/schema-plugins/plugins/AuthCASOnly/lib/Jifty/Plugin/AuthCASOnly.pm
   jifty/branches/schema-plugins/plugins/AuthCASOnly/lib/Jifty/Plugin/AuthCASOnly/Action/
   jifty/branches/schema-plugins/plugins/AuthCASOnly/lib/Jifty/Plugin/AuthCASOnly/Action/CASLogin.pm
   jifty/branches/schema-plugins/plugins/AuthCASOnly/lib/Jifty/Plugin/AuthCASOnly/Action/CASLogout.pm
   jifty/branches/schema-plugins/plugins/AuthCASOnly/lib/Jifty/Plugin/AuthCASOnly/CurrentUser.pm
   jifty/branches/schema-plugins/plugins/AuthCASOnly/lib/Jifty/Plugin/AuthCASOnly/Dispatcher.pm
   jifty/branches/schema-plugins/plugins/AuthCASOnly/lib/Jifty/Plugin/AuthCASOnly/Model/
   jifty/branches/schema-plugins/plugins/AuthCASOnly/lib/Jifty/Plugin/AuthCASOnly/Model/CASUser.pm
   jifty/branches/schema-plugins/plugins/AuthCASOnly/share/
   jifty/branches/schema-plugins/plugins/AuthCASOnly/share/po/
   jifty/branches/schema-plugins/plugins/AuthCASOnly/share/web/
   jifty/branches/schema-plugins/plugins/AuthCASOnly/share/web/static/
   jifty/branches/schema-plugins/plugins/AuthCASOnly/share/web/templates/
   jifty/branches/schema-plugins/plugins/AuthCASOnly/share/web/templates/caslogin
   jifty/branches/schema-plugins/plugins/AuthCASOnly/share/web/templates/caslogout
   jifty/branches/schema-plugins/plugins/AuthCASOnly/t/
   jifty/branches/schema-plugins/plugins/AuthCASOnly/t/00-load.t
   jifty/branches/schema-plugins/plugins/AuthLDAPLogin/
   jifty/branches/schema-plugins/plugins/AuthLDAPLogin/MANIFEST
   jifty/branches/schema-plugins/plugins/AuthLDAPLogin/Makefile.PL
   jifty/branches/schema-plugins/plugins/AuthLDAPLogin/debian/
   jifty/branches/schema-plugins/plugins/AuthLDAPLogin/debian/changelog
   jifty/branches/schema-plugins/plugins/AuthLDAPLogin/debian/compat
   jifty/branches/schema-plugins/plugins/AuthLDAPLogin/debian/control
   jifty/branches/schema-plugins/plugins/AuthLDAPLogin/debian/copyright
   jifty/branches/schema-plugins/plugins/AuthLDAPLogin/debian/rules   (contents, props changed)
   jifty/branches/schema-plugins/plugins/AuthLDAPLogin/doc/
   jifty/branches/schema-plugins/plugins/AuthLDAPLogin/lib/
   jifty/branches/schema-plugins/plugins/AuthLDAPLogin/lib/Jifty/
   jifty/branches/schema-plugins/plugins/AuthLDAPLogin/lib/Jifty/Plugin/
   jifty/branches/schema-plugins/plugins/AuthLDAPLogin/lib/Jifty/Plugin/AuthLDAPLogin/
   jifty/branches/schema-plugins/plugins/AuthLDAPLogin/lib/Jifty/Plugin/AuthLDAPLogin.pm
   jifty/branches/schema-plugins/plugins/AuthLDAPLogin/lib/Jifty/Plugin/AuthLDAPLogin/Action/
   jifty/branches/schema-plugins/plugins/AuthLDAPLogin/lib/Jifty/Plugin/AuthLDAPLogin/Action/LDAPLogin.pm
   jifty/branches/schema-plugins/plugins/AuthLDAPLogin/lib/Jifty/Plugin/AuthLDAPLogin/Action/LDAPLogout.pm
   jifty/branches/schema-plugins/plugins/AuthLDAPLogin/lib/Jifty/Plugin/AuthLDAPLogin/Dispatcher.pm
   jifty/branches/schema-plugins/plugins/AuthLDAPLogin/lib/Jifty/Plugin/AuthLDAPLogin/Model/
   jifty/branches/schema-plugins/plugins/AuthLDAPLogin/share/
   jifty/branches/schema-plugins/plugins/AuthLDAPLogin/share/po/
   jifty/branches/schema-plugins/plugins/AuthLDAPLogin/share/po/en.po
   jifty/branches/schema-plugins/plugins/AuthLDAPLogin/share/po/fr.po
   jifty/branches/schema-plugins/plugins/AuthLDAPLogin/share/web/
   jifty/branches/schema-plugins/plugins/AuthLDAPLogin/share/web/static/
   jifty/branches/schema-plugins/plugins/AuthLDAPLogin/share/web/templates/
   jifty/branches/schema-plugins/plugins/AuthLDAPLogin/share/web/templates/ldaplogin
   jifty/branches/schema-plugins/plugins/AuthLDAPLogin/share/web/templates/ldaplogout
   jifty/branches/schema-plugins/plugins/AuthLDAPLogin/t/
   jifty/branches/schema-plugins/plugins/AuthLDAPLogin/t/00-load.t
   jifty/branches/schema-plugins/plugins/AuthLDAPOnly/
   jifty/branches/schema-plugins/plugins/AuthLDAPOnly/MANIFEST
   jifty/branches/schema-plugins/plugins/AuthLDAPOnly/Makefile.PL
   jifty/branches/schema-plugins/plugins/AuthLDAPOnly/debian/
   jifty/branches/schema-plugins/plugins/AuthLDAPOnly/debian/changelog
   jifty/branches/schema-plugins/plugins/AuthLDAPOnly/debian/compat
   jifty/branches/schema-plugins/plugins/AuthLDAPOnly/debian/control
   jifty/branches/schema-plugins/plugins/AuthLDAPOnly/debian/copyright
   jifty/branches/schema-plugins/plugins/AuthLDAPOnly/debian/rules   (contents, props changed)
   jifty/branches/schema-plugins/plugins/AuthLDAPOnly/doc/
   jifty/branches/schema-plugins/plugins/AuthLDAPOnly/lib/
   jifty/branches/schema-plugins/plugins/AuthLDAPOnly/lib/Jifty/
   jifty/branches/schema-plugins/plugins/AuthLDAPOnly/lib/Jifty/Plugin/
   jifty/branches/schema-plugins/plugins/AuthLDAPOnly/lib/Jifty/Plugin/AuthLDAPOnly/
   jifty/branches/schema-plugins/plugins/AuthLDAPOnly/lib/Jifty/Plugin/AuthLDAPOnly.pm
   jifty/branches/schema-plugins/plugins/AuthLDAPOnly/lib/Jifty/Plugin/AuthLDAPOnly/Action/
   jifty/branches/schema-plugins/plugins/AuthLDAPOnly/lib/Jifty/Plugin/AuthLDAPOnly/Action/LDAPLogin.pm
   jifty/branches/schema-plugins/plugins/AuthLDAPOnly/lib/Jifty/Plugin/AuthLDAPOnly/Action/LDAPLogout.pm
   jifty/branches/schema-plugins/plugins/AuthLDAPOnly/lib/Jifty/Plugin/AuthLDAPOnly/CurrentUser.pm
   jifty/branches/schema-plugins/plugins/AuthLDAPOnly/lib/Jifty/Plugin/AuthLDAPOnly/Dispatcher.pm
   jifty/branches/schema-plugins/plugins/AuthLDAPOnly/lib/Jifty/Plugin/AuthLDAPOnly/Model/
   jifty/branches/schema-plugins/plugins/AuthLDAPOnly/lib/Jifty/Plugin/AuthLDAPOnly/Model/LDAPUser.pm
   jifty/branches/schema-plugins/plugins/AuthLDAPOnly/share/
   jifty/branches/schema-plugins/plugins/AuthLDAPOnly/share/po/
   jifty/branches/schema-plugins/plugins/AuthLDAPOnly/share/po/en.po
   jifty/branches/schema-plugins/plugins/AuthLDAPOnly/share/po/fr.po
   jifty/branches/schema-plugins/plugins/AuthLDAPOnly/share/web/
   jifty/branches/schema-plugins/plugins/AuthLDAPOnly/share/web/static/
   jifty/branches/schema-plugins/plugins/AuthLDAPOnly/share/web/templates/
   jifty/branches/schema-plugins/plugins/AuthLDAPOnly/share/web/templates/ldaplogin
   jifty/branches/schema-plugins/plugins/AuthLDAPOnly/share/web/templates/ldaplogout
   jifty/branches/schema-plugins/plugins/AuthLDAPOnly/t/
   jifty/branches/schema-plugins/plugins/AuthLDAPOnly/t/00-load.t
   jifty/branches/schema-plugins/plugins/AuthzLDAP/
   jifty/branches/schema-plugins/plugins/AuthzLDAP/MANIFEST
   jifty/branches/schema-plugins/plugins/AuthzLDAP/Makefile.PL
   jifty/branches/schema-plugins/plugins/AuthzLDAP/doc/
   jifty/branches/schema-plugins/plugins/AuthzLDAP/lib/
   jifty/branches/schema-plugins/plugins/AuthzLDAP/lib/Jifty/
   jifty/branches/schema-plugins/plugins/AuthzLDAP/lib/Jifty/Plugin/
   jifty/branches/schema-plugins/plugins/AuthzLDAP/lib/Jifty/Plugin/AuthzLDAP/
   jifty/branches/schema-plugins/plugins/AuthzLDAP/lib/Jifty/Plugin/AuthzLDAP.pm
   jifty/branches/schema-plugins/plugins/AuthzLDAP/lib/Jifty/Plugin/AuthzLDAP/Action/
   jifty/branches/schema-plugins/plugins/AuthzLDAP/lib/Jifty/Plugin/AuthzLDAP/Action/LDAPValidate.pm
   jifty/branches/schema-plugins/plugins/AuthzLDAP/lib/Jifty/Plugin/AuthzLDAP/Model/
   jifty/branches/schema-plugins/plugins/AuthzLDAP/lib/Jifty/Plugin/AuthzLDAP/Model/LDAPFilter.pm
   jifty/branches/schema-plugins/plugins/AuthzLDAP/share/
   jifty/branches/schema-plugins/plugins/AuthzLDAP/share/po/
   jifty/branches/schema-plugins/plugins/AuthzLDAP/share/po/en.po
   jifty/branches/schema-plugins/plugins/AuthzLDAP/share/po/fr.po
   jifty/branches/schema-plugins/plugins/AuthzLDAP/share/web/
   jifty/branches/schema-plugins/plugins/AuthzLDAP/share/web/static/
   jifty/branches/schema-plugins/plugins/AuthzLDAP/share/web/templates/
   jifty/branches/schema-plugins/plugins/AuthzLDAP/share/web/templates/error/
   jifty/branches/schema-plugins/plugins/AuthzLDAP/share/web/templates/error/AccessDenied
   jifty/branches/schema-plugins/plugins/AuthzLDAP/t/
   jifty/branches/schema-plugins/plugins/AuthzLDAP/t/00-load.t
   jifty/branches/schema-plugins/plugins/EditInPlace/
   jifty/branches/schema-plugins/plugins/EditInPlace/Makefile.PL
   jifty/branches/schema-plugins/plugins/EditInPlace/debian/
   jifty/branches/schema-plugins/plugins/EditInPlace/debian/changelog
   jifty/branches/schema-plugins/plugins/EditInPlace/debian/compat
   jifty/branches/schema-plugins/plugins/EditInPlace/debian/control
   jifty/branches/schema-plugins/plugins/EditInPlace/debian/rules   (contents, props changed)
   jifty/branches/schema-plugins/plugins/EditInPlace/inc/
   jifty/branches/schema-plugins/plugins/EditInPlace/inc/Module/
   jifty/branches/schema-plugins/plugins/EditInPlace/inc/Module/AutoInstall.pm
   jifty/branches/schema-plugins/plugins/EditInPlace/inc/Module/Install/
   jifty/branches/schema-plugins/plugins/EditInPlace/inc/Module/Install.pm
   jifty/branches/schema-plugins/plugins/EditInPlace/inc/Module/Install/AutoInstall.pm
   jifty/branches/schema-plugins/plugins/EditInPlace/inc/Module/Install/Base.pm
   jifty/branches/schema-plugins/plugins/EditInPlace/inc/Module/Install/Can.pm
   jifty/branches/schema-plugins/plugins/EditInPlace/inc/Module/Install/Fetch.pm
   jifty/branches/schema-plugins/plugins/EditInPlace/inc/Module/Install/Include.pm
   jifty/branches/schema-plugins/plugins/EditInPlace/inc/Module/Install/Makefile/
   jifty/branches/schema-plugins/plugins/EditInPlace/inc/Module/Install/Makefile.pm
   jifty/branches/schema-plugins/plugins/EditInPlace/inc/Module/Install/Makefile/Version.pm
   jifty/branches/schema-plugins/plugins/EditInPlace/inc/Module/Install/Metadata.pm
   jifty/branches/schema-plugins/plugins/EditInPlace/inc/Module/Install/Share.pm
   jifty/branches/schema-plugins/plugins/EditInPlace/inc/Module/Install/Win32.pm
   jifty/branches/schema-plugins/plugins/EditInPlace/inc/Module/Install/WriteAll.pm
   jifty/branches/schema-plugins/plugins/EditInPlace/lib/
   jifty/branches/schema-plugins/plugins/EditInPlace/lib/Jifty/
   jifty/branches/schema-plugins/plugins/EditInPlace/lib/Jifty/Plugin/
   jifty/branches/schema-plugins/plugins/EditInPlace/lib/Jifty/Plugin/EditInPlace/
   jifty/branches/schema-plugins/plugins/EditInPlace/lib/Jifty/Plugin/EditInPlace.pm
   jifty/branches/schema-plugins/plugins/EditInPlace/lib/Jifty/Plugin/EditInPlace/Action/
   jifty/branches/schema-plugins/plugins/EditInPlace/lib/Jifty/Plugin/EditInPlace/Action/FileEditor.pm
   jifty/branches/schema-plugins/plugins/EditInPlace/lib/Jifty/Plugin/EditInPlace/Dispatcher.pm
   jifty/branches/schema-plugins/plugins/EditInPlace/share/
   jifty/branches/schema-plugins/plugins/EditInPlace/share/web/
   jifty/branches/schema-plugins/plugins/EditInPlace/share/web/templates/
   jifty/branches/schema-plugins/plugins/EditInPlace/share/web/templates/__jifty/
   jifty/branches/schema-plugins/plugins/EditInPlace/share/web/templates/__jifty/create_file_inline
   jifty/branches/schema-plugins/plugins/EditInPlace/share/web/templates/__jifty/edit_file
   jifty/branches/schema-plugins/plugins/EditInPlace/share/web/templates/__jifty/edit_file_inline
   jifty/branches/schema-plugins/plugins/EmailErrors/
   jifty/branches/schema-plugins/plugins/EmailErrors/Makefile.PL
   jifty/branches/schema-plugins/plugins/EmailErrors/doc/
   jifty/branches/schema-plugins/plugins/EmailErrors/doc/site_config.yml
   jifty/branches/schema-plugins/plugins/EmailErrors/lib/
   jifty/branches/schema-plugins/plugins/EmailErrors/lib/Jifty/
   jifty/branches/schema-plugins/plugins/EmailErrors/lib/Jifty/Plugin/
   jifty/branches/schema-plugins/plugins/EmailErrors/lib/Jifty/Plugin/EmailErrors/
   jifty/branches/schema-plugins/plugins/EmailErrors/lib/Jifty/Plugin/EmailErrors.pm
   jifty/branches/schema-plugins/plugins/EmailErrors/lib/Jifty/Plugin/EmailErrors/Action/
   jifty/branches/schema-plugins/plugins/EmailErrors/lib/Jifty/Plugin/EmailErrors/Dispatcher.pm
   jifty/branches/schema-plugins/plugins/EmailErrors/lib/Jifty/Plugin/EmailErrors/Model/
   jifty/branches/schema-plugins/plugins/EmailErrors/lib/Jifty/Plugin/EmailErrors/Notification/
   jifty/branches/schema-plugins/plugins/EmailErrors/lib/Jifty/Plugin/EmailErrors/Notification/EmailError.pm
   jifty/branches/schema-plugins/plugins/EmailErrors/share/
   jifty/branches/schema-plugins/plugins/EmailErrors/share/web/
   jifty/branches/schema-plugins/plugins/EmailErrors/share/web/templates/
   jifty/branches/schema-plugins/plugins/EmailErrors/share/web/templates/.file
   jifty/branches/schema-plugins/plugins/LetMe/
   jifty/branches/schema-plugins/plugins/LetMe/Makefile.PL
   jifty/branches/schema-plugins/plugins/LetMe/doc/
   jifty/branches/schema-plugins/plugins/LetMe/lib/
   jifty/branches/schema-plugins/plugins/LetMe/lib/Jifty/
   jifty/branches/schema-plugins/plugins/LetMe/lib/Jifty/Plugin/
   jifty/branches/schema-plugins/plugins/LetMe/lib/Jifty/Plugin/LetMe/
   jifty/branches/schema-plugins/plugins/LetMe/lib/Jifty/Plugin/LetMe.pm
   jifty/branches/schema-plugins/plugins/LetMe/lib/Jifty/Plugin/LetMe/Action/
   jifty/branches/schema-plugins/plugins/LetMe/lib/Jifty/Plugin/LetMe/Dispatcher.pm
   jifty/branches/schema-plugins/plugins/LetMe/lib/Jifty/Plugin/LetMe/Model/
   jifty/branches/schema-plugins/plugins/LetMe/share/
   jifty/branches/schema-plugins/plugins/LetMe/share/po/
   jifty/branches/schema-plugins/plugins/LetMe/share/web/
   jifty/branches/schema-plugins/plugins/LetMe/share/web/static/
   jifty/branches/schema-plugins/plugins/LetMe/share/web/templates/
   jifty/branches/schema-plugins/plugins/LetMe/t/
   jifty/branches/schema-plugins/plugins/Login/
   jifty/branches/schema-plugins/plugins/Login/MANIFEST
   jifty/branches/schema-plugins/plugins/Login/META.yml
   jifty/branches/schema-plugins/plugins/Login/Makefile.PL
   jifty/branches/schema-plugins/plugins/Login/debian/
   jifty/branches/schema-plugins/plugins/Login/debian/changelog
   jifty/branches/schema-plugins/plugins/Login/debian/compat
   jifty/branches/schema-plugins/plugins/Login/debian/control
   jifty/branches/schema-plugins/plugins/Login/debian/rules   (contents, props changed)
   jifty/branches/schema-plugins/plugins/Login/doc/
   jifty/branches/schema-plugins/plugins/Login/inc/
   jifty/branches/schema-plugins/plugins/Login/inc/Module/
   jifty/branches/schema-plugins/plugins/Login/inc/Module/Install/
   jifty/branches/schema-plugins/plugins/Login/inc/Module/Install.pm
   jifty/branches/schema-plugins/plugins/Login/inc/Module/Install/Base.pm
   jifty/branches/schema-plugins/plugins/Login/inc/Module/Install/Can.pm
   jifty/branches/schema-plugins/plugins/Login/inc/Module/Install/Fetch.pm
   jifty/branches/schema-plugins/plugins/Login/inc/Module/Install/Makefile.pm
   jifty/branches/schema-plugins/plugins/Login/inc/Module/Install/Metadata.pm
   jifty/branches/schema-plugins/plugins/Login/inc/Module/Install/Share.pm
   jifty/branches/schema-plugins/plugins/Login/inc/Module/Install/Win32.pm
   jifty/branches/schema-plugins/plugins/Login/inc/Module/Install/WriteAll.pm
   jifty/branches/schema-plugins/plugins/Login/lib/
   jifty/branches/schema-plugins/plugins/Login/lib/Jifty/
   jifty/branches/schema-plugins/plugins/Login/lib/Jifty/Plugin/
   jifty/branches/schema-plugins/plugins/Login/lib/Jifty/Plugin/Login/
   jifty/branches/schema-plugins/plugins/Login/lib/Jifty/Plugin/Login.pm
   jifty/branches/schema-plugins/plugins/Login/lib/Jifty/Plugin/Login/Action/
   jifty/branches/schema-plugins/plugins/Login/lib/Jifty/Plugin/Login/Action/ChangePassword.pm
   jifty/branches/schema-plugins/plugins/Login/lib/Jifty/Plugin/Login/Action/ConfirmEmail.pm
   jifty/branches/schema-plugins/plugins/Login/lib/Jifty/Plugin/Login/Action/Login.pm
   jifty/branches/schema-plugins/plugins/Login/lib/Jifty/Plugin/Login/Action/Logout.pm
   jifty/branches/schema-plugins/plugins/Login/lib/Jifty/Plugin/Login/Action/RecoverPassword.pm
   jifty/branches/schema-plugins/plugins/Login/lib/Jifty/Plugin/Login/Action/ResetLostPassword.pm
   jifty/branches/schema-plugins/plugins/Login/lib/Jifty/Plugin/Login/Action/SendAccountConfirmation.pm
   jifty/branches/schema-plugins/plugins/Login/lib/Jifty/Plugin/Login/Action/SendPasswordReminder.pm
   jifty/branches/schema-plugins/plugins/Login/lib/Jifty/Plugin/Login/Action/Signup.pm
   jifty/branches/schema-plugins/plugins/Login/lib/Jifty/Plugin/Login/CurrentUser.pm
   jifty/branches/schema-plugins/plugins/Login/lib/Jifty/Plugin/Login/Dispatcher.pm
   jifty/branches/schema-plugins/plugins/Login/lib/Jifty/Plugin/Login/Model/
   jifty/branches/schema-plugins/plugins/Login/lib/Jifty/Plugin/Login/Model/User.pm
   jifty/branches/schema-plugins/plugins/Login/lib/Jifty/Plugin/Login/Notification/
   jifty/branches/schema-plugins/plugins/Login/lib/Jifty/Plugin/Login/Notification/ConfirmAddress.pm   (contents, props changed)
   jifty/branches/schema-plugins/plugins/Login/lib/Jifty/Plugin/Login/Notification/ConfirmLostPassword.pm
   jifty/branches/schema-plugins/plugins/Login/share/
   jifty/branches/schema-plugins/plugins/Login/share/po/
   jifty/branches/schema-plugins/plugins/Login/share/po/en.po
   jifty/branches/schema-plugins/plugins/Login/share/po/fr.po
   jifty/branches/schema-plugins/plugins/Login/share/web/
   jifty/branches/schema-plugins/plugins/Login/share/web/static/
   jifty/branches/schema-plugins/plugins/Login/share/web/templates/
   jifty/branches/schema-plugins/plugins/Login/share/web/templates/chgpasswd
   jifty/branches/schema-plugins/plugins/Login/share/web/templates/let/
   jifty/branches/schema-plugins/plugins/Login/share/web/templates/let/confirm_email
   jifty/branches/schema-plugins/plugins/Login/share/web/templates/let/reset_lost_password
   jifty/branches/schema-plugins/plugins/Login/share/web/templates/login
   jifty/branches/schema-plugins/plugins/Login/share/web/templates/passwordreminder
   jifty/branches/schema-plugins/plugins/Login/share/web/templates/signup
   jifty/branches/schema-plugins/plugins/Login/t/
   jifty/branches/schema-plugins/plugins/Nothing/
   jifty/branches/schema-plugins/plugins/Nothing/Makefile.PL
   jifty/branches/schema-plugins/plugins/Nothing/doc/
   jifty/branches/schema-plugins/plugins/Nothing/lib/
   jifty/branches/schema-plugins/plugins/Nothing/lib/Jifty/
   jifty/branches/schema-plugins/plugins/Nothing/lib/Jifty/Plugin/
   jifty/branches/schema-plugins/plugins/Nothing/lib/Jifty/Plugin/Nothing/
   jifty/branches/schema-plugins/plugins/Nothing/lib/Jifty/Plugin/Nothing.pm
   jifty/branches/schema-plugins/plugins/Nothing/lib/Jifty/Plugin/Nothing/Action/
   jifty/branches/schema-plugins/plugins/Nothing/lib/Jifty/Plugin/Nothing/Dispatcher.pm
   jifty/branches/schema-plugins/plugins/Nothing/lib/Jifty/Plugin/Nothing/Model/
   jifty/branches/schema-plugins/plugins/Nothing/share/
   jifty/branches/schema-plugins/plugins/Nothing/share/po/
   jifty/branches/schema-plugins/plugins/Nothing/share/web/
   jifty/branches/schema-plugins/plugins/Nothing/share/web/static/
   jifty/branches/schema-plugins/plugins/Nothing/share/web/templates/
   jifty/branches/schema-plugins/plugins/ProfileBehaviour/
   jifty/branches/schema-plugins/plugins/ProfileBehaviour/Makefile.PL
   jifty/branches/schema-plugins/plugins/ProfileBehaviour/doc/
   jifty/branches/schema-plugins/plugins/ProfileBehaviour/lib/
   jifty/branches/schema-plugins/plugins/ProfileBehaviour/lib/Jifty/
   jifty/branches/schema-plugins/plugins/ProfileBehaviour/lib/Jifty/Plugin/
   jifty/branches/schema-plugins/plugins/ProfileBehaviour/lib/Jifty/Plugin/ProfileBehaviour/
   jifty/branches/schema-plugins/plugins/ProfileBehaviour/lib/Jifty/Plugin/ProfileBehaviour.pm
   jifty/branches/schema-plugins/plugins/ProfileBehaviour/lib/Jifty/Plugin/ProfileBehaviour/Action/
   jifty/branches/schema-plugins/plugins/ProfileBehaviour/lib/Jifty/Plugin/ProfileBehaviour/Dispatcher.pm
   jifty/branches/schema-plugins/plugins/ProfileBehaviour/lib/Jifty/Plugin/ProfileBehaviour/Model/
   jifty/branches/schema-plugins/plugins/ProfileBehaviour/share/
   jifty/branches/schema-plugins/plugins/ProfileBehaviour/share/po/
   jifty/branches/schema-plugins/plugins/ProfileBehaviour/share/web/
   jifty/branches/schema-plugins/plugins/ProfileBehaviour/share/web/static/
   jifty/branches/schema-plugins/plugins/ProfileBehaviour/share/web/static/css/
   jifty/branches/schema-plugins/plugins/ProfileBehaviour/share/web/static/css/behaviour-profile.css
   jifty/branches/schema-plugins/plugins/ProfileBehaviour/share/web/static/js/
   jifty/branches/schema-plugins/plugins/ProfileBehaviour/share/web/static/js/behaviour.js
   jifty/branches/schema-plugins/plugins/ProfileBehaviour/share/web/templates/
   jifty/branches/schema-plugins/plugins/ProfileBehaviour/t/
   jifty/branches/schema-plugins/plugins/Users/
   jifty/branches/schema-plugins/plugins/Users-Identity-File/
   jifty/branches/schema-plugins/plugins/Users-Identity-File/Makefile.PL
   jifty/branches/schema-plugins/plugins/Users-Identity-File/doc/
   jifty/branches/schema-plugins/plugins/Users-Identity-File/lib/
   jifty/branches/schema-plugins/plugins/Users-Identity-File/lib/Jifty/
   jifty/branches/schema-plugins/plugins/Users-Identity-File/lib/Jifty/Plugin/
   jifty/branches/schema-plugins/plugins/Users-Identity-File/lib/Jifty/Plugin/Users/
   jifty/branches/schema-plugins/plugins/Users-Identity-File/lib/Jifty/Plugin/Users/Identity/
   jifty/branches/schema-plugins/plugins/Users-Identity-File/lib/Jifty/Plugin/Users/Identity/File/
   jifty/branches/schema-plugins/plugins/Users-Identity-File/lib/Jifty/Plugin/Users/Identity/File.pm
   jifty/branches/schema-plugins/plugins/Users-Identity-File/lib/Jifty/Plugin/Users/Identity/File/Action/
   jifty/branches/schema-plugins/plugins/Users-Identity-File/lib/Jifty/Plugin/Users/Identity/File/Action/Login.pm
   jifty/branches/schema-plugins/plugins/Users-Identity-File/lib/Jifty/Plugin/Users/Identity/File/Dispatcher.pm
   jifty/branches/schema-plugins/plugins/Users-Identity-File/lib/Jifty/Plugin/Users/Identity/File/Model/
   jifty/branches/schema-plugins/plugins/Users-Identity-File/share/
   jifty/branches/schema-plugins/plugins/Users-Identity-File/share/po/
   jifty/branches/schema-plugins/plugins/Users-Identity-File/share/web/
   jifty/branches/schema-plugins/plugins/Users-Identity-File/share/web/static/
   jifty/branches/schema-plugins/plugins/Users-Identity-File/share/web/templates/
   jifty/branches/schema-plugins/plugins/Users-Identity-File/share/web/templates/login
   jifty/branches/schema-plugins/plugins/Users-Identity-File/t/
   jifty/branches/schema-plugins/plugins/Users/Makefile.PL
   jifty/branches/schema-plugins/plugins/Users/doc/
   jifty/branches/schema-plugins/plugins/Users/lib/
   jifty/branches/schema-plugins/plugins/Users/lib/Jifty/
   jifty/branches/schema-plugins/plugins/Users/lib/Jifty/Plugin/
   jifty/branches/schema-plugins/plugins/Users/lib/Jifty/Plugin/Users/
   jifty/branches/schema-plugins/plugins/Users/lib/Jifty/Plugin/Users.pm
   jifty/branches/schema-plugins/plugins/Users/lib/Jifty/Plugin/Users/Action/
   jifty/branches/schema-plugins/plugins/Users/lib/Jifty/Plugin/Users/CurrentUser.pm
   jifty/branches/schema-plugins/plugins/Users/lib/Jifty/Plugin/Users/Dispatcher.pm
   jifty/branches/schema-plugins/plugins/Users/lib/Jifty/Plugin/Users/Model/
   jifty/branches/schema-plugins/plugins/Users/lib/Jifty/Plugin/Users/Model/User.pm
   jifty/branches/schema-plugins/plugins/Users/share/
   jifty/branches/schema-plugins/plugins/Users/share/po/
   jifty/branches/schema-plugins/plugins/Users/share/web/
   jifty/branches/schema-plugins/plugins/Users/share/web/static/
   jifty/branches/schema-plugins/plugins/Users/share/web/templates/
   jifty/branches/schema-plugins/plugins/Users/t/
   jifty/branches/schema-plugins/share/
   jifty/branches/schema-plugins/share/dtd/
   jifty/branches/schema-plugins/share/dtd/xhtml-lat1.ent
   jifty/branches/schema-plugins/share/dtd/xhtml-special.ent
   jifty/branches/schema-plugins/share/dtd/xhtml-symbol.ent
   jifty/branches/schema-plugins/share/dtd/xhtml1-strict.dtd
   jifty/branches/schema-plugins/share/po/
   jifty/branches/schema-plugins/share/po/en.po
   jifty/branches/schema-plugins/share/po/fr.po
   jifty/branches/schema-plugins/share/po/ja.po
   jifty/branches/schema-plugins/share/po/zh_cn.po
   jifty/branches/schema-plugins/share/po/zh_tw.po
   jifty/branches/schema-plugins/share/web/
   jifty/branches/schema-plugins/share/web/static/
   jifty/branches/schema-plugins/share/web/static/css/
   jifty/branches/schema-plugins/share/web/static/css/app-base.css
   jifty/branches/schema-plugins/share/web/static/css/app.css
   jifty/branches/schema-plugins/share/web/static/css/autocomplete.css
   jifty/branches/schema-plugins/share/web/static/css/autohandler
   jifty/branches/schema-plugins/share/web/static/css/base.css
   jifty/branches/schema-plugins/share/web/static/css/calendar.css
   jifty/branches/schema-plugins/share/web/static/css/combobox.css   (contents, props changed)
   jifty/branches/schema-plugins/share/web/static/css/context-menus.css
   jifty/branches/schema-plugins/share/web/static/css/forms.css
   jifty/branches/schema-plugins/share/web/static/css/halos.css
   jifty/branches/schema-plugins/share/web/static/css/keybindings.css
   jifty/branches/schema-plugins/share/web/static/css/main.css
   jifty/branches/schema-plugins/share/web/static/css/nav.css   (contents, props changed)
   jifty/branches/schema-plugins/share/web/static/css/notices.css
   jifty/branches/schema-plugins/share/web/static/css/yui/
   jifty/branches/schema-plugins/share/web/static/css/yui/calendar/
   jifty/branches/schema-plugins/share/web/static/css/yui/calendar/calendar.css
   jifty/branches/schema-plugins/share/web/static/css/yui/tabview/
   jifty/branches/schema-plugins/share/web/static/css/yui/tabview/border_tabs.css
   jifty/branches/schema-plugins/share/web/static/css/yui/tabview/tabs.css
   jifty/branches/schema-plugins/share/web/static/favicon.ico   (contents, props changed)
   jifty/branches/schema-plugins/share/web/static/images/
   jifty/branches/schema-plugins/share/web/static/images/css/
   jifty/branches/schema-plugins/share/web/static/images/css/bullet_arrow_down.png   (contents, props changed)
   jifty/branches/schema-plugins/share/web/static/images/css/bullet_arrow_up.png   (contents, props changed)
   jifty/branches/schema-plugins/share/web/static/images/css/fieldbg-autocomplete.gif   (contents, props changed)
   jifty/branches/schema-plugins/share/web/static/images/css/fieldbg.gif   (contents, props changed)
   jifty/branches/schema-plugins/share/web/static/images/iepngfix/
   jifty/branches/schema-plugins/share/web/static/images/iepngfix/blank.gif   (contents, props changed)
   jifty/branches/schema-plugins/share/web/static/images/pony.jpg   (contents, props changed)
   jifty/branches/schema-plugins/share/web/static/images/silk/
   jifty/branches/schema-plugins/share/web/static/images/silk/bullet_arrow_down.png   (contents, props changed)
   jifty/branches/schema-plugins/share/web/static/images/silk/bullet_arrow_up.png   (contents, props changed)
   jifty/branches/schema-plugins/share/web/static/images/silk/calendar.png   (contents, props changed)
   jifty/branches/schema-plugins/share/web/static/images/silk/cancel.png   (contents, props changed)
   jifty/branches/schema-plugins/share/web/static/images/silk/cancel_grey.png   (contents, props changed)
   jifty/branches/schema-plugins/share/web/static/images/silk/error.png   (contents, props changed)
   jifty/branches/schema-plugins/share/web/static/images/silk/information.png   (contents, props changed)
   jifty/branches/schema-plugins/share/web/static/images/silk/pencil.png   (contents, props changed)
   jifty/branches/schema-plugins/share/web/static/images/silk/pencil_add.png   (contents, props changed)
   jifty/branches/schema-plugins/share/web/static/images/yui/
   jifty/branches/schema-plugins/share/web/static/images/yui/us/
   jifty/branches/schema-plugins/share/web/static/images/yui/us/my/
   jifty/branches/schema-plugins/share/web/static/images/yui/us/my/bn/
   jifty/branches/schema-plugins/share/web/static/images/yui/us/my/bn/x_d.gif   (contents, props changed)
   jifty/branches/schema-plugins/share/web/static/images/yui/us/tr/
   jifty/branches/schema-plugins/share/web/static/images/yui/us/tr/callt.gif   (contents, props changed)
   jifty/branches/schema-plugins/share/web/static/images/yui/us/tr/calrt.gif   (contents, props changed)
   jifty/branches/schema-plugins/share/web/static/js/
   jifty/branches/schema-plugins/share/web/static/js/app.js
   jifty/branches/schema-plugins/share/web/static/js/app_behaviour.js
   jifty/branches/schema-plugins/share/web/static/js/behaviour.js
   jifty/branches/schema-plugins/share/web/static/js/bps_util.js   (contents, props changed)
   jifty/branches/schema-plugins/share/web/static/js/calendar.js
   jifty/branches/schema-plugins/share/web/static/js/combobox.js
   jifty/branches/schema-plugins/share/web/static/js/context_menu.js
   jifty/branches/schema-plugins/share/web/static/js/css_browser_selector.js   (contents, props changed)
   jifty/branches/schema-plugins/share/web/static/js/cssquery/
   jifty/branches/schema-plugins/share/web/static/js/cssquery/cssQuery-level2.js
   jifty/branches/schema-plugins/share/web/static/js/cssquery/cssQuery-level3.js
   jifty/branches/schema-plugins/share/web/static/js/cssquery/cssQuery-standard.js
   jifty/branches/schema-plugins/share/web/static/js/cssquery/cssQuery.js
   jifty/branches/schema-plugins/share/web/static/js/dom-drag.js
   jifty/branches/schema-plugins/share/web/static/js/formatDate.js   (contents, props changed)
   jifty/branches/schema-plugins/share/web/static/js/halo.js
   jifty/branches/schema-plugins/share/web/static/js/iepngfix.htc
   jifty/branches/schema-plugins/share/web/static/js/jifty.js
   jifty/branches/schema-plugins/share/web/static/js/jifty_smoothscroll.js
   jifty/branches/schema-plugins/share/web/static/js/jifty_subs.js
   jifty/branches/schema-plugins/share/web/static/js/jifty_utils.js
   jifty/branches/schema-plugins/share/web/static/js/jsTrace.js
   jifty/branches/schema-plugins/share/web/static/js/jsan/
   jifty/branches/schema-plugins/share/web/static/js/jsan/DOM/
   jifty/branches/schema-plugins/share/web/static/js/jsan/DOM/Events.js
   jifty/branches/schema-plugins/share/web/static/js/jsan/JSAN.js
   jifty/branches/schema-plugins/share/web/static/js/jsan/Push.js
   jifty/branches/schema-plugins/share/web/static/js/jsan/Upgrade/
   jifty/branches/schema-plugins/share/web/static/js/jsan/Upgrade.js
   jifty/branches/schema-plugins/share/web/static/js/jsan/Upgrade/Array/
   jifty/branches/schema-plugins/share/web/static/js/jsan/Upgrade/Array/push.js
   jifty/branches/schema-plugins/share/web/static/js/jsan/Upgrade/Function/
   jifty/branches/schema-plugins/share/web/static/js/jsan/Upgrade/Function/apply.js
   jifty/branches/schema-plugins/share/web/static/js/json.js
   jifty/branches/schema-plugins/share/web/static/js/key_bindings.js   (contents, props changed)
   jifty/branches/schema-plugins/share/web/static/js/prototype.js
   jifty/branches/schema-plugins/share/web/static/js/rico.js
   jifty/branches/schema-plugins/share/web/static/js/scriptaculous/
   jifty/branches/schema-plugins/share/web/static/js/scriptaculous/builder.js   (contents, props changed)
   jifty/branches/schema-plugins/share/web/static/js/scriptaculous/controls.js   (contents, props changed)
   jifty/branches/schema-plugins/share/web/static/js/scriptaculous/dragdrop.js   (contents, props changed)
   jifty/branches/schema-plugins/share/web/static/js/scriptaculous/effects.js   (contents, props changed)
   jifty/branches/schema-plugins/share/web/static/js/scriptaculous/scriptaculous.js   (contents, props changed)
   jifty/branches/schema-plugins/share/web/static/js/scriptaculous/slider.js   (contents, props changed)
   jifty/branches/schema-plugins/share/web/static/js/scriptaculous/unittest.js   (contents, props changed)
   jifty/branches/schema-plugins/share/web/static/js/setup_jsan.js
   jifty/branches/schema-plugins/share/web/static/js/yui/
   jifty/branches/schema-plugins/share/web/static/js/yui/calendar.js
   jifty/branches/schema-plugins/share/web/static/js/yui/container.js
   jifty/branches/schema-plugins/share/web/static/js/yui/dom.js
   jifty/branches/schema-plugins/share/web/static/js/yui/event.js
   jifty/branches/schema-plugins/share/web/static/js/yui/tabview.js
   jifty/branches/schema-plugins/share/web/static/js/yui/yahoo.js
   jifty/branches/schema-plugins/share/web/templates/
   jifty/branches/schema-plugins/share/web/templates/=/
   jifty/branches/schema-plugins/share/web/templates/=/subs
   jifty/branches/schema-plugins/share/web/templates/__jifty/
   jifty/branches/schema-plugins/share/web/templates/__jifty/admin/
   jifty/branches/schema-plugins/share/web/templates/__jifty/admin/_elements/
   jifty/branches/schema-plugins/share/web/templates/__jifty/admin/_elements/nav   (contents, props changed)
   jifty/branches/schema-plugins/share/web/templates/__jifty/admin/action/
   jifty/branches/schema-plugins/share/web/templates/__jifty/admin/action/dhandler
   jifty/branches/schema-plugins/share/web/templates/__jifty/admin/autohandler
   jifty/branches/schema-plugins/share/web/templates/__jifty/admin/fragments/
   jifty/branches/schema-plugins/share/web/templates/__jifty/admin/fragments/list/
   jifty/branches/schema-plugins/share/web/templates/__jifty/admin/fragments/list/header
   jifty/branches/schema-plugins/share/web/templates/__jifty/admin/fragments/list/list
   jifty/branches/schema-plugins/share/web/templates/__jifty/admin/fragments/list/new_item
   jifty/branches/schema-plugins/share/web/templates/__jifty/admin/fragments/list/search
   jifty/branches/schema-plugins/share/web/templates/__jifty/admin/fragments/list/update
   jifty/branches/schema-plugins/share/web/templates/__jifty/admin/fragments/list/view
   jifty/branches/schema-plugins/share/web/templates/__jifty/admin/index.html
   jifty/branches/schema-plugins/share/web/templates/__jifty/admin/model/
   jifty/branches/schema-plugins/share/web/templates/__jifty/admin/model/dhandler
   jifty/branches/schema-plugins/share/web/templates/__jifty/autocomplete.xml
   jifty/branches/schema-plugins/share/web/templates/__jifty/css/
   jifty/branches/schema-plugins/share/web/templates/__jifty/css/dhandler
   jifty/branches/schema-plugins/share/web/templates/__jifty/empty
   jifty/branches/schema-plugins/share/web/templates/__jifty/error/
   jifty/branches/schema-plugins/share/web/templates/__jifty/error/_elements/
   jifty/branches/schema-plugins/share/web/templates/__jifty/error/_elements/error_text
   jifty/branches/schema-plugins/share/web/templates/__jifty/error/_elements/wrapper
   jifty/branches/schema-plugins/share/web/templates/__jifty/error/autohandler
   jifty/branches/schema-plugins/share/web/templates/__jifty/error/dhandler
   jifty/branches/schema-plugins/share/web/templates/__jifty/error/error.css
   jifty/branches/schema-plugins/share/web/templates/__jifty/error/mason_internal_error
   jifty/branches/schema-plugins/share/web/templates/__jifty/halo
   jifty/branches/schema-plugins/share/web/templates/__jifty/js/
   jifty/branches/schema-plugins/share/web/templates/__jifty/js/dhandler
   jifty/branches/schema-plugins/share/web/templates/__jifty/online_docs/
   jifty/branches/schema-plugins/share/web/templates/__jifty/online_docs/autohandler   (contents, props changed)
   jifty/branches/schema-plugins/share/web/templates/__jifty/online_docs/content.html
   jifty/branches/schema-plugins/share/web/templates/__jifty/online_docs/index.html   (contents, props changed)
   jifty/branches/schema-plugins/share/web/templates/__jifty/online_docs/toc.html
   jifty/branches/schema-plugins/share/web/templates/__jifty/validator.xml
   jifty/branches/schema-plugins/share/web/templates/__jifty/webservices/
   jifty/branches/schema-plugins/share/web/templates/__jifty/webservices/json
   jifty/branches/schema-plugins/share/web/templates/__jifty/webservices/xml
   jifty/branches/schema-plugins/share/web/templates/__jifty/webservices/yaml
   jifty/branches/schema-plugins/share/web/templates/_elements/
   jifty/branches/schema-plugins/share/web/templates/_elements/header
   jifty/branches/schema-plugins/share/web/templates/_elements/keybindings
   jifty/branches/schema-plugins/share/web/templates/_elements/menu
   jifty/branches/schema-plugins/share/web/templates/_elements/nav
   jifty/branches/schema-plugins/share/web/templates/_elements/page_nav
   jifty/branches/schema-plugins/share/web/templates/_elements/sidebar
   jifty/branches/schema-plugins/share/web/templates/_elements/wrapper
   jifty/branches/schema-plugins/share/web/templates/autohandler
   jifty/branches/schema-plugins/share/web/templates/dhandler
   jifty/branches/schema-plugins/share/web/templates/helpers/
   jifty/branches/schema-plugins/share/web/templates/helpers/calendar.html
   jifty/branches/schema-plugins/share/web/templates/index.html
   jifty/branches/schema-plugins/t/
   jifty/branches/schema-plugins/t/00-load.t
   jifty/branches/schema-plugins/t/01-dependencies.t
   jifty/branches/schema-plugins/t/01-test-web.t
   jifty/branches/schema-plugins/t/01-version_checks.t
   jifty/branches/schema-plugins/t/02-connect.t
   jifty/branches/schema-plugins/t/03-form-protocol.t
   jifty/branches/schema-plugins/t/03-is_passing-no_plan.t   (contents, props changed)
   jifty/branches/schema-plugins/t/03-is_passing.t   (contents, props changed)
   jifty/branches/schema-plugins/t/03-test-mailbox.t   (contents, props changed)
   jifty/branches/schema-plugins/t/04-test_file.t   (contents, props changed)
   jifty/branches/schema-plugins/t/05-dispatcher.t
   jifty/branches/schema-plugins/t/06-forms.t
   jifty/branches/schema-plugins/t/07-limit-actions.t
   jifty/branches/schema-plugins/t/08-client.t
   jifty/branches/schema-plugins/t/09-url.t   (contents, props changed)
   jifty/branches/schema-plugins/t/10-i18n.t
   jifty/branches/schema-plugins/t/11-config-files.t
   jifty/branches/schema-plugins/t/12-param-schema.t   (contents, props changed)
   jifty/branches/schema-plugins/t/99-pod-coverage.t
   jifty/branches/schema-plugins/t/99-pod.t
   jifty/branches/schema-plugins/t/Continuations/   (props changed)
   jifty/branches/schema-plugins/t/Continuations/bin/
   jifty/branches/schema-plugins/t/Continuations/bin/jifty   (contents, props changed)
   jifty/branches/schema-plugins/t/Continuations/lib/
   jifty/branches/schema-plugins/t/Continuations/lib/Continuations/
   jifty/branches/schema-plugins/t/Continuations/lib/Continuations/Action/
   jifty/branches/schema-plugins/t/Continuations/lib/Continuations/Action/CrossBridge.pm
   jifty/branches/schema-plugins/t/Continuations/lib/Continuations/Action/GetGrail.pm
   jifty/branches/schema-plugins/t/Continuations/lib/Continuations/Dispatcher.pm
   jifty/branches/schema-plugins/t/Continuations/share/
   jifty/branches/schema-plugins/t/Continuations/share/web/
   jifty/branches/schema-plugins/t/Continuations/share/web/templates/
   jifty/branches/schema-plugins/t/Continuations/share/web/templates/autohandler
   jifty/branches/schema-plugins/t/Continuations/share/web/templates/black-knight-color.html
   jifty/branches/schema-plugins/t/Continuations/share/web/templates/black-knight-name.html
   jifty/branches/schema-plugins/t/Continuations/share/web/templates/black-knight-quest.html
   jifty/branches/schema-plugins/t/Continuations/share/web/templates/black-knight.html
   jifty/branches/schema-plugins/t/Continuations/share/web/templates/help-help.html
   jifty/branches/schema-plugins/t/Continuations/share/web/templates/index-help.html
   jifty/branches/schema-plugins/t/Continuations/share/web/templates/index.html
   jifty/branches/schema-plugins/t/Continuations/t/
   jifty/branches/schema-plugins/t/Continuations/t/00-prototype.t
   jifty/branches/schema-plugins/t/Continuations/t/01-raw-api.t
   jifty/branches/schema-plugins/t/Continuations/t/02-api.t
   jifty/branches/schema-plugins/t/Continuations/t/03-gc.t
   jifty/branches/schema-plugins/t/Continuations/t/04-before-blocks.t
   jifty/branches/schema-plugins/t/DateTime.t
   jifty/branches/schema-plugins/t/Jifty.pm
   jifty/branches/schema-plugins/t/Mapper/   (props changed)
   jifty/branches/schema-plugins/t/Mapper/bin/
   jifty/branches/schema-plugins/t/Mapper/bin/jifty   (contents, props changed)
   jifty/branches/schema-plugins/t/Mapper/lib/
   jifty/branches/schema-plugins/t/Mapper/lib/Mapper/
   jifty/branches/schema-plugins/t/Mapper/lib/Mapper/Action/
   jifty/branches/schema-plugins/t/Mapper/lib/Mapper/Action/CrossBridge.pm
   jifty/branches/schema-plugins/t/Mapper/lib/Mapper/Action/GetGrail.pm
   jifty/branches/schema-plugins/t/Mapper/share/
   jifty/branches/schema-plugins/t/Mapper/share/web/
   jifty/branches/schema-plugins/t/Mapper/share/web/templates/
   jifty/branches/schema-plugins/t/Mapper/share/web/templates/autohandler
   jifty/branches/schema-plugins/t/Mapper/share/web/templates/index.html
   jifty/branches/schema-plugins/t/Mapper/t/
   jifty/branches/schema-plugins/t/Mapper/t/00-prototype.t
   jifty/branches/schema-plugins/t/Mapper/t/01-raw-api.t
   jifty/branches/schema-plugins/t/Mapper/t/02-api.t
   jifty/branches/schema-plugins/t/TestApp/   (props changed)
   jifty/branches/schema-plugins/t/TestApp-Plugin-REST/
   jifty/branches/schema-plugins/t/TestApp-Plugin-REST/bin/
   jifty/branches/schema-plugins/t/TestApp-Plugin-REST/bin/jifty   (contents, props changed)
   jifty/branches/schema-plugins/t/TestApp-Plugin-REST/etc/
   jifty/branches/schema-plugins/t/TestApp-Plugin-REST/etc/config.yml
   jifty/branches/schema-plugins/t/TestApp-Plugin-REST/lib/
   jifty/branches/schema-plugins/t/TestApp-Plugin-REST/lib/TestApp/
   jifty/branches/schema-plugins/t/TestApp-Plugin-REST/lib/TestApp/Plugin/
   jifty/branches/schema-plugins/t/TestApp-Plugin-REST/lib/TestApp/Plugin/REST/
   jifty/branches/schema-plugins/t/TestApp-Plugin-REST/lib/TestApp/Plugin/REST/Action/
   jifty/branches/schema-plugins/t/TestApp-Plugin-REST/lib/TestApp/Plugin/REST/Action/DoSomething.pm
   jifty/branches/schema-plugins/t/TestApp-Plugin-REST/lib/TestApp/Plugin/REST/Dispatcher.pm
   jifty/branches/schema-plugins/t/TestApp-Plugin-REST/lib/TestApp/Plugin/REST/Model/
   jifty/branches/schema-plugins/t/TestApp-Plugin-REST/lib/TestApp/Plugin/REST/Model/Group.pm
   jifty/branches/schema-plugins/t/TestApp-Plugin-REST/lib/TestApp/Plugin/REST/Model/User.pm
   jifty/branches/schema-plugins/t/TestApp-Plugin-REST/share/
   jifty/branches/schema-plugins/t/TestApp-Plugin-REST/t/
   jifty/branches/schema-plugins/t/TestApp-Plugin-REST/t/00-model-User.t   (contents, props changed)
   jifty/branches/schema-plugins/t/TestApp-Plugin-REST/t/00-prototype.t   (contents, props changed)
   jifty/branches/schema-plugins/t/TestApp-Plugin-REST/t/01-config.t   (contents, props changed)
   jifty/branches/schema-plugins/t/TestApp-Plugin-REST/t/02-basic-use.t   (contents, props changed)
   jifty/branches/schema-plugins/t/TestApp/bin/
   jifty/branches/schema-plugins/t/TestApp/bin/jifty   (contents, props changed)
   jifty/branches/schema-plugins/t/TestApp/lib/
   jifty/branches/schema-plugins/t/TestApp/lib/TestApp/
   jifty/branches/schema-plugins/t/TestApp/lib/TestApp/Action/
   jifty/branches/schema-plugins/t/TestApp/lib/TestApp/Action/DoSomething.pm
   jifty/branches/schema-plugins/t/TestApp/lib/TestApp/Action/DoSomethingElse.pm
   jifty/branches/schema-plugins/t/TestApp/lib/TestApp/CurrentUser.pm
   jifty/branches/schema-plugins/t/TestApp/lib/TestApp/Dispatcher.pm
   jifty/branches/schema-plugins/t/TestApp/lib/TestApp/Model/
   jifty/branches/schema-plugins/t/TestApp/lib/TestApp/Model/User.pm
   jifty/branches/schema-plugins/t/TestApp/share/
   jifty/branches/schema-plugins/t/TestApp/share/web/
   jifty/branches/schema-plugins/t/TestApp/share/web/static/
   jifty/branches/schema-plugins/t/TestApp/share/web/static/images/
   jifty/branches/schema-plugins/t/TestApp/share/web/static/images/pony.jpg   (contents, props changed)
   jifty/branches/schema-plugins/t/TestApp/share/web/templates/
   jifty/branches/schema-plugins/t/TestApp/share/web/templates/concrete.html
   jifty/branches/schema-plugins/t/TestApp/share/web/templates/currentuser
   jifty/branches/schema-plugins/t/TestApp/share/web/templates/dispatch/
   jifty/branches/schema-plugins/t/TestApp/share/web/templates/dispatch/basic
   jifty/branches/schema-plugins/t/TestApp/share/web/templates/dispatch/basic-show
   jifty/branches/schema-plugins/t/TestApp/share/web/templates/dosomethingelse
   jifty/branches/schema-plugins/t/TestApp/share/web/templates/editform
   jifty/branches/schema-plugins/t/TestApp/share/web/templates/index.html
   jifty/branches/schema-plugins/t/TestApp/share/web/templates/manual_redirect
   jifty/branches/schema-plugins/t/TestApp/share/web/templates/regions/
   jifty/branches/schema-plugins/t/TestApp/share/web/templates/regions/list
   jifty/branches/schema-plugins/t/TestApp/share/web/templates/regions/long
   jifty/branches/schema-plugins/t/TestApp/share/web/templates/regions/short
   jifty/branches/schema-plugins/t/TestApp/share/web/templates/somedir/
   jifty/branches/schema-plugins/t/TestApp/share/web/templates/somedir/dhandler
   jifty/branches/schema-plugins/t/TestApp/t/
   jifty/branches/schema-plugins/t/TestApp/t/00-model-User.t
   jifty/branches/schema-plugins/t/TestApp/t/00-prototype.t
   jifty/branches/schema-plugins/t/TestApp/t/01-config.t
   jifty/branches/schema-plugins/t/TestApp/t/02-dispatch-show-rule-in-wrong-ruleset.t
   jifty/branches/schema-plugins/t/TestApp/t/02-dispatch.t
   jifty/branches/schema-plugins/t/TestApp/t/03-static.t
   jifty/branches/schema-plugins/t/TestApp/t/04-sessions.t
   jifty/branches/schema-plugins/t/TestApp/t/05-actions-before-redirect.pm
   jifty/branches/schema-plugins/t/TestApp/t/05-editactions-Cachable.t
   jifty/branches/schema-plugins/t/TestApp/t/05-editactions-Record.t
   jifty/branches/schema-plugins/t/TestApp/t/06-validation.t
   jifty/branches/schema-plugins/t/TestApp/t/07-sandboxing.t
   jifty/branches/schema-plugins/t/TestApp/t/08-notifications.t
   jifty/branches/schema-plugins/t/TestApp/t/09-redirect.t   (contents, props changed)
   jifty/branches/schema-plugins/t/TestApp/t/10-compress.t   (contents, props changed)
   jifty/branches/schema-plugins/t/TestApp/t/11-current_user.t   (contents, props changed)
   jifty/branches/schema-plugins/t/TestApp/t/12-search.t   (contents, props changed)
   jifty/branches/schema-plugins/t/TestApp/t/13-page-regions.t
   jifty/branches/schema-plugins/t/TestApp/t/config-Cachable
   jifty/branches/schema-plugins/t/TestApp/t/config-Record
   jifty/branches/schema-plugins/t/TestApp/t/i18n-standalone.t
   jifty/branches/schema-plugins/t/TestApp/t/instance_id.t
   jifty/branches/schema-plugins/t/TestApp/t/regex_meta_in_path_info.t
   jifty/branches/schema-plugins/t/lib/
   jifty/branches/schema-plugins/t/lib/Jifty/
   jifty/branches/schema-plugins/t/lib/Jifty/SubTest.pm   (contents, props changed)
Modified:
   jifty/   (props changed)

Log:
 r2740 at riddle:  andrew | 2007-01-29 12:06:20 -0600
 Creating a new branch to tinker with model/action schema editing plugins.


Added: jifty/branches/schema-plugins/AUTHORS
==============================================================================
--- (empty file)
+++ jifty/branches/schema-plugins/AUTHORS	Mon Jan 29 21:05:02 2007
@@ -0,0 +1,24 @@
+In order of first commit:
+Jesse Vincent <jesse at bestpractical.com>
+David Glasser <glasser at bestpractical.com>
+Alex Vandiver <alexmv at bestpractical.com>
+Thomas Sibley <trs at bestpractical.com>
+Kevin Riggle <kevinr at bestpractical.com>
+Audrey Tang <audreyt at audreyt.org>
+Eric Wilhelm <ewilhelm at cpan.org>
+Nelson Elhage <nelhage at mit.edu>
+Sean E Millichamp <sean at bruenor.org>
+Kenichi Ishigaki <ishigaki at tcool.org>
+Chia-Liang Kao <clkao at clkao.org>
+Dobrica Pavlinusic <dpavlin at rot13.org>
+Bart Bunting <bart at bunting.net.au>
+Norman Nunley, Jr. <nnunley at cpan.org>
+Mark Fowler <mark at twoshortplanks.com>
+Liang-Bin Hsueh <hlb at bestpractical.com>
+Wolfgang Kinkeldei <wolfgang at kinkeldei.de>
+Paul Fenwick <pjf at perltraining.com.au>
+Edmund von der Burg <evdb at ecclestoad.co.uk>
+Yves Agostini <agostini at univ-metz.fr>
+Agent Zhang <agentzh at gmail.com>
+Pawel Murias <pmurias at woobling.org>
+Andrew Sterling Hanenkamp <sterling at hanenkamp.com>

Added: jifty/branches/schema-plugins/Changelog
==============================================================================
--- (empty file)
+++ jifty/branches/schema-plugins/Changelog	Mon Jan 29 21:05:02 2007
@@ -0,0 +1,988 @@
+Jifty 0.70117
+   Dependencies: 
+     * Bumped the minimum required version of Jifty::DBI to 0.30
+
+Jifty 0.70116
+
+   New authors
+     * Add yves in authors, for localisation, debian packaging -yves
+     * Added PJF to AUTHORS file. -pjf
+     * Added evdb as a new author -evdb
+     * agentz
+     * pmurias
+
+   PubSub (audreyt, clkao, jesse)
+     * Audrey, Jesse and CL hacked out a PubSub message bus and a
+       preliminary Comet implementation.
+     * Doc for how subscription stuff works. a bit of refactoring toward
+       a second transport
+     * Added sample apps and design docs from the PubSub/Comet hackathon
+     * upgrade schema to work on mysql -jesse
+
+   Database
+     * Initial support for prefetched collections. -jesse
+     * Added support for SQL::ReservedWords to the schema tool, to stop
+       me from building applications for Postgres on SQLite and hurting
+       myself later -jesse
+     * Add a CheckSchema option to the config file to govern the SQL
+       Schema keyword checking -jesse
+     * Classify databases failing an SQL::ReservedWords check for nicer
+       output -gaal
+     * Better debugging information when running actions -jesse
+
+   Documentation
+     * Updated tutorial to remove mention of the deprecated download
+       area. -pjf
+     * Provided extra tips on how to install Jifty using Perl's standard
+       CPAN module on both Unix-like and Win32 systems. -pjf
+     * Documented PageRegions usage -wolfgang
+     * Show an example of a canonicalizer (lifted from the jifty
+       presentations). -falcone
+     * Document the ability to frob other pieces of the action from a
+       canonicalizer -falcone
+     * Jifty::Manual::UsingCSSandJS - Fix the misspelled "app.css" to the
+       correct "app.js"; minor reformatting. -audreyt
+     * Jifty::Manual::Models - It mentions <> as the SQL inequality
+       operator, but all internal code uses != instead; change the doc to
+       match reality. -audreyt
+     * Jifty::Manual::Cookbook - Trivial typo. -audreyt
+     * Jifty::Manual::AccessControl, Jifty::Manual::RequestHandling -
+       Change C< objEmeth > to the more readable C<< obj->meth >> POD
+       syntax. -audreyt
+     * expanded AccessControl.pod to reflect changes in Login plugin
+       -wolfgang
+     * added a pod describing Jifty's request handling process -wolfgang
+     * added a german translation for Tutorial.pod -wolfgang
+     * Minor fixes to pod -evdb
+     * added explanations about Login Plugin to AccessControl.pod
+       -wolfgang
+     * updated Models.pod to reflect recent changes -wolfgang
+     * added a section on 'limit' to 'Models.pod' -wolfgang
+     * Supply documentation for all of the methods which had been missing
+       it -jesse
+     * Jifty::Param::Schema merge algorithm rescued from the obscurity of
+       commit logs. -jesse
+     * Corrected Jifty::Record::current_user_can: The right is 'update',
+       not 'edit' -jesse
+     * Jifty::Record::current_user_can: "admin" should have been "delete"
+       -jesse
+     * Added the time and date filters to the cookbook. -nelhage
+     * Improved docs for Jifty::RightsFrom -jesse
+     * Improved docs for Jifty::Record (Access control related
+       functionality) -jesse
+     * Added a documentation fileon CSS and JS -wolfgang
+     * Jifty::Param::Schema - Trivial doc fix to s/Wifty/MyApp/. -audreyt
+     * Jifty::Action - add documentation for the automatic moniker
+       generation algorithm. -audreyt
+     * Minor documentation updates -gaal
+     * Jifty::Script::FastCGI doc - it's share/web/ not web/ nowadays.
+       -audreyt
+     * Two simple POD typos, one spotted by Gaal Yahas. -audreyt
+     * Minor spelling corrections. -jpeacock
+     * Fixed a cookbook typo, and add some sentences describing an issue
+       when defer{} failed to dwim. -gugod
+     * A cookbook recipe to do ajax canonicalization. -gugod
+     * Jifty::Action POD: Copy-n-paste the synopsis from
+       Jifty::Param::Schema and correctly L<> there. -audreyt
+     * Tell people where the docs for Jifty::Action::button really live -jesse
+     * [Manual/Actions.pod] added more explanation for the "return values" of Actions
+       made the $id args optional in the sample code.
+       added internal links to L</monikers>.
+       a few additions to the explanation
+       a few cleanups in the sample code -agentz
+     * Manual/Cookbook.pod: typo fixes, code cleanup -agentz
+     * document Jifty::Web::Form::Field::preamble -agentz
+     * Jifty::Manual::(Upgrading|RequestHandling|AccessControl|UsingCSSandJS|Actions|Continuations) 
+       typo and wording fixes -agentz
+     * Jifty::Manual::PageRegions examples and cleanup -agentz
+     * Jifty::Manual::Models - mentioned the build_select_query method,
+       paging, and Jifty::Manual::Upgrading. -agentz
+     * Added a note about the fact that mason needs to be flush left to the
+       tutorial -jesse
+     * add full MyWeblog example -jesse
+     * limit handling corrected in Jifty::Manual::Models -wolfgang
+     * Cookbook typo fixed. thanks to tokuhirom -jesse
+     * Jifty::Manual::Cookbook - applied the "edit" link patch from Peter Wise. -agentz
+     * plugin and declarative test design docs -nelhage
+     * ldap autocomplete example -yves
+     * Tutorial_de retitled to not conflict with the english one. -jesse
+
+   Plugins
+     * First release for plugins AuthLDAPOnly and AuthLDAPLogin, all
+       comments are welcome -yves
+     * Login plugin : Add missing Notification::ConfirmLostPassword,
+       dispatcher for passwordreminder, let to reset lost password -yves
+     * Added an action to let the user change his/her password in the
+       login plugin -yves
+     * AuthLDAP plugins: minor doc and debian rules fix -yves
+     * You can now run actions and get back arbitrary data formats from
+       the REST dispatcher -nelhage
+     * REST dispatcher cleanups. -jesse
+     * First cut at XML webservices in the REST plugin -jesse
+     * The first bit of major refactoring of the REST plugin. -jesse
+     * we loves our ACLs, we do. The REST plugin was violating too much
+       encapsuplation -jesse
+     * Added Module::Install files for plugins EditInPlace and Login;
+       some of them were in the MANIFEST but not the repository, so we
+       were getting false warnings of missing files when running 'make
+       distclean'. -jpeacock
+     * Add license to Login plugin's Makefile.PL. NOTE: remember to
+       increment the plugin's $VERSION strings before releasing to CPAN
+       (else updates won't get installed). -jpeacock
+     * test and debian updates for the LDAP plugin -yves
+     * Usable AuthzLDAP Plugin, see man Jifty::Plugin::AuthzLDAP
+       while thinking on new more generic Jifty::Plugin::Authz::XYZ , 
+       Jifty::Plugin::Authentication:XYZ -yves
+     * Login: Don't delete arguments that you don't know about /a priori/.  
+       Don't display fields that shouldn't be displayed 
+       (using the Unrendered attribute). -jpeacock
+     * Duplicate code removed from the plugin classloader -jesse
+     * Better handling of autocreated modules from plugins.
+       Print debug statements when autogenerating packages. -jpeacock
+     * reworking of Login plugin -jpeacock
+     * Some CAS authentification plugins -yves
+
+   Internals
+     * Jifty.pm: Load I18N after plugins, but before the main
+       classloader, so the main classes has access to _(). - audreyt
+     * Removed support for Devel::Gladiator. It was very, very beta and
+       caused server processes to end up as zombies -jesse
+     * qw'' is just weird. Change all instances to qw(). -schwern
+     * Jifty::Action::Record 'use'd DateManip but never uses it. -schwern
+     * It also used UNIVERSAL::require but did all of its requires via
+       Jifty::Util. -schwern
+     * Yet another fix to the URI-from-env feature, fixes a failing test
+       (reported by alexmv++). -gaal
+     * Guessing request schemes from the environment is fragile, so make
+       the fallback on BaseURL more reliable. -gaal
+     * when inferring a scheme for the application, look at REQUEST_URI
+       instead of assuming http://. Fixes tangent() on non-http:// apps.
+       -gaal
+     * Use Jifty->app_class whenever possible -alexmv
+     * Code cleanups in Jifty/Subs.pm -alexmv
+     * Fix for when Jifty->web->url is called with query parameters
+       -alexmv
+     * Added a Module::Pluggable subclass to get our own (somewhat
+       improved) require behaviour -jesse
+     * We were not properly removing blank values on record create -jesse
+     * Better handling of current_user when used as a class method -jesse
+     * use ApplicationClass, not Application Name in the login plugin
+       -clkao
+     * Add _is_readable in Jifty::Record, which means the record should
+       bypass current_user_can in check_read_rights. -clkao
+     * Add results_are_readable argument to collection to mark records
+       with _is_readable. -clkao
+     * Minor refactoring to enable non-cookie based session storage
+       -jesse
+     * Use Jifty->app_class to construct app-space class names. -clkao
+     * Jifty::JSON - Turn on $ImplicitUnicode so unicode strings
+       can be reliably serialized into .js and back.
+       (This is crucial for e.g. JavaScript confirm hooks.) -audreyt
+     * avoid warnings in LetMe -jesse
+     * DateTime: DateManip can get confused if someone else calls Date_Init 
+       earlier in the process.  Tell it "no, really, GMT please" -falcone
+     * DateTime: we're always setting the timezone to the user's timezone, even if
+       new is explicitly called with a timezone.  This breaks DateTime->from_epoch
+       which wants data back in UTC -falcone
+     * provide json webservices -audreyt && pmurias
+     * Jifty::ClassLoader - Defining MyApp::Action::Record::* now works. -audreyt
+     * Jifty.pm: Before we call Data::UUID->new, be sure to load it. -audreyt
+     * Jifty::Param::Schema allows "hints are 'type stuff'" but our Model syntax
+       uses 'are' to build an arrayref, so "hints are 'type stuff'" in a model would
+       result in displaying ARRAY(0x123456).   -falcone
+     * implement if-modified-since for static view handler. -clkao
+     * Module::Pluggable does't include empty intermediate classes now -alexmv
+
+   Web UI
+     * Links and Form titles needed to be better escaped -jesse
+     * Add delete option in admin view (for Jamalle - private joke) -yves
+     * Jifty::Param - It's no longer a Jifty::Web::Form::Field subclass.
+       -audreyt
+     * Add the ability to send "notes" to users from your canonicalizer.
+       This is separate from the warning and error spans used by the
+       validator -falcone
+     * validator.xml - allow us to update action data just by changing
+       it. Without this you had to set ajax_canonicalizes on a field in
+       order to change it and have it propagated back. --falcone
+     * Some refactoring of form field rendering, and adding a focus =>
+       argument to form fields to focus them on page load. -nelhage
+     * Switch our implementation of autofocus to use behavior, rather
+       than a custom onload event -jesse
+     * Fix calendar div & IE select box problem -ishigaki
+     * Do a slightly more generic dereferencing on the user object's
+       friendly name in the sidebar -jesse
+     * Fixing autocomplete so we render the autocomplete div *before
+     * the javascript, so the JS can hook it. -nelhage
+     * Remove useless check in buttonToLink to get a javascript
+       performance boost. -hlb
+     * Make render_messages sort on result moniker as well. -audreyt
+     * Jifty::Response: Ensure consistent ordering from monikers.
+       -audreyt
+     * Hacked the yui calendar component to allow selection of out-of-month
+       dates -jesse
+     * Even more I18N+L10N, this time for admin crud pages and calendar.html -audreyt
+     * adjusted the output format of render_preamble by removing a redundant space. -agentz
+     * The "length" attribute Web::Form::Field now also means HTML "maxlength"
+       in addition to "size". -audreyt
+     * calendar.js - Fire off canonicalization/validation methods upon clicking a
+       date. -audreyt
+     * Update YUI to 0.12 and port local changes -trs
+     * Administration manage model : 
+       add sortable capabilities in header table
+       bug fix in delete item
+       begining of modularity
+       other cosmetic changes
+       silk icons, wai tags thanks to Jamalle -yves
+     * Jifty::Web::Form::Field and ::Select - Label display was rendered using
+       the latin1-biased escaping in HTML::Entities; switch to the proper UTF-8
+       escaping in Jifty->web->escape. -audreyt
+     * This helps passing xhtml validation.
+       <input> cannot be direclty under <form>, there should be a
+       block-level element in-between. -gugod
+     * made wait-message look consistent in both firefox and IE -agentz
+     * admin/model/dhandler: localization hooks added, page title added -agentz
+     * add yui/tabview and its assets -hlb
+     * Indicate mandatory fields visually -trs
+     * Only emit mandatory field warnings with Ajax when the field starts with
+       data. -trs
+     * Close <li>s we open in the admin interface -alexmv
+     * remove extra </div>s -gugod
+     * upgrade yui library & add yui/container.js -hlb
+     * Fix broken Jifty.Utils.isMSIE -trs
+     * Fix buttonToLink to deal with normal, non-ajaxy buttons that we want to turn
+       into links -trs
+     * Use Jifty::JSON::objToJson to properly escape JS values (in particular
+       single quotes in button labels were causing problems) -trs
+     * Add a key_binding_label attribute so that key binding labels can be set
+       independently of the normal label -trs
+
+   Jifty Actions
+     * Jifty::Action: Generate stable auto-monikers for actions based on
+       the caller stack. -audreyt
+     * Negative searching for Search actions -jesse
+     * Added an option to search the contents of any text field to jifty
+       search actions -nelhage
+     * Jifty::Action::Record: Allow the same for user-generated param vs
+       CRUD actions. -audreyt
+     * Jifty::Action - Autoincrement the per-request stash counter for
+       the case of looped action creation. -audreyt
+     * Fixed 'mandatory' validation misbehavior -- 'mandatory' now
+       handled correctly -wolftang
+     * Jifty::Param::Schema: Allow partial override of superclass's
+       PARAMS by simply declaring a sub "param" and fill them with the
+       fields you'd override. -audreyt
+     * Jifty::Web / Jifty::Action: Stickiness now works on autogenerated
+       monikers. -audreyt
+     * Modified Jifty::Action::Record::Update so that empty strings for integer and
+       boolean columns will be interpreted as NULLs. This may break apps that
+       assume that an empty value string will be a no-op. -jesse
+     * Jifty::Action::Record::Search - Consider "float" and "double" fields
+       as numeric for comparison.  Also consider "char" as textual. -audreyt
+     * Allow a canonicalization note to be set, even if you don't change the 
+       value of the action parameter - falcone
+     * L10N for Action::Record::Search -audreyt
+     * Jifty::Manual::Actions include example with available are defer { ... }
+       syntax which doesn't work because ref on variables deferred with Scalar::Defer
+       return 0 instead of ARRAY -dpavlin
+     * Add an "(any)" label to Action::Record::Search when render as radio. -audreyt
+     * Jifty::Action::Record - Support for "is autocompleted" annotation. -audreyt
+     * Jifty::Action::Record::Search - "numeric" and "decimal" fields are also
+       numeric. -audreyt
+     * Jifty::Action::Record - "is autocompleted" choices should not consider
+       null/empty fields. -audreyt
+     * Action::Record::Search - When there is just one choice, don't bother
+       displaying '(any)' for Radio. -audreyt
+     * Jifty::Action::Record::Search - First cut at a _dwim field for numeric
+       fields that supports > >= < <= == = != ! <> operators. -audreyt
+     * Jifty::Action::Record - Autocompletion now lists only the parts
+       that matches the user-input as prefix. -audreyt
+     * Jifty::Action::Record::Search - Add _before/_since for dates, as well as
+       the equivalent _ge and _le for numbers. -audreyt
+     * Jifty::Action::Record::Search - Add hints to _dwim. -audreyt
+     * Adding a note about canonicalizers being idempotent -nelhage
+     * add max_length alias to fix Object::Declare and Jifty::Param::Schema
+       not handling length properly -alexmv
+
+   bin/jifty
+     * Change Jifty::Util's probe of bin/jifty from -x to -r for poor
+       people on filesystems that does not have a executable bit. (The
+       maybe_command is still needed for the .bat case.) -audrety
+     * Fix the bin/jifty detection logick: The .bat extension exists for
+       MSWin32, cygwin and os2, so use MM->maybe_command for those three
+       platforms. -audreyt
+     * Also, the -e check is redundant after -x, and in Win32 we can use
+       bin/jifty.bat alone without bin/jifty, so make the check respect
+       that case. Reported by: Stephen at s-team -audreyt
+     * bin/jifty covered sigterm in a way that could cause zombie processes
+       under fastcgi -jesse
+     * Be explicit about the paths we're creating -alexmv
+     * Jifty::Script::Server - Remedy for the edge error case where var/
+       is missing, which used to cause mysterious error messages. -audreyt
+
+   Building apps
+     * Small error string change to suggest looking for missing use lines
+       in models where refer_to is used -bartb
+     * Ongoing work to pass through Class::ReturnValue errors all the way
+       from Jifty::DBI to the view layer -jesse
+     * create scaffolding actions with the new Jifty::Param::Schema
+       syntax --falcone
+     * Jifty::Manual::Upgrading - Remove the now-obsoleted claim that one has
+       to "use" model classes before renaming it. -audreyt
+     * Jifty::Upgrade - rename() now works with SQLite too, woot! -audreyt
+
+   Dependencies and installation
+     * Makefile.PL typo. Spotted by David Adler -jesse
+     * Files for debian packaging, now rather for actual cpan release
+       than for svn. -yves
+     * Update MANIFEST.SKIP and run 'make manifest' to ensure that new
+       files get added properly. -jpeacock
+     * Added a dependency on libextutils-command-perl to debian control
+       file -bartb
+     * Older DBI versions didn't provide the API we're using. (0.22 is
+       known bad) -jesse
+     * Remove PerlIO::gzip as a Jifty dependency. -audreyt
+     * Older XML::Writer versions failed tests. Dependency bumped -
+       Thanks to Jonathan Stowe -jesse
+     * Reverting to dumping using YAML.pm *again*, because YAML::Syck
+       generates XML that makes YAML segfault :/ -nelhage
+     * Fixed missing dependency on Module::CoreList -- Thanks to Henry
+       Baragar -jesse
+     * Makefile.PL - Add dependency on Test::Base and Module::Refresh.
+       Reported by: Andreas Koenig -audreyt
+     * Makefile.PL - Bump JSON::Syck dependency to 0.15 to handle
+       single quote + unicode strings. -audreyt
+     * SQLite is required to test properly -jesse
+     * debian packaging updates -yves
+     * Skip html files when looking for dependencies. This may cause us to
+       miss some modules used only from within mason, but it will stop falsely
+       detecting lines that start with the word "use" in docs. -jesse
+     * add Test::MockModule and Test::MockObject for J::W::F::F testing -agentz
+     * made Test::MockModule and Test::MockObject optional by
+       putting them into development dependency list -agentz
+     * Makefile.PL: remove Test::HTTP::Server::Simple dependency when $^O eq
+       'MSWin32' -ishigaki
+     * debian packages : add libtest-mockobject-perl libtest-mockmodule-perl in
+       recommands packages (for new snapshot on jiftysvn repository) -yves
+     * cleaned up debian readme -bartb
+     * Clean up MANIFEST (mostly sqlite files) -alexmv
+     * hlb++ reported that we really want HTTP::Server::Simple 0.26+,
+       not 0.20+, as 0.20 and 0.21's critical URI-path-processing
+       bug makes us non utf8 friendly. -audreyt
+     * Added Data::UUID to the Makefile.PL and made sure we use'd it in 
+       Jifty.pm -kevinr
+
+   Internationalization
+     * The ubiquitous "There was an error completing the request. Please
+       try again later.") error message should be localised. -audreyt
+     * We now default the location of the jifty siteconfig file -jesse
+     * For some reason, loc('') started spewing out PO metadata. This
+       seems to be b0rkeness on the Locale::Maketext layer, but for now
+       generalize the undef detection logic in Jifty::I18N to recognize
+       that case. -audreyt
+     * "You need to fill in this field" needs to be localized. -audreyt
+     * Stopped the internationalization system from exploding if a plugin
+       doesn't have a module_dir -alexmv
+     * The internationalization system now extracts messages from
+       TemplateRoot, not share. -clkao
+     * Plugin internationalization and french po files -yves
+     * Jifty::I18N: New ->refresh method so .po files are reloaded
+       properly when DevelMode is on. -audreyt
+     * Even more l10n on Jifty::Action::Record. -audreyt
+     * jifty po shouldn't check/update files under .svn directories -ishigaki
+     * zh_cn and zh_tw translations -audreyt
+     * "jifty po": Ignore _svn/ directories (Win32), as well as foo~ files. -audreyt
+     * L10N for the new Search action fields. -audreyt
+     * update fr.po -yves
+     * update zh_cn and zh_tw and use traditional characters in zh_tw -agentz
+     * update german J::Manual::Tutorial_de to match english version's 
+       changes -wolfgang
+     * Jifty::Script::Po: shouldn't update other catalogs if we specify target
+       language with -l -ishigaki
+
+   Testing
+     * Jifty::Test: canonpath-ed for Win32 -ishigaki
+     * make sure to skip 04memcached.t if you don't have Cache::Memcached
+       -ishigaki
+     * skip all the live tests (that call 'start_ok') on Win32 -ishigaki
+     * shut up warnings when tests have no plan (t/Continuations/03-gc.t)
+       -ishigaki
+     * Added Jifty::Test->web to allow using Jifty->web in tests without
+       a bunch of scaffolding.
+     * Converted search tests to using Jifty::Test->web -schwern
+     * Basic compile and startup tests for the Chat sample -schwern
+     * add tests for Jifty::Web::Form::Field's render methods -agentz
+     * adjusted t/06-forms.t to skip related tests when
+       these two modules are not installed. -agentz
+     * fix t/TestApp-Plugin-REST/t/02-basic-use.t because ClassLoader
+       creates 4 new actions -falcone
+     * add tests for Jifty::Param::Schema -agentz
+     * TODO tests attempting to test if we get ajax validation errors for
+       mandatory values after the sticky_value has been deleted -trs
+
+   Email notifications
+     * When sending email notifications, encode the message body -clkao
+     * MIME-encode notification subjects. -clkao
+     * Content-transfer-encoding needs to be 8bit. -clkao
+     * Don't set notification transfer_encoding to 8bit if it's actually
+       multipart. -clkao
+
+   Dispatcher
+     * avoid undef warnings in the Dispatcher -jesse
+     * Jifty::Dispatcher - Alternation in extended shell globbing syntax
+       now admits zero characters as well:
+       on 'foo{,.zip}'     # matches 'foo' and 'foo.zip' -audreyt
+     * Jifty::Dispatcher - NUMBER SIGN (#) now captures one or more digit
+       characters in the extended shellglob condition syntax.
+       Suggested by: Sebastian Riedel -audreyt
+
+Jifty 0.60912
+
+Testing
+
+ * force to use Jifty::TestServer on Win32, though both JTS and THSS doesn't work properly at the moment. 
+ * Give a description for get_html_ok so that you know what URLs fail/succeed in test output
+ * Small stylistic cleanup to t/01-dependencies
+ * Honour coverage options.
+ * make sure to remove remnant test db before we test (Jifty on Win32 fails to unlink them right now)
+ * Add Jifty::Test->test_in_isolation
+ * Document Jifty::Test->is_done.
+ * Added Jifty::Test->is_passing and is_done
+ * Basic SYNOPSIS for Jifty::Test as well as mentioning the Test::More passthrough.
+ * Add Jifty::Test->teardown_mailbox to mirror setup_mailbox
+ * use safer File::Spec->rel2abs for SubTest
+ * TestServer: use File::Spec->rel2abs; it's safer than Cwd::abs_path which croaks
+ * Jifty::Test->test_file() accepting and returning a list causes problems
+   because people will try to do:  my $file = Jifty::Test->test_file($file) and
+   it ain't gonna DWIM.
+ * Mention Shell::Command and Jifty::Test->temp_file in the style guide.
+ * Add Jifty::Test->test_file() to declare files created only for testing and
+   which should be cleaned up.
+ * Fixing tests when using JDBI::Record::Memcached and setting things in the database from test scripts
+ * Added explicit tests for Jifty::Action::Redirect
+ * Script for running client and server side combined code coverage.
+ * Give a description for get_html_ok so that you know what URLs fail/succeed in test output
+ * Ignore "fluff" errors in HTML validation since they cause non-W3C attributes like "autocomplete" to be warned about
+ * Add html_ok method for checking the mech's current content so tests can use it while we retain control over Test::HTML::Lint
+
+Models
+
+ * jifty model --name now uses the new schema {} sub.
+ * Made the display of a friendly string for picking a record from a list a lot more flexible. 
+ * canonicalization wasn't being properly run on models before validation
+ * Added Jifty::Filter::DateTime, a JDBI filter that promotes DateTime
+   objects to Jifty::DateTime objects on read, setting the time zone
+   appropriately.
+ * Added a concept of "virtual" arguments to actions. These won't be passed on to Record classes, even if they're sumbitted. We use this for Password confirmation arguments, so that we don't pass password_confirm on to the database, which is kinda useless (and breaks the db ;)
+ * Added a as_superuser method to Jifty::Record to make it easier for
+ * code to briefly dodge around ACLs when needed.
+
+
+Admin UI
+
+ * __jifty/admin: use ->models reflection to build the nav bar.
+ * Integer C<gt> or C<lt> searching.
+ * Added substring search and date comparison to J::A::R::Search
+ * Basic search in admin mode using Jifty::Action::Record::Search. Still buggy, especially UI-wise, but functional.
+ * Initial version of Jifty::Action::Record::Search. It only supports
+ * exact positive searches on fields at the moment.
+ * There's no point in rendering confirm fields for passwords when we're
+   viewing records in admin mode.
+ * Don't create _gt and _lt search fields for magic _id refers_to fields.
+ * Make the admin UI look slightly less crappy.
+ * Make admin mode DTRT with columns that end in _id and refer to another model.
+
+REST
+
+ * REST Dispatcher: model list reflection
+ * Basic placeholder for REST plugin tests
+ * REST Dispatcher skeleton that actually works
+* Jifty::Plugin::REST::Dispatcher - /=/action/ now works across HTML+HTTP.
+* J::P::REST::Dispatcher - all GET model URLs work, with 404s.
+* Jifty::Plugin::REST::Dispatcher - model fetch actually works!
+
+
+Actions
+
+ * No longer generating arguments on C<Jifty::Action::Record> for fields
+   that C<refer_to> C<Jifty::DBI::Collection>s, since we can't do
+   anything useful with them right now anyways.
+ * Get the _confirm items on passwords to respect sort ordering
+ * Debugging improvements to stop stupid developer mistakes like passing the wrong sort of object to a Jifty::Action::Record. 
+ * Now we do proper escaping of values in select-one lists.
+ * Canonicalise {onclick}{submit} using the accessor wrapper.
+ * Only call moniker when {onclick}{submit} isa Jifty::Action.
+
+Documentation
+
+ * Wolfgang Kinkeldei: added a pod on models 
+ * Patch from Todd Chapman to fix tutorial
+ * The beginnings of a Jifty code style guide.
+ * Jifty::Manual::Continuations: reflect tangent() in the manual.
+ * Developer documentation for the Jifty::Web::Form::Field::* hierarchy.
+ * Add "How do I Add Atom/RSS Feeds" to Cookbook.
+ * Add a recipe about running fastcgi server, which, in fact, only points
+   to 'jifty help fastcgi'.
+ * lib/Jifty/Manual/FAQ.pod - a start on an FAQ
+ * Standardizing on referring to share/web everywhere in the tutorial.
+ * Todd Chapman noticed a typo in the docs about autocompleters
+ * Tutorial patch from rindolf++
+ * documented logger_component argument
+ * Add a small bit of doc about creating your own classes that are normally created by J::ClassLoader
+ * A start at some docs on upgrading, needs reviewing and some more examples
+ 
+
+Perfomance and optimization
+
+ * Don't try to lowercase session information on postgres
+ * Don't bother with session when serving static files.
+ * Don't need ExtUtils::MakeMaker in Jifty::Util.  This is about 7% of total compile time loading jifty.
+ * Kill Jifty::Web::Menu circular references.
+ * Transform actions in {onclick}{submit} to their monikers, to avoid
+   circular references.
+
+Javascript and HTML
+
+ * Fix AJAX canonicalization of date fields
+ * Some browsers don't like trailing commas in JS arrays and hashes.
+ * You can now pass confirm => 'question?' to javascript hooks (i.e. onclick) and get a confirm dialog in the browser. This doesn't work without javascript yet.
+ * Use a local copy of the icons in our calendar widget, rather than the version that yahoo points to on akamai
+ * fix the unexpected behavior in context menu for IE users.
+ * Fix bug that didn't allow calendar months to be changed
+ * Show calendar widget on focus and hide it on blur
+ * If we don't have XMLHttpRequest, fall back on page loads
+ * More thorough normalization of the submit parameter to Javascript handlers
+ * Accesskey support added to buttons and links. It just uses the same keys as our javascript key bindings.
+ * A little more Element/Clickable refactoring, and implementing a
+   C<disable> option to onclick handlers that toggles whether or not to
+   disable form fields for an action.
+ * We now write out state variables at the start of forms, instead of at the end. 
+ * Moved "Dismiss" buttons on messages and errors into Behaviour, so they only show up in javascripty contexts where they'd be useful
+ * Added the ability to support target attributes in menu items and clickables
+ * IE doesn't support element.setAttribute("class", "foo"), so use element.className instead
+ * Explicitly specify a radix of 10 (decimal) for the parseInt calls used in Yahoo's calendar widget when parsing the date to initially display
+ * Don't attempt to disable hidden inputs, since this sometimes causes IE to die
+ * Use our own "enter" handler to select the button to click, since Safari sometimes gets it wrong with complex fields
+ * The setAttribute call doesn't work for "class" in IE
+ * Fixing the calendar widget to create a new calendar every time, so
+   that the calendar reflects any changes the user makes in the text
+   field.
+ * Support turning off autocomplete on a per-form basis.  We still need per-field, but that's for later.
+
+Distribution
+
+ * debian packaging files for jifty
+ * Removed duplicated share/web (it was copied to lib/auto/Jifty)
+ * CGI.pm 3.17 (and possibly earier) had a bug where regex metacharacters in
+   the PATH_INFO would cause it to puke.  We now depend on CGI 3.19 which fixed
+   that bug.
+ * Update Module::Install to 0.64.  The important thing here is it gets us
+   a fixed Module::AutoInstall which works when you run Makefile.PL from the
+   command line without CPANPLUS installed.
+ * Don't index the t directory
+ * add "use Jifty::YAML" before all uses.
+ * Moved some modules to feature sections in Makefile.PL, updated 01-dependencies.t to recognise recommends sections as well as requires
+ * Win32 requires File::ShareDir 0.04
+ * Removed Text::Autoformat dependency and usage.
+
+Dispatcher
+
+ * Dispatcher: Support tangent($url) as sugar for Jifty->web->tangent(url=>$url).
+ * Dispatcher: Allow "**" in glob pattern to mean anychar including slash.
+ * Dispatcher did not have a ->{cgi}, so ->method certainly could not
+   work.  Use the env variable for now.
+ * Jifty::Dispatcher: abort(404) now works as the doc promised.
+
+Internals
+
+ * Jifty->web->return in void context is now an immediate return.
+ * Jifty::ClassLoader - Make Jifty::Handle a CL'ed module as well,
+   so MyApp::Handle can implement scary magick of its own.
+ * Don't blow up when trying to check if action mixins are autogenerated
+ * Let's be better about not redirect-looping when calling continuations
+   to paths that contain multibyte characters. This solution is a hack,
+   but it's better than looping.
+ * Fix placeholders on browser forward/back
+ * Replace hard tabs with spaces for consistency
+ * Jifty::Web::state_variables no longer prefixes keys with J:V- before
+   returning them, and Clickables now serialize the *outgoing* state
+   vars, instead of the previous request's.
+ * When rendering a page region, mark actions as inactive, don't remove
+   them, so that their arguments are available inside fragments.
+ * If we receive an action's arguments, but it's not in J:ACTIONS, or
+   we don't run it for some other reason, don't consider it to have
+   failed for the purposes of stickiness.
+ * moniker_for and action_form now behave more cleanly with forms which
+   have no non-continuation fields other than their submit buttons.
+ * No longer lose if you do a Jifty::Action::Redirect to the same page
+   you're already on. Also, add the ability to force Web to redirect,
+   even if it's to the current page.
+ * Jifty.pm: Change all __PACKAGE__ to Jifty.
+ * Jifty::ClassLoader: provide ->models accessor to list the model classes.
+ * added Jifty::Request::clear_state_variables
+ * Form::Clickable: Don't mix self accessors and args.
+ * Refactor the constructors for Jifty::Web::Form::*, which takes initial
+   hash and values to be overridden with accessors.
+ 
+Internationalization
+
+ * LetMes' escaping should be utf8 aware
+ * Email addresses probably shouldn't ever be utf8, but using the utf8 escaper is more Right(tm)
+ * Properly UTF-safeing Jifty::LetMe
+ Sean E. Millichamp and clkao both pointed out that Locale::Maketext could choke on overloaded objects like DateTimes. This change makes sure that doesn't happen any more.
+ * Locale::Maketext doesn't always do the right thing with user-generated strings. So let's do that for it.
+ * Properly encode arguments when generating LetMe URLs.
+
+Email
+
+ * add UTF-8 charset to message body on notifications
+ * added infrastructure to do mime mails
+ * make Jifty notifications be UTF-8
+
+Plugins
+
+ * Jifty::Web::Session::ClientSide - Client-side sessions.
+ * Added a ProfileBehaviour plugin to aid profiling Javascript
+   Behaviours (see app_behaviour.js in the Jifty source for some more
+   information)
+ * Some Behaviour profiling UI fixes.
+ * Removing profiling code from behaviour.js
+ * Get the signup form in the login plugin to respect locally defined schema for the user class
+ * Added information about the environment to the EmailErrors plugin
+ * Making the Login plugin play nice with admin mode.
+ * Plugin static roots should take precendence over jifty's
+
+
+Win32
+
+ * Win32 complains when you try to unlink open DB
+0.60722
+
+* Dispatcher fixes to deal with the better canonicalization we started doing in
+   0.60707
+* changed all instances of '/usr/bin/perl' to '/usr/bin/env perl'
+* added a path option to Jifty::Web->url
+* added url tests
+* Jifty::Manual::Actions -- update the worldview to reflect the
+  parameters/arguments concept split.
+* Introduce aliases.  See Jifty::Param::Schema for the table.
+* Declarative Jifty Parameters.
+* See Jifty::Param and Jifty::Param::Schema for the new syntax.
+* Also added dependencies for Jifty::Script::Deps and declarative parameters.
+* Also updated test applications to use declarative parameters. 
+* Adding the CSS browser selector trick from http://rafael.adm.br/css_browser_selector/ to Jifty
+* After autocomplete, trigger a validation.
+* Upping JSON::Syck version dependency. 0.14 fixes escaping in single-quoted strings.
+* Add a tooltip to the dismiss link and hide the dotted border
+* Trailing commas are not good for JS in Safari
+* Let's not blow up if we have placeholders on an input without a form
+* Don't fade autocomplete in and out, just show and hide it
+* Not submitting placeholder values when we submit forms or AJAX
+* Add the class before we set the text, so that it appears grayed-out, rather than appearing and *then* graying out
+* Support multi-line placeholders
+* textareas can have placeholders, too; Style them appropriately as well
+* Adding support for placeholders, grayed-out text in form fields that is written in with JS and vanishes on focus
+* Auto-accept cpan's wisdom about prompts (Jifty::Deps)
+* 0th sketch at "jifty deps"
+* packaging plan updates
+* J::Web::redirect can take a Clickable as arg, so make goto do that, instead of passing a URL with parameters, which doesn't work right
+* Proper port support on urls. Thanks to jpeacock.
+*  Resolve inconsistent filenames vs packages (Plugins)
+* Switched Jifty::Web::url to use uri.pm rather than "heuristics"
+* Let's not blow up if an action has a result that's an unblessed reference.
+* Don't upgrade the database versions with schema --print. I'm not sure
+  if there's a good way to persuade JDBI to give us the SQL to print, so
+  we're just spitting out a warning for now, but that's better than the
+  old behavior.
+* Stop notification from flipping out if you use a scalar as the To:
+* basic smoke test for jifty's notifications 
+* Only set active child on create if we have a request
+* More serious failure message, and don't imply that it's necessarily the server's fault.
+* update .po files
+* Jifty::Dispatcher - there's no call_next, remove it from POD, fnord.
+* Refactoring message rendering slightly
+* Fix Jifty-Win32 by having canonicalize_path always returning
+  /-separated paths, never \-separated paths.
+* Let classes be set on menu items
+* Adding a warning about our slow Rico.Corner.round
+* Documenting how to write sane Behaviours that don't leak memory (leak
+  less memory, probably) in IE and aren't dog-slow.
+* Fix JS memory leak in IE
+* Make jifty tests respect the current given @INC, so it doesn't
+  use lib when you are supposed to use blib during make test.
+* Make the subtest system less painful.
+* Use Jifty::Script to invoke test server, so it doesn't depend on
+  bin/jifty.
+* Fix a Safari display bug
+* Fix calendar positioning bug and make sure it works when the date field is within a relative or absolutely positioned element
+* Test file for Jifty::Client
+* First pass at a Jifty client module.
+*  English orthography fixes.
+* Trailing commas in Perl are good.  In Javascript, they aren't, and sometimes cause IE to barf (like this one).
+*  Hide focus border
+* Lowering the autocomplete delay
+* first-pass editorial run over Continuations.pod.
+* Sketchy sketchy handwavy descriptions of page region backend.
+  Ramblings totally not expected to be interpretable.
+* Wrap the popup notification div in dropshadow wrapper hooks
+* Mention webservices in Actions doc
+* Double fallback goes the way of the dodo
+* Continuation manual
+* Set up the output API for mapping of request parameters (input API
+  already existed)
+* Change method of getting results out of response on continuation RETURN
+* Fewer calls to ->arguments, though they might be cached already.
+* Not all CurrentUser classes may have a "nobody"
+* Jifty::Web::Form:Clickable - provide a bit more info on how to use
+  the "returns" field.
+* jifty-dispatcher.graffle that shows the dispatch chain.
+* Nicer "server down" message
+* Re-enable form inputs after failure
+* toggleable page region clickables weren't doing the right thing when used in non-ajax mode
+* Fix the validation and autocomplete race condition
+* Skip nobody and superuser when we do notifications
+
+
+060707
+
+  * Minor build fixes
+
+060706
+  * SECURITY UPDATE: Previous versions of Jifty did not 
+  protect users against a class of remote data access vulnerability. If an
+  attacker knew the structure of your local filesystem and you were using 
+  the "standalone" webserver in production, the attacker could gain read
+  only access to local files. 
+  
+  We found this vulnerability on 6 July 2006 during an internal Security 
+  scan. We've added new tests to ensure that these and other similar
+  vulnerabilities don't recur.
+
+  We recommend that ALL users of Jifty UPGRADE to 0.60706 IMMEDIATELY.
+
+
+060616
+  * The last CPAN release was broken. No real changes.
+
+060615 (15 June 2006)
+
+The following incompatible changes were made to Jifty. For a complete changelog,
+please see the "Changes" file.
+
+ * Removed the ActionBasePath and CurrentUserClass configuration
+   variables.  This breaks backwards compatibility.
+
+ * If you've overridden /_elements/javascript in your app, you'll want to 
+   take a look at the new stock version to see what has changed.
+
+ * The JS method document.getElementsBySelector() no longer exists.  Use 
+   cssQuery() instead.
+
+ * Jifty::Record now returns empty objects for related objects that can't be 
+   loaded, rather than undef
+
+
+ * The keybinding JS code is now a more proper library 
+   (Jifty.KeyBindings) and less intrusive.  If you've overridden the 
+   default /_elements/wrapper in your app, you'll want to make sure you get 
+   rid of the keybinding javascript (see the stock wrapper).  Just include 
+   <& /_elements/keybindings &> wherever you want the keybindings for a 
+   page to appear.
+
+ * This shouldn't be the cause of breakage, but the included rico.js is 
+   no longer a stock Rico build.  See the comments at the top of the file 
+   if you're interested.
+
+ * 'last_rule' now aborts only the current stage -- thus, last_rule                         
+   from a 'before' block will *NOT* prevent the RUN stage from happening!
+   This is a *BACKWARDS-INCOMPATIBILE CHANGE*, but fixes the dispatcher
+   to agree with its docs.
+ * 'abort' is the correct call to skip straight to the cleanup block.                       
+ * This allows the edit in place plugin to 'claim' its path and                             
+   protect it from access control in the app's 'before' blocks                                                                                                                              
+
+
+
+0.60507 (7 May 2006)
+
+  * Pod fixes from Eric Wilhelm
+    lib/Jifty/Object.pm - removed incorrect '=for' directive
+    lib/Jifty/Web/Form/Field.pm - removed incorrect '=for' directive
+    lib/Jifty/Web/Form.pm - removed incorrect '=for' directive
+
+  * Better failure messages on when schema upgrades with SQLite fail
+    from Alex Vandiver
+
+  * Be a little more explicit about SQLite's limitation, and a possible
+    (painful) workaround
+
+  * Update the inc tree to 0.62 for various fixes,
+    in particular improved share_dir compatibility. --Audrey Tang
+
+  * We were inconsistently using Jifty::Util::make_path as a
+    subroutine. It's a class method.  This could break the stub
+    generators and tutorial.  Thanks to Sean E. Millichamp
+
+0.60505 - Cinco de Jifty! (5 May 2006)
+
+  * Native support for times and timezones.
+
+  * Bug fixes (Many contributors)
+
+  * Documentation updates (Many contributors)
+
+  * Win32 Support (Audrey Tang)
+
+  * New Session layer based on Jifty instead of Apache::Session.
+    Designed for AJAX and Continations (alexmv)
+
+  * Jifty internal metadata store (The begining of an internal configuration
+    management system (alexmv)
+
+  * Form fields no longer automatically insert the field name by itself
+    as a class.  Instead, the class has changed to "argument-<fieldname>"
+	to avoid conflicts with generic class names (such as date).
+
+  * Move allow and deny'ing of actions into Jifty::API; this breaks
+    backwards compatibility.
+
+  * Don't allow applications to be named "Jifty" by default.  They are
+    forced to be named "JiftyApp" now, for namespace reasons.
+
+  * Remove Jifty->web->actions method; you should be using
+    Jifty::Form's actions method.
+
+  * Beginning of localization support.
+
+  * Notifications can now take a user object or an email address
+
+  * "sort order for arguments" patch, as suggested by miyagawa.  This
+    makes use of sort_order column property of Jifty::DBI
+
+  * YAML -> Jifty::YAML
+
+  * Switch from Time::ParseDate to Date::Manip, since the former isn't
+    win32 compatible
+
+  * Shuffle the Mason and static handlers into Jifty::View namespace
+
+  * Jifty no longer attempts to AJAX submit file upload fields
+
+  * We no longer write DefaultStaticRoot and DefaultTemplateRoot into
+    config files
+
+  * Added a "LogLevel" option to the Jifty config file, so you can
+    more easily enable debug logging.
+
+
+0.60321
+
+  * 'return if already_run' in after rules so they run only once
+
+  * Overhauled the static server to try really hard to force caching
+    by clients.  It also gzips its content, if possible.
+
+  * More stylish forms
+
+  * Allow Jifty->web->return( to => "..default path..", ...)
+
+  * Actually accept region names to refresh
+
+  * Halo improvements
+
+  * chromatic supplied a patch to switch from UNIVERSAL::isa to ->isa.
+
+  * Trivial webservices hack
+
+  * It's now possible to override Jifty::Record's baseclass in your
+    app
+
+
+0.60221
+
+  * Use Jifty::Util->require to log require errors
+
+  * Auto-generate Bootstrap class
+
+  * Give us a way to get the CurrentUser from a Mech object during
+    testing
+
+  * When calling a continuation, try to make sure that the urls are
+    really different, not just differently canonicalized, lest we get
+    an infinite loop
+
+  * Default to not showing debug logs
+
+  * Fragments in JS land now know about their parents, and pass their
+    superstructure in the fragment request.  This lets $region->parent
+    have full information.
+
+  * 'refresh => region' mode for replacement
+
+  * Better docs on region replacement
+
+  * add_* calls on Jifty::Request now return the object added, not the
+    request
+
+
+0.60213
+
+  * Jifty::Dispatcher written
+
+  * Jifty::Handler is now an object, not a utility. It has the power
+    to "run" a request.
+
+  * Call chain is now Handler to Dispatcher, which calls Jifty::Web
+    and Mason, instead of the other way around.
+
+  * Better Documentation coverage.
+
+  * Paint on some really bitchin 'go faster' stripes on the server.
+
+  * Refactored the dispatcher to use exceptions rather than LABELS: so
+    that Devel::DProf doesn't fall over
+
+  * Added a new "DevelMode" flag, to toggle the peformance-killing
+    development aids.
+
+  * Only drop tables if the tests all succeeded
+
+  * Fragments now go through the dispatcher
+
+  * `jifty schema` overhaul
+
+  * Mandatory form fields now have a css marker.
+
+  * Do away with setup_actions mason method
+
+  * Stop using mason notes
+
+  * Jifty::Script::Schema support for basic mysql love
+
+  * lighttpd support.
+
+  * Move autocomplete.xml and validator.xml to __jifty/.
+
+  * Upgrade to Scriptaculous 1.5.1.
+
+  * Delete is its own action now, instead of being part of Update.
+
+
+0.51228
+
+ * Jifty::Action->argument_names should sort keys lexographically, not
+   random hash-ordering.
+
+ * Remove last vestiges of ::Delete from ::Update
+
+ * Refactored Jifty::Config to allow the application class to be
+   specified when calling Config->guess
+
+ * Refactored Jifty::Script::App into bite-sized morsels
+
+ * Made Jifty::Script::App generate a config file
+
+ * Made Jifty::Script::App and Jifty::Config::Guess happy with
+   multi-level package names
+
+
+0.51225 - Initial release

Added: jifty/branches/schema-plugins/MANIFEST
==============================================================================
--- (empty file)
+++ jifty/branches/schema-plugins/MANIFEST	Mon Jan 29 21:05:02 2007
@@ -0,0 +1,588 @@
+AUTHORS
+bin/build_par
+bin/jifty
+bin/runcover
+bin/service
+bin/xgettext
+Changelog
+debian/changelog
+debian/compat
+debian/control
+debian/README
+debian/rules
+doc/ajax-upgraded-links
+doc/building_a_par
+doc/client_side_continuations
+doc/command_naming
+doc/declarative-test-design
+doc/edit-in-place
+doc/examples/CounterDemo/bin/jifty
+doc/examples/CounterDemo/etc/config.yml
+doc/examples/CounterDemo/Makefile.PL
+doc/examples/CounterDemo/share/web/templates/index.html
+doc/examples/CounterDemo/t/00-counter-test.t
+doc/jifty-action-record-search
+doc/jifty-dispatcher.graffle
+doc/jifty-dispatcher.svg
+doc/jifty-plugins-2.0
+doc/jifty-web-form-etc
+doc/packaging
+doc/plugin-requirements
+doc/plugin-syntax
+doc/plugins-restated-assumptions
+doc/pubsub/backend_message_types
+doc/pubsub/subscriptions
+doc/pubsub/system_architecture.graffle
+doc/pubsub/system_architecture.png
+etc/config.yml
+etc/site_config.yml
+examples/Chat/bin/jifty
+examples/Chat/etc/config.yml
+examples/Chat/lib/Chat/Action/Send.pm
+examples/Chat/lib/Chat/Event/Message.pm
+examples/Chat/lib/Chat/Server.pm
+examples/Chat/Makefile.PL
+examples/Chat/share/web/templates/fragments/message
+examples/Chat/share/web/templates/fragments/sender
+examples/Chat/share/web/templates/index.html
+examples/Chat/t/00compile.t
+examples/Chat/t/01startup.t
+examples/Clock/bin/jifty
+examples/Clock/clockserv.pl
+examples/Clock/etc/config.yml
+examples/Clock/lib/Clock/Event/Tick.pm
+examples/Clock/lib/Clock/Server.pm
+examples/Clock/Makefile.PL
+examples/Clock/share/web/templates/fragments/time
+examples/Clock/share/web/templates/index.html
+examples/MyWeblog/bin/jifty
+examples/MyWeblog/etc/config.yml
+examples/MyWeblog/lib/MyWeblog/Model/Post.pm
+examples/MyWeblog/Makefile.PL
+examples/MyWeblog/share/web/templates/_elements/nav
+examples/MyWeblog/share/web/templates/fragments/page_of_posts
+examples/MyWeblog/share/web/templates/index.html
+examples/MyWeblog/share/web/templates/post
+examples/MyWeblog/t/00-model-Post.t
+examples/Ping/bin/jifty
+examples/Ping/etc/config.yml
+examples/Ping/lib/Ping/Action/AddPing.pm
+examples/Ping/lib/Ping/Action/CancelPing.pm
+examples/Ping/lib/Ping/Event/Pong.pm
+examples/Ping/lib/Ping/PingServer.pm
+examples/Ping/lib/Ping/Server.pm
+examples/Ping/Makefile.PL
+examples/Ping/share/web/templates/fragments/pong
+examples/Ping/share/web/templates/index.html
+examples/Ping/t/00compile.t
+examples/Ping/t/01startup.t
+inc/Module/AutoInstall.pm
+inc/Module/Install.pm
+inc/Module/Install/AutoInstall.pm
+inc/Module/Install/Base.pm
+inc/Module/Install/Can.pm
+inc/Module/Install/Fetch.pm
+inc/Module/Install/Include.pm
+inc/Module/Install/Makefile.pm
+inc/Module/Install/Metadata.pm
+inc/Module/Install/Scripts.pm
+inc/Module/Install/Share.pm
+inc/Module/Install/Win32.pm
+inc/Module/Install/WriteAll.pm
+lib/Email/Send/Jifty/Test.pm
+lib/Jifty.pm
+lib/Jifty/Action.pm
+lib/Jifty/Action/Autocomplete.pm
+lib/Jifty/Action/Record.pm
+lib/Jifty/Action/Record/Create.pm
+lib/Jifty/Action/Record/Delete.pm
+lib/Jifty/Action/Record/Search.pm
+lib/Jifty/Action/Record/Update.pm
+lib/Jifty/Action/Redirect.pm
+lib/Jifty/API.pm
+lib/Jifty/Bootstrap.pm
+lib/Jifty/ClassLoader.pm
+lib/Jifty/Client.pm
+lib/Jifty/Collection.pm
+lib/Jifty/Config.pm
+lib/Jifty/Continuation.pm
+lib/Jifty/CurrentUser.pm
+lib/Jifty/DateTime.pm
+lib/Jifty/Dispatcher.pm
+lib/Jifty/Event.pm
+lib/Jifty/Event/Model.pm
+lib/Jifty/Everything.pm
+lib/Jifty/Filter/DateTime.pm
+lib/Jifty/Handle.pm
+lib/Jifty/Handler.pm
+lib/Jifty/I18N.pm
+lib/Jifty/JSON.pm
+lib/Jifty/LetMe.pm
+lib/Jifty/Logger.pm
+lib/Jifty/Manual/AccessControl.pod
+lib/Jifty/Manual/Actions.pod
+lib/Jifty/Manual/Continuations.pod
+lib/Jifty/Manual/Cookbook.pod
+lib/Jifty/Manual/FAQ.pod
+lib/Jifty/Manual/Glossary.pod
+lib/Jifty/Manual/Models.pod
+lib/Jifty/Manual/ObjectModel.pod
+lib/Jifty/Manual/PageRegions.pod
+lib/Jifty/Manual/RequestHandling.pod
+lib/Jifty/Manual/Style.pod
+lib/Jifty/Manual/Tutorial.pod
+lib/Jifty/Manual/Tutorial_de.pod
+lib/Jifty/Manual/Tutorial_ja.pod
+lib/Jifty/Manual/Upgrading.pod
+lib/Jifty/Manual/UsingCSSandJS.pod
+lib/Jifty/Mason/Halo.pm
+lib/Jifty/Model/Metadata.pm
+lib/Jifty/Model/Session.pm
+lib/Jifty/Model/SessionCollection.pm
+lib/Jifty/Module/Pluggable.pm
+lib/Jifty/Notification.pm
+lib/Jifty/Object.pm
+lib/Jifty/Param.pm
+lib/Jifty/Param/Schema.pm
+lib/Jifty/Plugin.pm
+lib/Jifty/Plugin/ClassLoader.pm
+lib/Jifty/Plugin/REST.pm
+lib/Jifty/Plugin/REST/Dispatcher.pm
+lib/Jifty/Record.pm
+lib/Jifty/Request.pm
+lib/Jifty/Request/Mapper.pm
+lib/Jifty/Response.pm
+lib/Jifty/Result.pm
+lib/Jifty/RightsFrom.pm
+lib/Jifty/Script.pm
+lib/Jifty/Script/Action.pm
+lib/Jifty/Script/App.pm
+lib/Jifty/Script/Deps.pm
+lib/Jifty/Script/FastCGI.pm
+lib/Jifty/Script/Help.pm
+lib/Jifty/Script/Model.pm
+lib/Jifty/Script/Plugin.pm
+lib/Jifty/Script/Po.pm
+lib/Jifty/Script/Schema.pm
+lib/Jifty/Script/Server.pm
+lib/Jifty/Server.pm
+lib/Jifty/Subs.pm
+lib/Jifty/Subs/Render.pm
+lib/Jifty/Test.pm
+lib/Jifty/Test/WWW/Mechanize.pm
+lib/Jifty/TestServer.pm
+lib/Jifty/Upgrade.pm
+lib/Jifty/Upgrade/Internal.pm
+lib/Jifty/Util.pm
+lib/Jifty/View/Mason/Handler.pm
+lib/Jifty/View/Static/Handler.pm
+lib/Jifty/Web.pm
+lib/Jifty/Web/Form.pm
+lib/Jifty/Web/Form/Clickable.pm
+lib/Jifty/Web/Form/Element.pm
+lib/Jifty/Web/Form/Field.pm
+lib/Jifty/Web/Form/Field/Button.pm
+lib/Jifty/Web/Form/Field/Checkbox.pm
+lib/Jifty/Web/Form/Field/Combobox.pm
+lib/Jifty/Web/Form/Field/Date.pm
+lib/Jifty/Web/Form/Field/Hidden.pm
+lib/Jifty/Web/Form/Field/InlineButton.pm
+lib/Jifty/Web/Form/Field/Password.pm
+lib/Jifty/Web/Form/Field/Radio.pm
+lib/Jifty/Web/Form/Field/ResetButton.pm
+lib/Jifty/Web/Form/Field/Select.pm
+lib/Jifty/Web/Form/Field/Text.pm
+lib/Jifty/Web/Form/Field/Textarea.pm
+lib/Jifty/Web/Form/Field/Unrendered.pm
+lib/Jifty/Web/Form/Field/Upload.pm
+lib/Jifty/Web/Form/Link.pm
+lib/Jifty/Web/Menu.pm
+lib/Jifty/Web/PageRegion.pm
+lib/Jifty/Web/Session.pm
+lib/Jifty/Web/Session/ClientSide.pm
+lib/Jifty/YAML.pm
+Makefile.PL
+MANIFEST			This list of files
+MANIFEST.SKIP
+META.yml
+plugins/AuthCASLogin/debian/changelog
+plugins/AuthCASLogin/debian/compat
+plugins/AuthCASLogin/debian/control
+plugins/AuthCASLogin/debian/copyright
+plugins/AuthCASLogin/debian/files
+plugins/AuthCASLogin/debian/rules
+plugins/AuthCASLogin/lib/Jifty/Plugin/AuthCASLogin.pm
+plugins/AuthCASLogin/lib/Jifty/Plugin/AuthCASLogin/Action/CASLogin.pm
+plugins/AuthCASLogin/lib/Jifty/Plugin/AuthCASLogin/Action/CASLogout.pm
+plugins/AuthCASLogin/lib/Jifty/Plugin/AuthCASLogin/Dispatcher.pm
+plugins/AuthCASLogin/Makefile.PL
+plugins/AuthCASLogin/MANIFEST
+plugins/AuthCASLogin/share/web/templates/caslogin
+plugins/AuthCASLogin/share/web/templates/caslogout
+plugins/AuthCASLogin/t/00-load.t
+plugins/AuthCASOnly/debian/changelog
+plugins/AuthCASOnly/debian/compat
+plugins/AuthCASOnly/debian/control
+plugins/AuthCASOnly/debian/copyright
+plugins/AuthCASOnly/debian/files
+plugins/AuthCASOnly/debian/rules
+plugins/AuthCASOnly/lib/Jifty/Plugin/AuthCASOnly.pm
+plugins/AuthCASOnly/lib/Jifty/Plugin/AuthCASOnly/Action/CASLogin.pm
+plugins/AuthCASOnly/lib/Jifty/Plugin/AuthCASOnly/Action/CASLogout.pm
+plugins/AuthCASOnly/lib/Jifty/Plugin/AuthCASOnly/CurrentUser.pm
+plugins/AuthCASOnly/lib/Jifty/Plugin/AuthCASOnly/Dispatcher.pm
+plugins/AuthCASOnly/lib/Jifty/Plugin/AuthCASOnly/Model/CASUser.pm
+plugins/AuthCASOnly/Makefile.PL
+plugins/AuthCASOnly/MANIFEST
+plugins/AuthCASOnly/META.yml
+plugins/AuthCASOnly/share/web/templates/caslogin
+plugins/AuthCASOnly/share/web/templates/caslogout
+plugins/AuthCASOnly/t/00-load.t
+plugins/AuthLDAPLogin/debian/changelog
+plugins/AuthLDAPLogin/debian/compat
+plugins/AuthLDAPLogin/debian/control
+plugins/AuthLDAPLogin/debian/copyright
+plugins/AuthLDAPLogin/debian/rules
+plugins/AuthLDAPLogin/lib/Jifty/Plugin/AuthLDAPLogin.pm
+plugins/AuthLDAPLogin/lib/Jifty/Plugin/AuthLDAPLogin/Action/LDAPLogin.pm
+plugins/AuthLDAPLogin/lib/Jifty/Plugin/AuthLDAPLogin/Action/LDAPLogout.pm
+plugins/AuthLDAPLogin/lib/Jifty/Plugin/AuthLDAPLogin/Dispatcher.pm
+plugins/AuthLDAPLogin/Makefile.PL
+plugins/AuthLDAPLogin/MANIFEST
+plugins/AuthLDAPLogin/share/po/en.po
+plugins/AuthLDAPLogin/share/po/fr.po
+plugins/AuthLDAPLogin/share/web/templates/ldaplogin
+plugins/AuthLDAPLogin/share/web/templates/ldaplogout
+plugins/AuthLDAPLogin/t/00-load.t
+plugins/AuthLDAPOnly/debian/changelog
+plugins/AuthLDAPOnly/debian/compat
+plugins/AuthLDAPOnly/debian/control
+plugins/AuthLDAPOnly/debian/copyright
+plugins/AuthLDAPOnly/debian/rules
+plugins/AuthLDAPOnly/lib/Jifty/Plugin/AuthLDAPOnly.pm
+plugins/AuthLDAPOnly/lib/Jifty/Plugin/AuthLDAPOnly/Action/LDAPLogin.pm
+plugins/AuthLDAPOnly/lib/Jifty/Plugin/AuthLDAPOnly/Action/LDAPLogout.pm
+plugins/AuthLDAPOnly/lib/Jifty/Plugin/AuthLDAPOnly/CurrentUser.pm
+plugins/AuthLDAPOnly/lib/Jifty/Plugin/AuthLDAPOnly/Dispatcher.pm
+plugins/AuthLDAPOnly/lib/Jifty/Plugin/AuthLDAPOnly/Model/LDAPUser.pm
+plugins/AuthLDAPOnly/Makefile.PL
+plugins/AuthLDAPOnly/MANIFEST
+plugins/AuthLDAPOnly/share/po/en.po
+plugins/AuthLDAPOnly/share/po/fr.po
+plugins/AuthLDAPOnly/share/web/templates/ldaplogin
+plugins/AuthLDAPOnly/share/web/templates/ldaplogout
+plugins/AuthLDAPOnly/t/00-load.t
+plugins/AuthzLDAP/lib/Jifty/Plugin/AuthzLDAP.pm
+plugins/AuthzLDAP/lib/Jifty/Plugin/AuthzLDAP/Action/LDAPValidate.pm
+plugins/AuthzLDAP/lib/Jifty/Plugin/AuthzLDAP/Model/LDAPFilter.pm
+plugins/AuthzLDAP/Makefile.PL
+plugins/AuthzLDAP/MANIFEST
+plugins/AuthzLDAP/share/po/en.po
+plugins/AuthzLDAP/share/po/fr.po
+plugins/AuthzLDAP/share/web/templates/error/AccessDenied
+plugins/AuthzLDAP/t/00-load.t
+plugins/EditInPlace/debian/changelog
+plugins/EditInPlace/debian/compat
+plugins/EditInPlace/debian/control
+plugins/EditInPlace/debian/rules
+plugins/EditInPlace/inc/Module/AutoInstall.pm
+plugins/EditInPlace/inc/Module/Install.pm
+plugins/EditInPlace/inc/Module/Install/AutoInstall.pm
+plugins/EditInPlace/inc/Module/Install/Base.pm
+plugins/EditInPlace/inc/Module/Install/Can.pm
+plugins/EditInPlace/inc/Module/Install/Fetch.pm
+plugins/EditInPlace/inc/Module/Install/Include.pm
+plugins/EditInPlace/inc/Module/Install/Makefile.pm
+plugins/EditInPlace/inc/Module/Install/Makefile/Version.pm
+plugins/EditInPlace/inc/Module/Install/Metadata.pm
+plugins/EditInPlace/inc/Module/Install/Share.pm
+plugins/EditInPlace/inc/Module/Install/Win32.pm
+plugins/EditInPlace/inc/Module/Install/WriteAll.pm
+plugins/EditInPlace/lib/Jifty/Plugin/EditInPlace.pm
+plugins/EditInPlace/lib/Jifty/Plugin/EditInPlace/Action/FileEditor.pm
+plugins/EditInPlace/lib/Jifty/Plugin/EditInPlace/Dispatcher.pm
+plugins/EditInPlace/Makefile.PL
+plugins/EditInPlace/share/web/templates/__jifty/create_file_inline
+plugins/EditInPlace/share/web/templates/__jifty/edit_file
+plugins/EditInPlace/share/web/templates/__jifty/edit_file_inline
+plugins/EmailErrors/doc/site_config.yml
+plugins/EmailErrors/lib/Jifty/Plugin/EmailErrors.pm
+plugins/EmailErrors/lib/Jifty/Plugin/EmailErrors/Dispatcher.pm
+plugins/EmailErrors/lib/Jifty/Plugin/EmailErrors/Notification/EmailError.pm
+plugins/EmailErrors/Makefile.PL
+plugins/EmailErrors/share/web/templates/.file
+plugins/LetMe/lib/Jifty/Plugin/LetMe.pm
+plugins/LetMe/lib/Jifty/Plugin/LetMe/Dispatcher.pm
+plugins/LetMe/Makefile.PL
+plugins/Login/debian/changelog
+plugins/Login/debian/compat
+plugins/Login/debian/control
+plugins/Login/debian/rules
+plugins/Login/inc/Module/Install.pm
+plugins/Login/inc/Module/Install/Base.pm
+plugins/Login/inc/Module/Install/Can.pm
+plugins/Login/inc/Module/Install/Fetch.pm
+plugins/Login/inc/Module/Install/Makefile.pm
+plugins/Login/inc/Module/Install/Metadata.pm
+plugins/Login/inc/Module/Install/Share.pm
+plugins/Login/inc/Module/Install/Win32.pm
+plugins/Login/inc/Module/Install/WriteAll.pm
+plugins/Login/lib/Jifty/Plugin/Login.pm
+plugins/Login/lib/Jifty/Plugin/Login/Action/ChangePassword.pm
+plugins/Login/lib/Jifty/Plugin/Login/Action/ConfirmEmail.pm
+plugins/Login/lib/Jifty/Plugin/Login/Action/Login.pm
+plugins/Login/lib/Jifty/Plugin/Login/Action/Logout.pm
+plugins/Login/lib/Jifty/Plugin/Login/Action/RecoverPassword.pm
+plugins/Login/lib/Jifty/Plugin/Login/Action/ResetLostPassword.pm
+plugins/Login/lib/Jifty/Plugin/Login/Action/SendAccountConfirmation.pm
+plugins/Login/lib/Jifty/Plugin/Login/Action/SendPasswordReminder.pm
+plugins/Login/lib/Jifty/Plugin/Login/Action/Signup.pm
+plugins/Login/lib/Jifty/Plugin/Login/CurrentUser.pm
+plugins/Login/lib/Jifty/Plugin/Login/Dispatcher.pm
+plugins/Login/lib/Jifty/Plugin/Login/Model/User.pm
+plugins/Login/lib/Jifty/Plugin/Login/Notification/ConfirmAddress.pm
+plugins/Login/lib/Jifty/Plugin/Login/Notification/ConfirmLostPassword.pm
+plugins/Login/Makefile.PL
+plugins/Login/MANIFEST
+plugins/Login/META.yml
+plugins/Login/share/po/en.po
+plugins/Login/share/po/fr.po
+plugins/Login/share/web/templates/chgpasswd
+plugins/Login/share/web/templates/let/confirm_email
+plugins/Login/share/web/templates/let/reset_lost_password
+plugins/Login/share/web/templates/login
+plugins/Login/share/web/templates/passwordreminder
+plugins/Login/share/web/templates/signup
+plugins/Nothing/lib/Jifty/Plugin/Nothing.pm
+plugins/Nothing/lib/Jifty/Plugin/Nothing/Dispatcher.pm
+plugins/Nothing/Makefile.PL
+plugins/ProfileBehaviour/lib/Jifty/Plugin/ProfileBehaviour.pm
+plugins/ProfileBehaviour/lib/Jifty/Plugin/ProfileBehaviour/Dispatcher.pm
+plugins/ProfileBehaviour/Makefile.PL
+plugins/ProfileBehaviour/share/web/static/css/behaviour-profile.css
+plugins/ProfileBehaviour/share/web/static/js/behaviour.js
+README
+share/dtd/xhtml-lat1.ent
+share/dtd/xhtml-special.ent
+share/dtd/xhtml-symbol.ent
+share/dtd/xhtml1-strict.dtd
+share/po/en.po
+share/po/fr.po
+share/po/ja.po
+share/po/zh_cn.po
+share/po/zh_tw.po
+share/web/static/css/app-base.css
+share/web/static/css/app.css
+share/web/static/css/autocomplete.css
+share/web/static/css/autohandler
+share/web/static/css/base.css
+share/web/static/css/calendar.css
+share/web/static/css/combobox.css
+share/web/static/css/context-menus.css
+share/web/static/css/forms.css
+share/web/static/css/halos.css
+share/web/static/css/keybindings.css
+share/web/static/css/main.css
+share/web/static/css/nav.css
+share/web/static/css/notices.css
+share/web/static/css/yui/calendar/calendar.css
+share/web/static/css/yui/tabview/border_tabs.css
+share/web/static/css/yui/tabview/tabs.css
+share/web/static/favicon.ico
+share/web/static/images/css/bullet_arrow_down.png
+share/web/static/images/css/bullet_arrow_up.png
+share/web/static/images/css/fieldbg-autocomplete.gif
+share/web/static/images/css/fieldbg.gif
+share/web/static/images/pony.jpg
+share/web/static/images/silk/bullet_arrow_down.png
+share/web/static/images/silk/bullet_arrow_up.png
+share/web/static/images/silk/calendar.png
+share/web/static/images/silk/cancel.png
+share/web/static/images/silk/cancel_grey.png
+share/web/static/images/silk/error.png
+share/web/static/images/silk/information.png
+share/web/static/images/silk/pencil.png
+share/web/static/images/silk/pencil_add.png
+share/web/static/images/yui/us/my/bn/x_d.gif
+share/web/static/images/yui/us/tr/callt.gif
+share/web/static/images/yui/us/tr/calrt.gif
+share/web/static/js/app.js
+share/web/static/js/app_behaviour.js
+share/web/static/js/behaviour.js
+share/web/static/js/bps_util.js
+share/web/static/js/calendar.js
+share/web/static/js/combobox.js
+share/web/static/js/context_menu.js
+share/web/static/js/css_browser_selector.js
+share/web/static/js/cssquery/cssQuery-level2.js
+share/web/static/js/cssquery/cssQuery-level3.js
+share/web/static/js/cssquery/cssQuery-standard.js
+share/web/static/js/cssquery/cssQuery.js
+share/web/static/js/dom-drag.js
+share/web/static/js/formatDate.js
+share/web/static/js/halo.js
+share/web/static/js/jifty.js
+share/web/static/js/jifty_smoothscroll.js
+share/web/static/js/jifty_subs.js
+share/web/static/js/jifty_utils.js
+share/web/static/js/jsan/DOM/Events.js
+share/web/static/js/jsan/JSAN.js
+share/web/static/js/jsan/Push.js
+share/web/static/js/jsan/Upgrade.js
+share/web/static/js/jsan/Upgrade/Array/push.js
+share/web/static/js/jsan/Upgrade/Function/apply.js
+share/web/static/js/json.js
+share/web/static/js/jsTrace.js
+share/web/static/js/key_bindings.js
+share/web/static/js/prototype.js
+share/web/static/js/rico.js
+share/web/static/js/scriptaculous/builder.js
+share/web/static/js/scriptaculous/controls.js
+share/web/static/js/scriptaculous/dragdrop.js
+share/web/static/js/scriptaculous/effects.js
+share/web/static/js/scriptaculous/scriptaculous.js
+share/web/static/js/scriptaculous/slider.js
+share/web/static/js/scriptaculous/unittest.js
+share/web/static/js/setup_jsan.js
+share/web/static/js/yui/calendar.js
+share/web/static/js/yui/container.js
+share/web/static/js/yui/dom.js
+share/web/static/js/yui/event.js
+share/web/static/js/yui/tabview.js
+share/web/static/js/yui/yahoo.js
+share/web/templates/=/subs
+share/web/templates/__jifty/admin/_elements/nav
+share/web/templates/__jifty/admin/action/dhandler
+share/web/templates/__jifty/admin/autohandler
+share/web/templates/__jifty/admin/fragments/list/header
+share/web/templates/__jifty/admin/fragments/list/list
+share/web/templates/__jifty/admin/fragments/list/new_item
+share/web/templates/__jifty/admin/fragments/list/search
+share/web/templates/__jifty/admin/fragments/list/update
+share/web/templates/__jifty/admin/fragments/list/view
+share/web/templates/__jifty/admin/index.html
+share/web/templates/__jifty/admin/model/dhandler
+share/web/templates/__jifty/autocomplete.xml
+share/web/templates/__jifty/css/dhandler
+share/web/templates/__jifty/empty
+share/web/templates/__jifty/error/_elements/error_text
+share/web/templates/__jifty/error/_elements/wrapper
+share/web/templates/__jifty/error/autohandler
+share/web/templates/__jifty/error/dhandler
+share/web/templates/__jifty/error/error.css
+share/web/templates/__jifty/error/mason_internal_error
+share/web/templates/__jifty/halo
+share/web/templates/__jifty/js/dhandler
+share/web/templates/__jifty/online_docs/autohandler
+share/web/templates/__jifty/online_docs/content.html
+share/web/templates/__jifty/online_docs/index.html
+share/web/templates/__jifty/online_docs/toc.html
+share/web/templates/__jifty/validator.xml
+share/web/templates/__jifty/webservices/json
+share/web/templates/__jifty/webservices/xml
+share/web/templates/__jifty/webservices/yaml
+share/web/templates/_elements/header
+share/web/templates/_elements/keybindings
+share/web/templates/_elements/menu
+share/web/templates/_elements/nav
+share/web/templates/_elements/page_nav
+share/web/templates/_elements/sidebar
+share/web/templates/_elements/wrapper
+share/web/templates/autohandler
+share/web/templates/dhandler
+share/web/templates/helpers/calendar.html
+share/web/templates/index.html
+SIGNATURE
+t/00-load.t
+t/01-dependencies.t
+t/01-test-web.t
+t/01-version_checks.t
+t/02-connect.t
+t/03-form-protocol.t
+t/03-is_passing-no_plan.t
+t/03-is_passing.t
+t/03-test-mailbox.t
+t/04-test_file.t
+t/05-dispatcher.t
+t/06-forms.t
+t/07-limit-actions.t
+t/08-client.t
+t/09-url.t
+t/10-i18n.t
+t/11-config-files.t
+t/12-param-schema.t
+t/99-pod-coverage.t
+t/99-pod.t
+t/Continuations/bin/jifty
+t/Continuations/lib/Continuations/Action/CrossBridge.pm
+t/Continuations/lib/Continuations/Action/GetGrail.pm
+t/Continuations/lib/Continuations/Dispatcher.pm
+t/Continuations/share/web/templates/autohandler
+t/Continuations/share/web/templates/black-knight-color.html
+t/Continuations/share/web/templates/black-knight-name.html
+t/Continuations/share/web/templates/black-knight-quest.html
+t/Continuations/share/web/templates/black-knight.html
+t/Continuations/share/web/templates/help-help.html
+t/Continuations/share/web/templates/index-help.html
+t/Continuations/share/web/templates/index.html
+t/Continuations/t/00-prototype.t
+t/Continuations/t/01-raw-api.t
+t/Continuations/t/02-api.t
+t/Continuations/t/03-gc.t
+t/Continuations/t/04-before-blocks.t
+t/DateTime.t
+t/Jifty.pm
+t/lib/Jifty/SubTest.pm
+t/Mapper/bin/jifty
+t/Mapper/lib/Mapper/Action/CrossBridge.pm
+t/Mapper/lib/Mapper/Action/GetGrail.pm
+t/Mapper/share/web/templates/autohandler
+t/Mapper/share/web/templates/index.html
+t/Mapper/t/00-prototype.t
+t/Mapper/t/01-raw-api.t
+t/Mapper/t/02-api.t
+t/TestApp-Plugin-REST/bin/jifty
+t/TestApp-Plugin-REST/etc/config.yml
+t/TestApp-Plugin-REST/lib/TestApp/Plugin/REST/Action/DoSomething.pm
+t/TestApp-Plugin-REST/lib/TestApp/Plugin/REST/Dispatcher.pm
+t/TestApp-Plugin-REST/lib/TestApp/Plugin/REST/Model/Group.pm
+t/TestApp-Plugin-REST/lib/TestApp/Plugin/REST/Model/User.pm
+t/TestApp-Plugin-REST/t/00-model-User.t
+t/TestApp-Plugin-REST/t/00-prototype.t
+t/TestApp-Plugin-REST/t/01-config.t
+t/TestApp-Plugin-REST/t/02-basic-use.t
+t/TestApp/bin/jifty
+t/TestApp/lib/TestApp/Action/DoSomething.pm
+t/TestApp/lib/TestApp/Action/DoSomethingElse.pm
+t/TestApp/lib/TestApp/CurrentUser.pm
+t/TestApp/lib/TestApp/Dispatcher.pm
+t/TestApp/lib/TestApp/Model/User.pm
+t/TestApp/share/web/static/images/pony.jpg
+t/TestApp/share/web/templates/currentuser
+t/TestApp/share/web/templates/dispatch/basic
+t/TestApp/share/web/templates/dispatch/basic-show
+t/TestApp/share/web/templates/dosomethingelse
+t/TestApp/share/web/templates/editform
+t/TestApp/share/web/templates/index.html
+t/TestApp/share/web/templates/manual_redirect
+t/TestApp/share/web/templates/somedir/dhandler
+t/TestApp/t/00-model-User.t
+t/TestApp/t/00-prototype.t
+t/TestApp/t/01-config.t
+t/TestApp/t/02-dispatch.t
+t/TestApp/t/03-static.t
+t/TestApp/t/04-sessions.t
+t/TestApp/t/05-actions-before-redirect.pm
+t/TestApp/t/05-editactions-Cachable.t
+t/TestApp/t/05-editactions-Record.t
+t/TestApp/t/06-validation.t
+t/TestApp/t/07-sandboxing.t
+t/TestApp/t/08-notifications.t
+t/TestApp/t/09-redirect.t
+t/TestApp/t/10-compress.t
+t/TestApp/t/11-current_user.t
+t/TestApp/t/12-search.t
+t/TestApp/t/config-Cachable
+t/TestApp/t/config-Record
+t/TestApp/t/instance_id.t
+t/TestApp/t/regex_meta_in_path_info.t

Added: jifty/branches/schema-plugins/MANIFEST.SKIP
==============================================================================
--- (empty file)
+++ jifty/branches/schema-plugins/MANIFEST.SKIP	Mon Jan 29 21:05:02 2007
@@ -0,0 +1,31 @@
+\.ppd$
+\bCVS\b
+\b.svn\b
+~$
+t/lib/File/
+t/Big-Dummy
+t/Problem-Module
+.gz$
+.bak$
+Makefile$
+MANIFEST.perl$
+\.old$
+merge_bleadperl$
+^blib/
+^pm_to_blib
+.DS_Store
+\#
+^bleadperl\.patch$
+.*.swp
+var/*
+t/*/var/*
+doc/talks/*
+^\.
+/\._
+t/mailbox$
+jiftyapptest$
+\.orig$
+\.rej$
+\.tmp$
+\.diff$
+blib

Added: jifty/branches/schema-plugins/META.yml
==============================================================================
--- (empty file)
+++ jifty/branches/schema-plugins/META.yml	Mon Jan 29 21:05:02 2007
@@ -0,0 +1,103 @@
+build_requires: 
+  ExtUtils::MakeMaker: 6.11
+distribution_type: module
+generated_by: Module::Install version 0.640
+license: Perl
+name: Jifty
+no_index: 
+  directory: 
+    - share
+    - t
+    - doc
+    - inc
+    - t
+  package: 
+    - DB
+    - inc
+recommends: 
+  Class::Accessor::Named: 0
+  DBD::SQLite: 0
+  Devel::Cover: 0
+  Module::CoreList: 0
+  Module::Install::Admin: 0.50
+  Module::Refresh: 0.09
+  PAR::Dist::FromCPAN: 0
+  Test::Base: 0.44
+  Test::HTML::Lint: 0
+  Test::HTTP::Server::Simple: 0.02
+  Test::MockModule: 0.05
+  Test::MockObject: 1.07
+  Test::More: 0.62
+  Test::Pod::Coverage: 0
+  Test::WWW::Mechanize: 1.04
+  WWW::Mechanize: 1.12
+requires: 
+  App::CLI: 0.03
+  CGI: 3.19
+  CGI::Cookie::Splitter: 0
+  CSS::Squish: 0.05
+  Cache::Cache: 0
+  Calendar::Simple: 0
+  Class::Accessor: 0
+  Class::Container: 0
+  Class::Data::Inheritable: 0
+  Compress::Zlib: 0
+  Crypt::CBC: 0
+  Crypt::Rijndael: 0
+  DBD::SQLite: 1.11
+  Data::Page: 0
+  Data::UUID: 0
+  Date::Manip: 0
+  DateTime: 0
+  Email::Folder: 0
+  Email::LocalDelivery: 0
+  Email::MIME: 0
+  Email::MIME::ContentType: 0
+  Email::MIME::Creator: 0
+  Email::Send: 1.99_01
+  Email::Simple: 0
+  Email::Simple::Creator: 0
+  Exporter::Lite: 0
+  File::Find::Rule: 0
+  File::MMagic: 0
+  File::ShareDir: 0.04
+  HTML::Entities: 0
+  HTML::Lint: 0
+  HTML::Mason: 1.3101
+  HTML::Mason::Plugin: 0
+  HTTP::Cookies: 0
+  HTTP::Date: 0
+  HTTP::Server::Simple: 0.26
+  HTTP::Server::Simple::Recorder: 0
+  Hash::Merge: 0
+  Hook::LexWrap: 0
+  IPC::PubSub: 0.22
+  JSON::Syck: 0.15
+  Jifty::DBI: 0.31
+  LWP::UserAgent: 0
+  Locale::Maketext::Extract: 0.20
+  Locale::Maketext::Lexicon: 0.60
+  Log::Log4perl: 0
+  MIME::Types: 0
+  Module::CoreList: 0
+  Module::Pluggable: 3.1
+  Module::Refresh: 0
+  Module::ScanDeps: 0
+  Object::Declare: 0.13
+  Params::Validate: 0
+  Pod::Simple: 0
+  SQL::ReservedWords: 0
+  Scalar::Defer: 0.06
+  Shell::Command: 0
+  String::Koremutake: 0
+  Test::Base: 0
+  UNIVERSAL::require: 0
+  URI: 0
+  XML::Simple: 0
+  XML::Writer: 0.601
+  XML::XPath: 0
+  YAML::Syck: 0.71
+  perl: 5.8.3
+  version: 0
+tests: t/*.t t/*/t/*.t
+version: 0.70117

Added: jifty/branches/schema-plugins/Makefile.PL
==============================================================================
--- (empty file)
+++ jifty/branches/schema-plugins/Makefile.PL	Mon Jan 29 21:05:02 2007
@@ -0,0 +1,133 @@
+use inc::Module::Install 0.46;
+name('Jifty');
+license('Perl');
+requires(perl => '5.8.3');
+requires('App::CLI' => 0.03 ); # App::CLI::Command::Help App::CLI::Command
+requires('Cache::Cache'); #Cache::FileCache
+requires('Calendar::Simple');
+requires('Class::Accessor'); # Class::Accessor::Fast
+requires('Class::Container');
+requires('Class::Data::Inheritable');
+requires('CGI' => '3.19');
+requires('CGI::Cookie::Splitter');
+requires('Crypt::CBC');
+requires('Crypt::Rijndael');
+requires('Compress::Zlib');
+requires('CSS::Squish' => 0.05 );
+requires('DBD::SQLite' => 1.11 );
+requires('Data::Page');
+requires('Data::UUID');
+requires('DateTime');
+requires('Date::Manip');
+requires('Email::Folder');
+requires('Email::LocalDelivery');
+requires('Email::MIME');
+requires('Email::MIME::Creator');
+requires('Email::MIME::ContentType');
+requires('Email::Send' => '1.99_01'); # Email::Send::Jifty::Test
+requires('Email::Simple');
+requires('Email::Simple::Creator');
+requires('Exporter::Lite');
+requires('File::Find::Rule');
+requires('File::MMagic');
+requires('File::ShareDir' => '0.04');
+requires('HTML::Entities');
+requires('HTML::Lint');
+requires('HTML::Mason' => 1.3101);           # HTML::Mason::Exceptions HTML::Mason::FakeApache HTML::Mason::MethodMaker HTML::Mason::Request HTML::Mason::Utils
+requires('HTML::Mason::Plugin');
+requires('HTTP::Cookies');
+requires('HTTP::Date');
+requires('HTTP::Server::Simple' => '0.26');  # HTTP::Server::Simple::CGI
+requires('HTTP::Server::Simple::Recorder');
+requires('Hash::Merge');
+requires('Hook::LexWrap');
+requires('IPC::PubSub' => '0.22' );
+requires('Jifty::DBI' => '0.31' );            # Jifty::DBI::Collection Jifty::DBI::Handle Jifty::DBI::Record::Cachable Jifty::DBI::SchemaGenerator
+requires('Locale::Maketext::Extract' => '0.20');
+requires('Locale::Maketext::Lexicon' => '0.60');
+requires('Log::Log4perl');
+requires('LWP::UserAgent'); # Net::HTTP
+requires('MIME::Types');
+requires('Module::Pluggable' => '3.1'); # Module::Pluggable::Object
+requires('Module::Pluggable::Object');
+requires('Module::CoreList');
+requires('Module::Refresh');
+requires('Module::ScanDeps');
+requires('Object::Declare' => '0.13');
+requires('Params::Validate');
+requires('Scalar::Defer' => '0.06');
+requires('Shell::Command');
+requires('String::Koremutake');
+requires('SQL::ReservedWords');
+requires('Test::Base');
+requires('UNIVERSAL::require');
+requires('URI');
+requires('XML::Writer' => '0.601');
+requires('XML::Simple');
+requires('XML::XPath');
+requires('version');
+
+if (can_cc()) {
+    # Always require the Syck bindings if a C compiler is available
+    requires('YAML::Syck' => 0.71);
+    requires('JSON::Syck' => 0.15);
+}
+else {
+    requires('YAML' => 0.35) unless can_use('YAML::Syck' => 0.71);
+    requires('JSON' => 0.01) unless can_use('JSON::Syck' => 0.15);
+}
+
+features(
+    'Administrative Interface (web)' => [ 
+        -default => 1,
+       requires( 'Pod::Simple') # Pod::Simple::Text Pod::Simple::HTML
+   ],
+    'Development of a jifty application' => [
+        -default => 1,
+        recommends('DBD::SQLite' => 1.11 ),
+        recommends('Test::Base' => 0.44 ),            # Test::Base::Filter
+        recommends('Module::Install::Admin' => '0.50'),
+        ($^O ne 'MSWin32' ? recommends('Test::HTTP::Server::Simple' => '0.02' ) : ()),
+        recommends('Test::HTML::Lint'),
+        recommends('Test::More' => 0.62 ),
+        recommends('Test::MockModule' => '0.05'),
+        recommends('Test::MockObject' => '1.07'),
+        recommends('Test::Pod::Coverage'),
+        recommends('Test::WWW::Mechanize' => 1.04 ),
+        recommends('WWW::Mechanize' => 1.12 ),
+        recommends('Module::Refresh' => '0.09')
+    ],
+    'Development of the jifty framework' => [
+        -default => 0,
+        recommends('DBD::SQLite'),
+        recommends('Class::Accessor::Named'),
+        recommends('Devel::Cover'),
+        recommends('Module::CoreList'),
+        recommends('Module::Install::Admin' => '0.50')
+     ],
+    'Experimental features' => [
+        -default => 0,
+        recommends('PAR::Dist::FromCPAN'),
+    ],
+);
+
+
+no_index directory => 'share';
+no_index directory => 't';
+no_index package => 'DB';
+no_index package => 'inc';
+no_index directory => 'doc';
+
+version_from('lib/Jifty.pm');
+#&auto_bundle_deps();
+&auto_install();
+#&auto_include_dependent_dists();
+
+install_script('bin/jifty');
+install_share;
+
+# Test all of our sub-dist tests too
+tests('t/*.t t/*/t/*.t');
+
+WriteAll;
+

Added: jifty/branches/schema-plugins/README
==============================================================================
--- (empty file)
+++ jifty/branches/schema-plugins/README	Mon Jan 29 21:05:02 2007
@@ -0,0 +1,79 @@
+NAME
+    Jifty -- Just Do It
+
+DESCRIPTION
+    Yet another web framework.
+
+  What's cool about Jifty? (Buzzwords)
+    DRY (Don't Repeat Yourself)
+        Jifty tries not to make you say things more than once.
+
+    Full-stack
+        Out of the proverbial box, Jifty comes with one way to do everything
+        you should need to do: One database mapper, one templating system,
+        one web services layer, one AJAX toolkit, one set of handlers for
+        standalone or FastCGI servers. We work hard to make all the bits
+        play well together, so you don't have to.
+
+    Continuations
+        With Jifty, it's easy to let the user go off and do something else,
+        like fill out a wizard, look something up in the help system or go
+        twiddle their preferences and come right back to where they were.
+
+    Form-based dispatch
+        This is one of the things that Jifty does that we've not seen
+        anywhere else. Jifty owns your form rendering and processing. This
+        means you never need to write form handling logic. All you say is "I
+        want an input for this argument here" and Jifty takes care of the
+        rest. (Even autocomplete and validation)
+
+    A Pony
+        Jifty is the only web application framework that comes with a pony.
+
+  Introduction
+    If this is your first time using Jifty, Jifty::Manual::Tutorial is
+    probably a better place to start.
+
+METHODS
+  new PARAMHASH
+    This class method instantiates a new "Jifty" object. This object deals
+    with configuration files, logging and database handles for the system.
+    Most of the time, the server will call this for you to set up your
+    "Jifty" object. If you are writing command-line programs htat want to
+    use your libraries (as opposed to web services) you will need to call
+    this yourself.
+
+    See Jifty::Config for details on how to configure your Jifty
+    application.
+
+   Arguments
+    no_handle
+        If this is set to true, Jifty will not create a Jifty::Handle and
+        connect to a database. Only use this if you're about to drop the
+        database or do something extreme like that; most of Jifty expects
+        the handle to exist. Defaults to false.
+
+  config
+    An accessor for the Jifty::Config object that stores the configuration
+    for the Jifty application.
+
+  logger
+    An accessor for our Jifty::Logger object for the application.
+
+  handle
+    An accessor for the Jifty::Handle object that stores the database handle
+    for the application.
+
+  web
+    An accessor for the Jifty::Web object that the web interface uses.
+
+LICENSE
+    Jifty is Copyright 2005 Best Practical Solutions, LLC. Jifty is
+    distributed under the same terms as Perl itself.
+
+SEE ALSO
+    <http://jifty.org>
+
+AUTHORS
+    Jesse Vincent, Alex Vandiver and David Glasser.
+

Added: jifty/branches/schema-plugins/SIGNATURE
==============================================================================
--- (empty file)
+++ jifty/branches/schema-plugins/SIGNATURE	Mon Jan 29 21:05:02 2007
@@ -0,0 +1,610 @@
+This file contains message digests of all files listed in MANIFEST,
+signed via the Module::Signature module, version 0.41.
+
+To verify the content in this distribution, first make sure you have
+Module::Signature installed, then type:
+
+    % cpansign -v
+
+It would check each file's integrity, as well as the signature's
+validity.  If "==> Signature verified OK! <==" is not displayed,
+the distribution may already have been compromised, and you should
+not run its Makefile.PL or Build.PL.
+
+-----BEGIN PGP SIGNED MESSAGE-----
+Hash: SHA1
+
+SHA1 ef933bd94b1e449d781c19e74a92412f08e602c5 AUTHORS
+SHA1 fc571a41cf0774f0099bd365a6e21607a2da0151 Changelog
+SHA1 8c31edaf5f07a1bae38d787bbdf2d79bb17d6f7c MANIFEST
+SHA1 d4adbf5948041cd460da5cb7ad21394a790e2022 MANIFEST.SKIP
+SHA1 f7177c83690e1bac7930f31b96c991afb6adbc8b META.yml
+SHA1 767b1c8e6573516120842aabb2033fddab178d39 Makefile.PL
+SHA1 e395a2eabaf8faf8266dedc664c1eb52c6c589cf README
+SHA1 aaf8f7a1025fc97077072672f325e2a5f3c03a41 bin/build_par
+SHA1 f7f44f9a7337def0c97f981073e3ed970851d9ae bin/jifty
+SHA1 bc5d0dc181bffe0694e5282c2d2336eaec5a06ff bin/runcover
+SHA1 9a91a81e3db1a12368153fed9e504aad492cd971 bin/service
+SHA1 543a2677f66d3c8ca671b790509b6c1721ac6270 bin/xgettext
+SHA1 1c042485ba8a21f0f124dd8ed412d43d3805430e debian/README
+SHA1 43b4786695f70ebd8ee74aac9e7eb270b4641b63 debian/changelog
+SHA1 5d9474c0309b7ca09a182d888f73b37a8fe1362c debian/compat
+SHA1 73f845d1185d0d977dd5bea3f046a0ae53451363 debian/control
+SHA1 8fc130ffa6d53c47d94eab1616887c511d54d61f debian/rules
+SHA1 b8bb315ef8fbdd2f069b6339ad0461b5d933d7da doc/ajax-upgraded-links
+SHA1 a0d03921821ca39ea461f1f9fa812fdbb5f501a0 doc/building_a_par
+SHA1 20e10cd0ef04ed61f2c6975caaf70f6cdfd0f657 doc/client_side_continuations
+SHA1 a78a22aa4be910be14347278720e196137819d55 doc/command_naming
+SHA1 9c56b756b1383ad76b48c2149f64c323f35d5050 doc/declarative-test-design
+SHA1 69cafeee7cc90aabb0ae8cf1e9c695794a54c9a6 doc/edit-in-place
+SHA1 fa5b3f272228531a255c7c676d798e3162c68ce0 doc/examples/CounterDemo/Makefile.PL
+SHA1 af23c4b1688a4ad7167173083381cea744d57691 doc/examples/CounterDemo/bin/jifty
+SHA1 d1b66f68f17cc67957c534e1e493c5a0f5b22556 doc/examples/CounterDemo/etc/config.yml
+SHA1 61b3c250cbb86dd5f1e5f42e82020e3e3befaff1 doc/examples/CounterDemo/share/web/templates/index.html
+SHA1 514c712a4e0bd5a16b71c35ab9e607a7db865a67 doc/examples/CounterDemo/t/00-counter-test.t
+SHA1 0eab037e835b3d998df54883377b58802cb78f7a doc/jifty-action-record-search
+SHA1 4f01bbe985a1ad3742b48563992bdbf032a6ce4d doc/jifty-dispatcher.graffle
+SHA1 b07f1666f9da714a9007058ea74d0d4cfa31ebfe doc/jifty-dispatcher.svg
+SHA1 29514abbc940365a861d196d8b1f35ee34f91526 doc/jifty-plugins-2.0
+SHA1 94a787c12228136c7797f81fef39e9bb52786067 doc/jifty-web-form-etc
+SHA1 44839f806443cbb6469f3610f9a6c488d1777f60 doc/packaging
+SHA1 3ec038720e82a1297a3a5db6a0e1b24fe0aa13c2 doc/plugin-requirements
+SHA1 3de2d7f062e78fc8b543f6b93e79852274c6c657 doc/plugin-syntax
+SHA1 c83d2b6f9d5638d1e2abdb56bf7dd4bb549baa65 doc/plugins-restated-assumptions
+SHA1 8616376196cac3c0a3f2edfe2b5a64c2c7799b96 doc/pubsub/backend_message_types
+SHA1 0c128fd9b43899c4445f10d274d0426663bbb4b5 doc/pubsub/subscriptions
+SHA1 7fd8530361a16c75b66a0f2e5cd4f6b4f269a6f0 doc/pubsub/system_architecture.graffle
+SHA1 59e165b4f4b81b5a8ce637ccc7a7d0fb0866f59c doc/pubsub/system_architecture.png
+SHA1 ec93d8fb7af302ae550d122564812e85d7308b22 etc/config.yml
+SHA1 9db8566a4bacf0f3be943b9b3a84c45439c45337 etc/site_config.yml
+SHA1 3d3cce325969be4618e89c976aa9f950618ff39a examples/Chat/Makefile.PL
+SHA1 a7dc1f376cac630ea28d2965e561469deb951cc7 examples/Chat/bin/jifty
+SHA1 418a81711645390f06a417a0e4328901c9c92dc4 examples/Chat/etc/config.yml
+SHA1 08043c294b69d1a2e23940346034283e6f686e14 examples/Chat/lib/Chat/Action/Send.pm
+SHA1 63f552215f7ed2d75278509fab4324dddda90591 examples/Chat/lib/Chat/Event/Message.pm
+SHA1 a8c6b5a40ec985c240db0cfc56922d534b9dd60d examples/Chat/lib/Chat/Server.pm
+SHA1 f6f5a7db0d950b19cb3a0e2f0776ac4fc0186082 examples/Chat/share/web/templates/fragments/message
+SHA1 ceb9ecbd5ba19436ff3cfe423e688bcc0d4b1adc examples/Chat/share/web/templates/fragments/sender
+SHA1 047c066b5f143e1a80056fa158e172448ee912e5 examples/Chat/share/web/templates/index.html
+SHA1 cea50b3afbb46ef7ac3f06c38650f98836799668 examples/Chat/t/00compile.t
+SHA1 3ea590f5bdf90c3b5ec31e0d59345801e34a61b0 examples/Chat/t/01startup.t
+SHA1 3d3cce325969be4618e89c976aa9f950618ff39a examples/Clock/Makefile.PL
+SHA1 a7dc1f376cac630ea28d2965e561469deb951cc7 examples/Clock/bin/jifty
+SHA1 faca2e649d4d9b4b00f5f6bf8932a7610c698415 examples/Clock/clockserv.pl
+SHA1 793ef4d540d2df071daad4ad73514c75d8e9aa51 examples/Clock/etc/config.yml
+SHA1 72feb5e40abfac4e87793b427f9de45c03cfaca4 examples/Clock/lib/Clock/Event/Tick.pm
+SHA1 c2e597a83448804e04989db290404766180033ab examples/Clock/lib/Clock/Server.pm
+SHA1 e70cea658fbef26cdeb5558b89dd9c6890fbd9db examples/Clock/share/web/templates/fragments/time
+SHA1 bddc300d6e81f578c85a8807156822d682c61efe examples/Clock/share/web/templates/index.html
+SHA1 4db882e66864fa40a6532ce5b83699839804b062 examples/MyWeblog/Makefile.PL
+SHA1 a7dc1f376cac630ea28d2965e561469deb951cc7 examples/MyWeblog/bin/jifty
+SHA1 d1394cef410a14394a05e2a6e6a9b32c059cb5d6 examples/MyWeblog/etc/config.yml
+SHA1 df2d54b2520dc8bb7aa1c16d7b5e6e7efcb2de1e examples/MyWeblog/lib/MyWeblog/Model/Post.pm
+SHA1 31c9e2fb12f92ea7a1444ebde93680bcdd441d65 examples/MyWeblog/share/web/templates/_elements/nav
+SHA1 3d2b9750da1277747e5f7a67c587f950245ec12c examples/MyWeblog/share/web/templates/fragments/page_of_posts
+SHA1 e22357ab6d96f44152e83060e34e954f497b413a examples/MyWeblog/share/web/templates/index.html
+SHA1 dc34445c1c7bab11cc129cf10597469f179002ff examples/MyWeblog/share/web/templates/post
+SHA1 242c000d466ce6782ac759b7baea86c3b4c902bd examples/MyWeblog/t/00-model-Post.t
+SHA1 37ff983ec74bee20ce6a6425e2cbd2effa55e586 examples/Ping/Makefile.PL
+SHA1 a7dc1f376cac630ea28d2965e561469deb951cc7 examples/Ping/bin/jifty
+SHA1 2630087e4914b7d8a7fa8bea82e778fab51735dd examples/Ping/etc/config.yml
+SHA1 9b143bab7499c4ebde34e88e635a59bd205a1bf0 examples/Ping/lib/Ping/Action/AddPing.pm
+SHA1 fc630086e84277cf19a9e9eb382c79e41d0dd810 examples/Ping/lib/Ping/Action/CancelPing.pm
+SHA1 918d401c046480483ca935728529e016de6d73f6 examples/Ping/lib/Ping/Event/Pong.pm
+SHA1 ba3f1840a56742c011e96890a327ccbe7ecb3a4d examples/Ping/lib/Ping/PingServer.pm
+SHA1 85e03a9df32331e713be7d637c04fa3ca1a24626 examples/Ping/lib/Ping/Server.pm
+SHA1 dc0966379ee2dc74c10ee8d5688cec5b1db17ac4 examples/Ping/share/web/templates/fragments/pong
+SHA1 05ac283a14e76750d63678d0864a0403aa18fd28 examples/Ping/share/web/templates/index.html
+SHA1 53c8822ddf426e82fe239e4470574913411b1355 examples/Ping/t/00compile.t
+SHA1 6d6c378447f9d74d53c06a2a027736b48b5d0670 examples/Ping/t/01startup.t
+SHA1 603bb9de29fb8cba7f13409c546750972eff645d inc/Module/AutoInstall.pm
+SHA1 9b2f9d83bcf77860f53a0c07c90a4a59ad9f5df1 inc/Module/Install.pm
+SHA1 ad955f51ad2c40d4ba35395c27f5ed899a80bf7a inc/Module/Install/AutoInstall.pm
+SHA1 abe32855d75ab13747cf65765af9947b7a8c3057 inc/Module/Install/Base.pm
+SHA1 95b81d1e91bd634467bf633571eff4420e9c04eb inc/Module/Install/Can.pm
+SHA1 1fe98c63cf9d7271c8cb4183ba230f152df69e26 inc/Module/Install/Fetch.pm
+SHA1 0606a8b02a420600bc3e2b65ab82f70266784926 inc/Module/Install/Include.pm
+SHA1 2249171a2b72cd73ff2c0a06597d29f86e5df456 inc/Module/Install/Makefile.pm
+SHA1 381bb98ea3877bba49ae85e7a7ea130645fd3dbf inc/Module/Install/Metadata.pm
+SHA1 b384bd42bc6263dc56d04a884ef4e5fe340049f8 inc/Module/Install/Scripts.pm
+SHA1 fcae3a3bda09e6ba955c8746c2bdf582a23b8d56 inc/Module/Install/Share.pm
+SHA1 0c2118868ef82ac517eb6d9c3bd93e6eb9bbf83e inc/Module/Install/Win32.pm
+SHA1 e827d6d43771032fa3df35c0ad5e5698d0e54cda inc/Module/Install/WriteAll.pm
+SHA1 c17e8f3cf8ebe1eb4929fd2bd2fd530a9de1abd0 lib/Email/Send/Jifty/Test.pm
+SHA1 9380a1872911cf469d08049e4c76645eecef63f8 lib/Jifty.pm
+SHA1 f2db715c8a15d0c7c5c7cf30511dac6547f72fc5 lib/Jifty/API.pm
+SHA1 25ed41c1b89c6d39a8e6d027a9120b3e35785951 lib/Jifty/Action.pm
+SHA1 a6d9d87b4fa06cfab36f249a67946b45669dcee7 lib/Jifty/Action/Autocomplete.pm
+SHA1 19147544734762a243ba7e8b603168930aad9c62 lib/Jifty/Action/Record.pm
+SHA1 39d9bca03c6502e128b453fe3bda5e1d4173f343 lib/Jifty/Action/Record/Create.pm
+SHA1 224f3ed1a4710fb13e4627acd22067e2fa5c35c6 lib/Jifty/Action/Record/Delete.pm
+SHA1 1e400299405a06d3d09bb7548d97c52b850b7f43 lib/Jifty/Action/Record/Search.pm
+SHA1 821d06cdd92876efd01e08800eae46e52e13c2a6 lib/Jifty/Action/Record/Update.pm
+SHA1 ab7a0e0bae4cd1ecbda260b339a4116e65708a7f lib/Jifty/Action/Redirect.pm
+SHA1 cf349fcfe9ee28216eae2213ab0016ceaffaf2a7 lib/Jifty/Bootstrap.pm
+SHA1 f6e9cb12da25b65df8bc2762423d1fcc9d41ec3e lib/Jifty/ClassLoader.pm
+SHA1 1009fa942a8cf3da853694f321d6f67d70613a79 lib/Jifty/Client.pm
+SHA1 a4e91b327848fe1c5b76e4ffaa926300e4c1ef2f lib/Jifty/Collection.pm
+SHA1 ce2f398600582262a2f5562a1de77bc03f6e2676 lib/Jifty/Config.pm
+SHA1 48514a496198c022aff7e4d1c578824addda7c91 lib/Jifty/Continuation.pm
+SHA1 15970f85b57eab885568a71f164dc627c791287c lib/Jifty/CurrentUser.pm
+SHA1 4521a0e9a145697c836e2247fbdb4e93b8966366 lib/Jifty/DateTime.pm
+SHA1 9595652e061d4066615b1ac811700da46394ea65 lib/Jifty/Dispatcher.pm
+SHA1 c9c904906c35def343f14c0c216b62771c07f842 lib/Jifty/Event.pm
+SHA1 fb9f33e2838fbff0cd5b5a784adee8b0fc347ebc lib/Jifty/Event/Model.pm
+SHA1 5a6b765e4e61e1a098cc997127c9a5e9405ea32d lib/Jifty/Everything.pm
+SHA1 818bd0aa6afeb39bf96e0068fe3222c74133b4d8 lib/Jifty/Filter/DateTime.pm
+SHA1 8f83cbce4937acba8d2f5c944d3d3a95a0156d9c lib/Jifty/Handle.pm
+SHA1 0c5f2e31fc9cdd266ff3c10bc3ff6715a3b77c9d lib/Jifty/Handler.pm
+SHA1 89fb4f3164b4ea84eb8084829bbca9e93d2259b1 lib/Jifty/I18N.pm
+SHA1 7ce311e2005ef0df27d71b1d80a4f05237dda9f4 lib/Jifty/JSON.pm
+SHA1 3af93349fe8a236c714d88367077f88af11f5d32 lib/Jifty/LetMe.pm
+SHA1 f76b940651eb2c53bce0af9be451a24b0358fec9 lib/Jifty/Logger.pm
+SHA1 858723b0874be436d44be113934f182eff7e9388 lib/Jifty/Manual/AccessControl.pod
+SHA1 ef9ff36385a9f780ac0204bffb9425818d78b789 lib/Jifty/Manual/Actions.pod
+SHA1 d320630f6613f4aa1ec3b9537129fd9ca847fb61 lib/Jifty/Manual/Continuations.pod
+SHA1 976198d6f93f9c46625c3fd1bd9d89a13ab89f40 lib/Jifty/Manual/Cookbook.pod
+SHA1 38a90072f4a25eac8d4480b00290b069e6397673 lib/Jifty/Manual/FAQ.pod
+SHA1 0f95658ca3d4ed3deb1951f514774446a583247f lib/Jifty/Manual/Glossary.pod
+SHA1 f272be20cc67acaf01c116f432a8f42d82c57877 lib/Jifty/Manual/Models.pod
+SHA1 1204d70c868084ac3114fae277e98a756f83f819 lib/Jifty/Manual/ObjectModel.pod
+SHA1 537017160a444f84bf1673cc3722db644c2b662e lib/Jifty/Manual/PageRegions.pod
+SHA1 8ba19a0760196ceb1afbeaa06e7314e254bef258 lib/Jifty/Manual/RequestHandling.pod
+SHA1 11c2a307f398203ebd804cee990a89e940c406f6 lib/Jifty/Manual/Style.pod
+SHA1 69c995fe4da233dc1b54655813cb6e51d979b759 lib/Jifty/Manual/Tutorial.pod
+SHA1 4ad61c8957fdfed1aa5cc60294cbfb43a359e2d2 lib/Jifty/Manual/Tutorial_de.pod
+SHA1 45f95f61826365d39a5eab2cc119967273d17077 lib/Jifty/Manual/Tutorial_ja.pod
+SHA1 0398a7d053b6c78f7d769f7251d3a01af80cbe57 lib/Jifty/Manual/Upgrading.pod
+SHA1 d0b7a4277c8a3d1a393d7c51fff48b059461f87c lib/Jifty/Manual/UsingCSSandJS.pod
+SHA1 59ce74460e9c1fe8aa1114c2e874348583b76548 lib/Jifty/Mason/Halo.pm
+SHA1 809ace5bafff5ad2461d5495464863ba808dfd19 lib/Jifty/Model/Metadata.pm
+SHA1 36de25464ae4eb07675f453cc590b634c6ff5a37 lib/Jifty/Model/Session.pm
+SHA1 0efcdf22d66e521cf250c1398caf3aba93ed795d lib/Jifty/Model/SessionCollection.pm
+SHA1 e24506b3e0fbdb450e55f3935980813c9c9e2bee lib/Jifty/Module/Pluggable.pm
+SHA1 f0090580d6a54fd8114b8fc1b4cb644c8c3dd2f5 lib/Jifty/Notification.pm
+SHA1 7223070583b1b15f651db7a71b97e039e084aa4f lib/Jifty/Object.pm
+SHA1 c3fde2a862013cd6284637d79c751c3c2e360720 lib/Jifty/Param.pm
+SHA1 11d4de5da85ee53e6f3f434a5a519ebc574cedab lib/Jifty/Param/Schema.pm
+SHA1 69708ae740a40953c50217c37e23740179da80be lib/Jifty/Plugin.pm
+SHA1 d80065a87ec1dd8b0bbcd1853e9a7192a18a04f5 lib/Jifty/Plugin/ClassLoader.pm
+SHA1 20d3f35b391236d9a0e554e62368b4f6fd1383dc lib/Jifty/Plugin/REST.pm
+SHA1 690d1ca831e42d1b1810875abdbae0ff480620e2 lib/Jifty/Plugin/REST/Dispatcher.pm
+SHA1 3fccef02727c8e75a0b4c93f940e9e18e0a499d4 lib/Jifty/Record.pm
+SHA1 0283384c06b36339143690b4beb7830ab4648e0f lib/Jifty/Request.pm
+SHA1 7e4d83147f5f665bb0e8d290ea70340b82a205c2 lib/Jifty/Request/Mapper.pm
+SHA1 0a92b4cdb402463e303b897195c9ad914767c27f lib/Jifty/Response.pm
+SHA1 56988d89d24e33a5ed2c2c6539b02593cc9e3344 lib/Jifty/Result.pm
+SHA1 85de033731ae63d0b3efec515a3608337cbc5c31 lib/Jifty/RightsFrom.pm
+SHA1 0306af64a6289796db4b5ff2b8c5e7c23506a9e3 lib/Jifty/Script.pm
+SHA1 a576b768487f81889ade60cb10f89eb2073adadc lib/Jifty/Script/Action.pm
+SHA1 17bb02c22e126df9ff783843e5921e46b060c2be lib/Jifty/Script/App.pm
+SHA1 1ad9937d9e28f1568954bcffac500be87f3cb355 lib/Jifty/Script/Deps.pm
+SHA1 cb42aff8740412f9e7a26915a4e852817aa39af8 lib/Jifty/Script/FastCGI.pm
+SHA1 e25a259fc9fd3183a7981236f428f54ac4c4f49e lib/Jifty/Script/Help.pm
+SHA1 be1f648841609388f48214e632e0b169216dd58a lib/Jifty/Script/Model.pm
+SHA1 77c221bb4b7162b2fc95c841ceeea04194afb264 lib/Jifty/Script/Plugin.pm
+SHA1 eba3c96bcfae42ea6a9e5d2cbef6bca19617b47e lib/Jifty/Script/Po.pm
+SHA1 afb4c37e7503e53676773bb3d6f65fde111679fc lib/Jifty/Script/Schema.pm
+SHA1 4bbe2362a6cd195fac119a37cd71119afb5516f6 lib/Jifty/Script/Server.pm
+SHA1 0646a96ca5f3da1585e3fb1dcc9b3540d2b8f50f lib/Jifty/Server.pm
+SHA1 4c51d2df15281788b74d080488b0c5959cd95a1a lib/Jifty/Subs.pm
+SHA1 43277d31da2a30afd160dbe2077314285898438f lib/Jifty/Subs/Render.pm
+SHA1 df6cadbfbd91dcbf91d334a2132882821d9b3741 lib/Jifty/Test.pm
+SHA1 24eb481ac109ce0639496d6e16311ae2af0bb0da lib/Jifty/Test/WWW/Mechanize.pm
+SHA1 bacce10076cd7790405d29b0cabd99cae06b739e lib/Jifty/TestServer.pm
+SHA1 206e12811205063b22fcaaf0cd04dd66321d793c lib/Jifty/Upgrade.pm
+SHA1 f3957ac04ad92737d68b2a63f068679b4bacafed lib/Jifty/Upgrade/Internal.pm
+SHA1 01e8cf19fef0094b917712165d5ae0acf37fa31d lib/Jifty/Util.pm
+SHA1 bf4cbc6a7c94597cadb101b609f80004bfb64eef lib/Jifty/View/Mason/Handler.pm
+SHA1 91b4185b0570453805f15b0eb0ce0f50a6f1eef3 lib/Jifty/View/Static/Handler.pm
+SHA1 1b62b886ec2a10b9b078535a7782bd01507bf6a6 lib/Jifty/Web.pm
+SHA1 93f70b329f4e05105edd6a2bacb1d71ed59c5449 lib/Jifty/Web/Form.pm
+SHA1 07cea2d1e0075a331d4f028fee34c5fd1bdda618 lib/Jifty/Web/Form/Clickable.pm
+SHA1 9065dcef2d3e755bcefbc5ec1481bf92e883c287 lib/Jifty/Web/Form/Element.pm
+SHA1 f7b910dc62f6265d4df1a8ec937d902549f1ee49 lib/Jifty/Web/Form/Field.pm
+SHA1 ba87c27d5432a8393ffeaf39323ac80c0f4facab lib/Jifty/Web/Form/Field/Button.pm
+SHA1 c1071263839a663d44d7f922c7c24b5bcc132a82 lib/Jifty/Web/Form/Field/Checkbox.pm
+SHA1 b21ef4e33a628f5d6c54adf5f47f75e69a861644 lib/Jifty/Web/Form/Field/Combobox.pm
+SHA1 cc86a97a80c6c9e22183a099979a712a3900a39a lib/Jifty/Web/Form/Field/Date.pm
+SHA1 e2db0ce71a56f59e8154a8af8187fab198c01fe7 lib/Jifty/Web/Form/Field/Hidden.pm
+SHA1 41b5344b9e5b0dcdc2c944d2cacdc18421aa8a93 lib/Jifty/Web/Form/Field/InlineButton.pm
+SHA1 db78f61b0fe36589d0f3acbf8df470f89cbc6ee9 lib/Jifty/Web/Form/Field/Password.pm
+SHA1 1006c6e4e07fbbf5ef5ccd2020cbe82ebbd8da1c lib/Jifty/Web/Form/Field/Radio.pm
+SHA1 5e6d07f48f59a7b2106a8f22ead83263368b26ad lib/Jifty/Web/Form/Field/ResetButton.pm
+SHA1 f865b1b411cf40aa3a0bf0cd51e364a0f23a4d3c lib/Jifty/Web/Form/Field/Select.pm
+SHA1 5586d4fdda6b5b8e6014750d5b912be898b18465 lib/Jifty/Web/Form/Field/Text.pm
+SHA1 bb397fc6092ddb8196342e80a4148d07fcd037b0 lib/Jifty/Web/Form/Field/Textarea.pm
+SHA1 2548412d5bfbd08050d53ab5c58e0d962d4b2448 lib/Jifty/Web/Form/Field/Unrendered.pm
+SHA1 e37541952c969f2e74f942782d483de75e9265f9 lib/Jifty/Web/Form/Field/Upload.pm
+SHA1 16cff04150ba0ae8bffe04c1c661d80972876248 lib/Jifty/Web/Form/Link.pm
+SHA1 e4baa13068c7de8e4737efa4dbc18f1f059e6047 lib/Jifty/Web/Menu.pm
+SHA1 e17189fe3d525c4fe2a251db20a5a6eabbc7c786 lib/Jifty/Web/PageRegion.pm
+SHA1 093ab860163f03e9d85c8bb366d694830b7d940a lib/Jifty/Web/Session.pm
+SHA1 f655fb9734715ebf51fb5e9b554c02b9e4e2ac61 lib/Jifty/Web/Session/ClientSide.pm
+SHA1 c4de1ef964243aae5ab90d0a5a6dd9c213eb9f80 lib/Jifty/YAML.pm
+SHA1 feeb00d6502ca54367036767f5e3f20275580291 plugins/AuthCASLogin/MANIFEST
+SHA1 f7ee4953b3c05710fe531cc9b579f65ed04af761 plugins/AuthCASLogin/Makefile.PL
+SHA1 e02920219c74449947a6c3a04c35a25ad944faf4 plugins/AuthCASLogin/debian/changelog
+SHA1 9c6b057a2b9d96a4067a749ee3b3b0158d390cf1 plugins/AuthCASLogin/debian/compat
+SHA1 bf43e4b8cb112727059c7738c762f71184fe7a1d plugins/AuthCASLogin/debian/control
+SHA1 c361200ede7340a93f131034eaaaa71f36bf1617 plugins/AuthCASLogin/debian/copyright
+SHA1 b612a9f276fb1016d242acf81406946dd146bfcf plugins/AuthCASLogin/debian/files
+SHA1 df2b684174a5e8bdf6d14b985020057702b4c884 plugins/AuthCASLogin/debian/rules
+SHA1 2481d6a02ca4959e29bed6eca04499cf808cc8a3 plugins/AuthCASLogin/lib/Jifty/Plugin/AuthCASLogin.pm
+SHA1 6a687e551737ce850bfa02c15871f462845f8f3b plugins/AuthCASLogin/lib/Jifty/Plugin/AuthCASLogin/Action/CASLogin.pm
+SHA1 44ee4a567f2fd636aac8b6a8bc6c46a898bff080 plugins/AuthCASLogin/lib/Jifty/Plugin/AuthCASLogin/Action/CASLogout.pm
+SHA1 b743661f79c8620f19275181e0458589eca4b6a7 plugins/AuthCASLogin/lib/Jifty/Plugin/AuthCASLogin/Dispatcher.pm
+SHA1 36215b6306dd37ebbf6206f526e9464d2d261d2a plugins/AuthCASLogin/share/web/templates/caslogin
+SHA1 f971aec45ba679dc55a9955077324f5c0ea75cca plugins/AuthCASLogin/share/web/templates/caslogout
+SHA1 c93e6f367c6a110cb05f8fefa4cb37881daeebe7 plugins/AuthCASLogin/t/00-load.t
+SHA1 96e2b7d839f54a14c42dd421516a267d7e2c4b94 plugins/AuthCASOnly/MANIFEST
+SHA1 62ee3ecfa8b4923ee68aa5f3179f2b3c5c8551dd plugins/AuthCASOnly/META.yml
+SHA1 9e218ee17e541c947ceb6f78d4714fc4baa43895 plugins/AuthCASOnly/Makefile.PL
+SHA1 0211277b86a7c26952a44da5ea55945a32ca2689 plugins/AuthCASOnly/debian/changelog
+SHA1 9c6b057a2b9d96a4067a749ee3b3b0158d390cf1 plugins/AuthCASOnly/debian/compat
+SHA1 df5baa3318d61d253b6256a2a3abb06aa28669a5 plugins/AuthCASOnly/debian/control
+SHA1 c361200ede7340a93f131034eaaaa71f36bf1617 plugins/AuthCASOnly/debian/copyright
+SHA1 6178f211c12057c7f8bf110ae4d9ae9961ba90c7 plugins/AuthCASOnly/debian/files
+SHA1 df2b684174a5e8bdf6d14b985020057702b4c884 plugins/AuthCASOnly/debian/rules
+SHA1 e324ade45843a878b10cc5bd78061401dcf56685 plugins/AuthCASOnly/lib/Jifty/Plugin/AuthCASOnly.pm
+SHA1 827a868f825e94c7630368d4cd98d591edacc188 plugins/AuthCASOnly/lib/Jifty/Plugin/AuthCASOnly/Action/CASLogin.pm
+SHA1 cc9279734210b6a8de3312716ee36868d437f7db plugins/AuthCASOnly/lib/Jifty/Plugin/AuthCASOnly/Action/CASLogout.pm
+SHA1 b401b903bece0f11a45c7fe129ada9e6e2681f4b plugins/AuthCASOnly/lib/Jifty/Plugin/AuthCASOnly/CurrentUser.pm
+SHA1 d0a159254cb3d99a5d3664ffd8c8d42c3daa40f1 plugins/AuthCASOnly/lib/Jifty/Plugin/AuthCASOnly/Dispatcher.pm
+SHA1 67aea2e30d74af4e01b66ef5bebb4d69d78f2b37 plugins/AuthCASOnly/lib/Jifty/Plugin/AuthCASOnly/Model/CASUser.pm
+SHA1 36215b6306dd37ebbf6206f526e9464d2d261d2a plugins/AuthCASOnly/share/web/templates/caslogin
+SHA1 f971aec45ba679dc55a9955077324f5c0ea75cca plugins/AuthCASOnly/share/web/templates/caslogout
+SHA1 de334fd98ec8b7bf6b72b9f4d98da1405f2fd9a9 plugins/AuthCASOnly/t/00-load.t
+SHA1 49e6479da4844f3e44e073c8ff055177a97b73c6 plugins/AuthLDAPLogin/MANIFEST
+SHA1 a9231ecdff2144eeecefb05318f6b0929b9b888a plugins/AuthLDAPLogin/Makefile.PL
+SHA1 3d40e1b567b7ca16f6c6bbc2110feac5e4d03030 plugins/AuthLDAPLogin/debian/changelog
+SHA1 9c6b057a2b9d96a4067a749ee3b3b0158d390cf1 plugins/AuthLDAPLogin/debian/compat
+SHA1 81d9344b39a55abe73c3bc969676f5970b851fe2 plugins/AuthLDAPLogin/debian/control
+SHA1 c361200ede7340a93f131034eaaaa71f36bf1617 plugins/AuthLDAPLogin/debian/copyright
+SHA1 df2b684174a5e8bdf6d14b985020057702b4c884 plugins/AuthLDAPLogin/debian/rules
+SHA1 9a467c6b819af40acba655cf70795c9867a31544 plugins/AuthLDAPLogin/lib/Jifty/Plugin/AuthLDAPLogin.pm
+SHA1 4f8ca81ec122164153bfeed566934cb96d3e5a5e plugins/AuthLDAPLogin/lib/Jifty/Plugin/AuthLDAPLogin/Action/LDAPLogin.pm
+SHA1 db807f73a0a665abe5f18bcbdb6587d830e1f209 plugins/AuthLDAPLogin/lib/Jifty/Plugin/AuthLDAPLogin/Action/LDAPLogout.pm
+SHA1 e69c4b3784c49e7c389d5635cf08020b7ac833be plugins/AuthLDAPLogin/lib/Jifty/Plugin/AuthLDAPLogin/Dispatcher.pm
+SHA1 bddb067764a83d2beaa4d4672486e9009b0dee4f plugins/AuthLDAPLogin/share/po/en.po
+SHA1 6046f83cca826e2ff0f43ce95b0d842ce65df37b plugins/AuthLDAPLogin/share/po/fr.po
+SHA1 a52f49740c6a0c5dfb5ef2413b26d40c71e8dba0 plugins/AuthLDAPLogin/share/web/templates/ldaplogin
+SHA1 f971aec45ba679dc55a9955077324f5c0ea75cca plugins/AuthLDAPLogin/share/web/templates/ldaplogout
+SHA1 43c8998946172ac32eeefdfbf95a663d6e60e40a plugins/AuthLDAPLogin/t/00-load.t
+SHA1 8c487e541a3d5115e8b04f35ac6555cca05de933 plugins/AuthLDAPOnly/MANIFEST
+SHA1 76658d43f96759a30895e9ab9116d3fe2ec475bf plugins/AuthLDAPOnly/Makefile.PL
+SHA1 6490648ff1114d79ba05a70e8106d5d0226d72ae plugins/AuthLDAPOnly/debian/changelog
+SHA1 9c6b057a2b9d96a4067a749ee3b3b0158d390cf1 plugins/AuthLDAPOnly/debian/compat
+SHA1 e256f776a58f8ca1de7a20082e855e03bace79d8 plugins/AuthLDAPOnly/debian/control
+SHA1 c361200ede7340a93f131034eaaaa71f36bf1617 plugins/AuthLDAPOnly/debian/copyright
+SHA1 68dfa9d87a39ca9c6480d8a93e7efb18565b4db3 plugins/AuthLDAPOnly/debian/rules
+SHA1 69f53febd6a99e6e61e5b87a387139a74f509b8d plugins/AuthLDAPOnly/lib/Jifty/Plugin/AuthLDAPOnly.pm
+SHA1 3a1a5ac6571c49fd766eba8f8fb94dbc35081192 plugins/AuthLDAPOnly/lib/Jifty/Plugin/AuthLDAPOnly/Action/LDAPLogin.pm
+SHA1 8709ec6fd348b2229eecab4778fe52b9e3f5f241 plugins/AuthLDAPOnly/lib/Jifty/Plugin/AuthLDAPOnly/Action/LDAPLogout.pm
+SHA1 5776159e43fe28077ebe66359d888620c1a78c30 plugins/AuthLDAPOnly/lib/Jifty/Plugin/AuthLDAPOnly/CurrentUser.pm
+SHA1 11063de8ce0267140e4eeacc8caa552de893d435 plugins/AuthLDAPOnly/lib/Jifty/Plugin/AuthLDAPOnly/Dispatcher.pm
+SHA1 be8d85f7423aabd9e504feb4e759d412990c4f5a plugins/AuthLDAPOnly/lib/Jifty/Plugin/AuthLDAPOnly/Model/LDAPUser.pm
+SHA1 645c578bde4a89f2a47ffbff048863a52691ad11 plugins/AuthLDAPOnly/share/po/en.po
+SHA1 42fa3dbdbfd9c34dd1260df7d70fd215aeb3d987 plugins/AuthLDAPOnly/share/po/fr.po
+SHA1 a52f49740c6a0c5dfb5ef2413b26d40c71e8dba0 plugins/AuthLDAPOnly/share/web/templates/ldaplogin
+SHA1 f971aec45ba679dc55a9955077324f5c0ea75cca plugins/AuthLDAPOnly/share/web/templates/ldaplogout
+SHA1 e6a78e0b4226f86df4d2865bef599aab18b441a5 plugins/AuthLDAPOnly/t/00-load.t
+SHA1 42c851e5906962ad1574ff20cd4284c88a7c1bac plugins/AuthzLDAP/MANIFEST
+SHA1 0086fe18fd01b6ace92636034ea606008ab5a374 plugins/AuthzLDAP/Makefile.PL
+SHA1 d9d714781bef6a0e3892f258350f9d6797eafa9a plugins/AuthzLDAP/lib/Jifty/Plugin/AuthzLDAP.pm
+SHA1 a63d50ed4f93a1d9909af9889fc30d8b3e9140a4 plugins/AuthzLDAP/lib/Jifty/Plugin/AuthzLDAP/Action/LDAPValidate.pm
+SHA1 5b391191e624c0d2e8c16f19c531a2c2993ba49e plugins/AuthzLDAP/lib/Jifty/Plugin/AuthzLDAP/Model/LDAPFilter.pm
+SHA1 dc50e07d76934884116843767a1784571accac4e plugins/AuthzLDAP/share/po/en.po
+SHA1 18be32490b494470824534cccd87b034cd790987 plugins/AuthzLDAP/share/po/fr.po
+SHA1 cd21439e1906eb58e9c576a477a8a31e05340c05 plugins/AuthzLDAP/share/web/templates/error/AccessDenied
+SHA1 289f295702910035ed2b122279ecf8b3b6a6389b plugins/AuthzLDAP/t/00-load.t
+SHA1 e8ce16205eccb1b99224ca81d3a3496163a98864 plugins/EditInPlace/Makefile.PL
+SHA1 f2d5b6fb2d7628c2dd7207a8a7fb3dab1ea2f4bf plugins/EditInPlace/debian/changelog
+SHA1 9c6b057a2b9d96a4067a749ee3b3b0158d390cf1 plugins/EditInPlace/debian/compat
+SHA1 769bf223b7f14e4c1f2074cb4c7328324d26ca19 plugins/EditInPlace/debian/control
+SHA1 df2b684174a5e8bdf6d14b985020057702b4c884 plugins/EditInPlace/debian/rules
+SHA1 603bb9de29fb8cba7f13409c546750972eff645d plugins/EditInPlace/inc/Module/AutoInstall.pm
+SHA1 9b2f9d83bcf77860f53a0c07c90a4a59ad9f5df1 plugins/EditInPlace/inc/Module/Install.pm
+SHA1 ad955f51ad2c40d4ba35395c27f5ed899a80bf7a plugins/EditInPlace/inc/Module/Install/AutoInstall.pm
+SHA1 abe32855d75ab13747cf65765af9947b7a8c3057 plugins/EditInPlace/inc/Module/Install/Base.pm
+SHA1 95b81d1e91bd634467bf633571eff4420e9c04eb plugins/EditInPlace/inc/Module/Install/Can.pm
+SHA1 1fe98c63cf9d7271c8cb4183ba230f152df69e26 plugins/EditInPlace/inc/Module/Install/Fetch.pm
+SHA1 0606a8b02a420600bc3e2b65ab82f70266784926 plugins/EditInPlace/inc/Module/Install/Include.pm
+SHA1 2249171a2b72cd73ff2c0a06597d29f86e5df456 plugins/EditInPlace/inc/Module/Install/Makefile.pm
+SHA1 c6cbbd5beff5b83ac581fed0e294fc6726c868de plugins/EditInPlace/inc/Module/Install/Makefile/Version.pm
+SHA1 381bb98ea3877bba49ae85e7a7ea130645fd3dbf plugins/EditInPlace/inc/Module/Install/Metadata.pm
+SHA1 fcae3a3bda09e6ba955c8746c2bdf582a23b8d56 plugins/EditInPlace/inc/Module/Install/Share.pm
+SHA1 0c2118868ef82ac517eb6d9c3bd93e6eb9bbf83e plugins/EditInPlace/inc/Module/Install/Win32.pm
+SHA1 e827d6d43771032fa3df35c0ad5e5698d0e54cda plugins/EditInPlace/inc/Module/Install/WriteAll.pm
+SHA1 312dfe93d52daa4c72257cf2299aee35f61b0a16 plugins/EditInPlace/lib/Jifty/Plugin/EditInPlace.pm
+SHA1 187cd200affbf8861a91d008273eb9de664a9d60 plugins/EditInPlace/lib/Jifty/Plugin/EditInPlace/Action/FileEditor.pm
+SHA1 69ff778cc486bfd14a97f7690a7706633dbc2e6b plugins/EditInPlace/lib/Jifty/Plugin/EditInPlace/Dispatcher.pm
+SHA1 6f363a3b2826ee1fb01921fefebaf99b111a1c31 plugins/EditInPlace/share/web/templates/__jifty/create_file_inline
+SHA1 dc4e60f93e56496f8010ae81888e84e3352e979f plugins/EditInPlace/share/web/templates/__jifty/edit_file
+SHA1 fea2934c144a7983dc7fb4d2a2826b0f7f6bbc1f plugins/EditInPlace/share/web/templates/__jifty/edit_file_inline
+SHA1 69352f6e1ee12026575162e559aa0ee154be3366 plugins/EmailErrors/Makefile.PL
+SHA1 ff2699ef47b63f7a185f53ffc96bcdc9d05799ec plugins/EmailErrors/doc/site_config.yml
+SHA1 a41d80d1e2c02de64581f13da37ed601e0baabee plugins/EmailErrors/lib/Jifty/Plugin/EmailErrors.pm
+SHA1 e84437393b86a21e865df9ea0d0711a75ef4928e plugins/EmailErrors/lib/Jifty/Plugin/EmailErrors/Dispatcher.pm
+SHA1 20fcd16f0baba3e0114bc73d2dca0c9da3a6405c plugins/EmailErrors/lib/Jifty/Plugin/EmailErrors/Notification/EmailError.pm
+SHA1 da39a3ee5e6b4b0d3255bfef95601890afd80709 plugins/EmailErrors/share/web/templates/.file
+SHA1 6d36892393c5848ca54991272c03460b330734d2 plugins/LetMe/Makefile.PL
+SHA1 88f5ed45b2c506fcab80f178cf4cedd23a62f365 plugins/LetMe/lib/Jifty/Plugin/LetMe.pm
+SHA1 aae4870db361c1076fd151ddd0cf2fd3f02f4813 plugins/LetMe/lib/Jifty/Plugin/LetMe/Dispatcher.pm
+SHA1 5ece7af558c3a7bc83f535e948b7a6b24372daec plugins/Login/MANIFEST
+SHA1 4439300be4c8a1b99726658ceed25674216a079e plugins/Login/META.yml
+SHA1 5d7bbe469fc6a8e0c5f303539c1d235f7c4f50a2 plugins/Login/Makefile.PL
+SHA1 4c552f502b762c8e1a12848423a36ddff99bd38b plugins/Login/debian/changelog
+SHA1 9c6b057a2b9d96a4067a749ee3b3b0158d390cf1 plugins/Login/debian/compat
+SHA1 90e2e662014841fff93a7e346908f66178dfcc07 plugins/Login/debian/control
+SHA1 df2b684174a5e8bdf6d14b985020057702b4c884 plugins/Login/debian/rules
+SHA1 017bedfcba1e0c72b36301e6ef21b8712b84d175 plugins/Login/inc/Module/Install.pm
+SHA1 b1a70869c098ba602151631386fc510b5bfd3511 plugins/Login/inc/Module/Install/Base.pm
+SHA1 dd7313db23119d49ae78593bfa576554fb5b0fd8 plugins/Login/inc/Module/Install/Can.pm
+SHA1 7c3a5153a5574556d895f23e121a41e680da11c1 plugins/Login/inc/Module/Install/Fetch.pm
+SHA1 176d68fe7c07b6ab7cfe09093078b8127bbde786 plugins/Login/inc/Module/Install/Makefile.pm
+SHA1 8b37b38215d14f922b3d5132ce33d11d21d531ba plugins/Login/inc/Module/Install/Metadata.pm
+SHA1 9915504ffb4f14696ecca28af457e03f795ed2ce plugins/Login/inc/Module/Install/Share.pm
+SHA1 7eb44b00058c44795038d7fa4c0c77470f20a7f8 plugins/Login/inc/Module/Install/Win32.pm
+SHA1 6d05967a5e1680b5f118315aaa6b8a1e143d79d8 plugins/Login/inc/Module/Install/WriteAll.pm
+SHA1 b85d6515d225ef48073ac3f0ee1744019bff113f plugins/Login/lib/Jifty/Plugin/Login.pm
+SHA1 e2c32d8af104a88ce499131173ccc97247bd177e plugins/Login/lib/Jifty/Plugin/Login/Action/ChangePassword.pm
+SHA1 490f6f80d1addbd3b49908068f4f076301a0df85 plugins/Login/lib/Jifty/Plugin/Login/Action/ConfirmEmail.pm
+SHA1 dd8061d61508a1e9df2f0486750a6e1aeedd6311 plugins/Login/lib/Jifty/Plugin/Login/Action/Login.pm
+SHA1 58fd545139f90dd71964ec38ecffb386949cf5a6 plugins/Login/lib/Jifty/Plugin/Login/Action/Logout.pm
+SHA1 b869cffda9c3d66c648faac4952e0cd02333a541 plugins/Login/lib/Jifty/Plugin/Login/Action/RecoverPassword.pm
+SHA1 122c7769c6ba202aa4e791f9f34972e58fc1fcd2 plugins/Login/lib/Jifty/Plugin/Login/Action/ResetLostPassword.pm
+SHA1 c2438302917e04b15f940d12452a3d07328ba95d plugins/Login/lib/Jifty/Plugin/Login/Action/SendAccountConfirmation.pm
+SHA1 e238cc4ec479aefb8864ca99984cdea4c76141cf plugins/Login/lib/Jifty/Plugin/Login/Action/SendPasswordReminder.pm
+SHA1 6a41bfe4d8c024874b16f4c8f01d5d16fb77fcd3 plugins/Login/lib/Jifty/Plugin/Login/Action/Signup.pm
+SHA1 81875f6ab2d807bfe4671af084b4f238d383464c plugins/Login/lib/Jifty/Plugin/Login/CurrentUser.pm
+SHA1 525f9e063afd64961982b513c5eab0a85909c917 plugins/Login/lib/Jifty/Plugin/Login/Dispatcher.pm
+SHA1 26715ae2299b714b2eeaad1b0d9d709623c2b05d plugins/Login/lib/Jifty/Plugin/Login/Model/User.pm
+SHA1 3a8233f78d474c2671121f87c7e20bc01ba3090a plugins/Login/lib/Jifty/Plugin/Login/Notification/ConfirmAddress.pm
+SHA1 dd2d89075e1d29eb0e20cfc43fba7db98ef02529 plugins/Login/lib/Jifty/Plugin/Login/Notification/ConfirmLostPassword.pm
+SHA1 c67dcd72acc2f4e5b43863c7480697cc711b5e57 plugins/Login/share/po/en.po
+SHA1 d2e2fc32dbf2ebba82469cb0e8918c71660dc00b plugins/Login/share/po/fr.po
+SHA1 b157d8e7752bab6182ff13e64dec194cc67caf50 plugins/Login/share/web/templates/chgpasswd
+SHA1 cf9c995f10d81a5b124f278756808ad3418818e5 plugins/Login/share/web/templates/let/confirm_email
+SHA1 803c22a5ae8761da7bc9f62e392ec7ebef9bd98d plugins/Login/share/web/templates/let/reset_lost_password
+SHA1 8506d39fc45be929fb5a9e289a3682791a605d6d plugins/Login/share/web/templates/login
+SHA1 929a56746e77440a8b0bfda2b020a9583afe6cbf plugins/Login/share/web/templates/passwordreminder
+SHA1 fd4e0da55b29bae4c01d0868c9af9566923fb971 plugins/Login/share/web/templates/signup
+SHA1 6a8008c78f6f0985542b8c42ef3327508b798897 plugins/Nothing/Makefile.PL
+SHA1 514f77cd3c01a1fea159187fde9fa8ab78b0b75c plugins/Nothing/lib/Jifty/Plugin/Nothing.pm
+SHA1 ceeff321fbe0e12b7a4a2421320db57b8bee8732 plugins/Nothing/lib/Jifty/Plugin/Nothing/Dispatcher.pm
+SHA1 d6cbace955b9546e82780a4c070a96265fb788a1 plugins/ProfileBehaviour/Makefile.PL
+SHA1 f315c0902c3f5102ab8ca3159d201a1475074a5e plugins/ProfileBehaviour/lib/Jifty/Plugin/ProfileBehaviour.pm
+SHA1 145948e25dc1be742b76d870a20d13383f902f49 plugins/ProfileBehaviour/lib/Jifty/Plugin/ProfileBehaviour/Dispatcher.pm
+SHA1 1059b85f661b36f61b63cc72d0fc15cf732cc00a plugins/ProfileBehaviour/share/web/static/css/behaviour-profile.css
+SHA1 39746321849746fdfbeb51d7d2f1cb2adc1c3cdf plugins/ProfileBehaviour/share/web/static/js/behaviour.js
+SHA1 2c5d29ea2981cc759cc5f5b27cf7c536d4ea9384 share/dtd/xhtml-lat1.ent
+SHA1 62229286e03ec35c922c8a7f9f3bb68412a78a55 share/dtd/xhtml-special.ent
+SHA1 e7749f99989ec8a9608f6cfbd41a5e5dddc18aec share/dtd/xhtml-symbol.ent
+SHA1 b4a6d708f6b55a48526e9483c718f2ed820df75c share/dtd/xhtml1-strict.dtd
+SHA1 ddc3a6849e3db2ff2c5e1113a36d6e9869718dc4 share/po/en.po
+SHA1 a2f3d82acc9d343569eb0bc53a1517650c446189 share/po/fr.po
+SHA1 44b99ffe0fd8b2410b3ea5c988ebc61f07d30a38 share/po/ja.po
+SHA1 434c54b1132635916b8f6c70227685661593615d share/po/zh_cn.po
+SHA1 55bf7ecd5ef87fe38e5e3c6d6a0df3b7d8041994 share/po/zh_tw.po
+SHA1 da39a3ee5e6b4b0d3255bfef95601890afd80709 share/web/static/css/app-base.css
+SHA1 da39a3ee5e6b4b0d3255bfef95601890afd80709 share/web/static/css/app.css
+SHA1 c566d7ab5005e82dcf2f90809ae757e07d338138 share/web/static/css/autocomplete.css
+SHA1 5f569fc23eb815ee6f6d086aa6df87f6c38952d3 share/web/static/css/autohandler
+SHA1 c8f7207fab0b74a53a2a798bcedd2f9d94ecc32e share/web/static/css/base.css
+SHA1 669f07ab36d148383013733d8230d49e7e7b25ec share/web/static/css/calendar.css
+SHA1 bf48b6bda86f359b95b29a7c3451a3c1b5721385 share/web/static/css/combobox.css
+SHA1 6b4d4cbc063731dabe50356a3560eae6a9f25aef share/web/static/css/context-menus.css
+SHA1 9da37a3dea2259252e33e0cd72198baa04d17530 share/web/static/css/forms.css
+SHA1 52ddd83ee7c511d78537454a097f0264a7db3c1c share/web/static/css/halos.css
+SHA1 c7eede0c22f68e4417748bb0903b48195648f4c0 share/web/static/css/keybindings.css
+SHA1 91cd2873a5521bbc172389d8af2c29f33578fcc9 share/web/static/css/main.css
+SHA1 903069dae3de35d6a3226b8272ff317b8eebd58c share/web/static/css/nav.css
+SHA1 45861338bc40888737738521a44d4adf286b1204 share/web/static/css/notices.css
+SHA1 4389605ead1cf3e51a96f69d700ca70b3be6ca32 share/web/static/css/yui/calendar/calendar.css
+SHA1 b8074785c5372a76038c88feed271f1dd839b561 share/web/static/css/yui/tabview/border_tabs.css
+SHA1 2008bf0af63ee36885dd8bbc5fb134bc09b58135 share/web/static/css/yui/tabview/tabs.css
+SHA1 2f28dd2d59fe5486abce194e6fe68da0e49b1084 share/web/static/favicon.ico
+SHA1 6197eb13b4254f77f16833e1a9a8640e939d574c share/web/static/images/css/bullet_arrow_down.png
+SHA1 fdab0053425ba609387dffb0e2529a8feacc3906 share/web/static/images/css/bullet_arrow_up.png
+SHA1 3410d5156716e13443770cce0f3384eacfdb5adb share/web/static/images/css/fieldbg-autocomplete.gif
+SHA1 97c94d7dfb0683f9d2ac7f9406ca36495fa638e0 share/web/static/images/css/fieldbg.gif
+SHA1 67f41db40d62b81d71cb60c542695e0d7e6d393d share/web/static/images/pony.jpg
+SHA1 6197eb13b4254f77f16833e1a9a8640e939d574c share/web/static/images/silk/bullet_arrow_down.png
+SHA1 fdab0053425ba609387dffb0e2529a8feacc3906 share/web/static/images/silk/bullet_arrow_up.png
+SHA1 757e85619231e57be461e54982877457e0fbf6fc share/web/static/images/silk/calendar.png
+SHA1 899445ef75b18925f3c47969e122562dc6da5158 share/web/static/images/silk/cancel.png
+SHA1 bd221f74c7d3442a1db5f5594a1be86c662497ad share/web/static/images/silk/cancel_grey.png
+SHA1 3855754e8fc9331c67dd2d0789d9f2d6e7daae8b share/web/static/images/silk/error.png
+SHA1 04b482344d75d0732275727bd73cceb9b049d276 share/web/static/images/silk/information.png
+SHA1 62a1b41ac5eefbf3d0ad578a19572d4096d88146 share/web/static/images/silk/pencil.png
+SHA1 2f84cd8d3f46ffe9eb1406a4f6337fa5b5e2bcd1 share/web/static/images/silk/pencil_add.png
+SHA1 d2c01c9ded34297020c6f9abb5240e0b2fd8606a share/web/static/images/yui/us/my/bn/x_d.gif
+SHA1 88a51e34bc8c5d616b76743a52ad1fe0cae8232e share/web/static/images/yui/us/tr/callt.gif
+SHA1 f818910630fc046dbdd6dde2960d3e26c5d4beaf share/web/static/images/yui/us/tr/calrt.gif
+SHA1 eb756c931be8ef70fc27ba0046375f32022e3b6d share/web/static/js/app.js
+SHA1 716b6f8326bd5cd05c31e521351197b5038e052e share/web/static/js/app_behaviour.js
+SHA1 2b28f63068ff486e7fd7937f725f47e886d01831 share/web/static/js/behaviour.js
+SHA1 aa6192ac38a0c708ea0efb60bb98c666d9687423 share/web/static/js/bps_util.js
+SHA1 6b09c590f5e94b238fd99031e6b57ec57e70bd3f share/web/static/js/calendar.js
+SHA1 e9f9931abe8ddf86cf5cfddd1f0e963bb5bf0ccb share/web/static/js/combobox.js
+SHA1 cd5a80e098d28f7cf0b74cee38f08bd336ccdc95 share/web/static/js/context_menu.js
+SHA1 b03b1f06f9c972cfb083c3d87b3dc74e4d85bf77 share/web/static/js/css_browser_selector.js
+SHA1 a90d3ffbc606979282dba3296599f582715021ab share/web/static/js/cssquery/cssQuery-level2.js
+SHA1 ba5ff2e1484476981ccf311ff8fe0062a9b2ac01 share/web/static/js/cssquery/cssQuery-level3.js
+SHA1 a80e117cfca6644bde2bb8bd8d48a093e784a731 share/web/static/js/cssquery/cssQuery-standard.js
+SHA1 95408c5aa294bdbc7b857d35772c1bd888b87b33 share/web/static/js/cssquery/cssQuery.js
+SHA1 d542a217ef9c527340d25bfffbccce27927d1259 share/web/static/js/dom-drag.js
+SHA1 4553f3cb184b09228ed4362898e9d30200a2a585 share/web/static/js/formatDate.js
+SHA1 a1d2c6292d656c275383b97aad6ca913b8a1b031 share/web/static/js/halo.js
+SHA1 44bac00f46d4e6809892fc03c42487bd275be71e share/web/static/js/jifty.js
+SHA1 29fe34f11192976f1a388562188b1eb9af7f4497 share/web/static/js/jifty_smoothscroll.js
+SHA1 8723bf251531e79ab109ea0d3fb2187a8dac8cb6 share/web/static/js/jifty_subs.js
+SHA1 2fd261c3c30a0b17e02e6af79d7c7c587dfe2f2a share/web/static/js/jifty_utils.js
+SHA1 d6c17ef3717315c08659082144a2caf2e970b23d share/web/static/js/jsTrace.js
+SHA1 2d8acba4acfd5508381461ccabe954c2e9df086c share/web/static/js/jsan/DOM/Events.js
+SHA1 36b2a3f1966b97fcc338b557830106bf2d490485 share/web/static/js/jsan/JSAN.js
+SHA1 679d9c011aa8403cfc0ba945a9143c2e9cacccfa share/web/static/js/jsan/Push.js
+SHA1 4d3474847360cb00edc1ae4745ea6b56a7ec1a2b share/web/static/js/jsan/Upgrade.js
+SHA1 7a13c9041326f2e70494f6ed5bcd87396bdd4280 share/web/static/js/jsan/Upgrade/Array/push.js
+SHA1 becdf6868ec4aec2dc93c8c33b0713d1c4f4eb34 share/web/static/js/jsan/Upgrade/Function/apply.js
+SHA1 f15b0364f99d2e4c1af795c82883f89b9eaca9b2 share/web/static/js/json.js
+SHA1 df1c8b06e2d10c743cbd65d7feda8db5a23522d6 share/web/static/js/key_bindings.js
+SHA1 986a63bc533f6fa99c9b0f0226a14f9871b94ce5 share/web/static/js/prototype.js
+SHA1 a1048deeafbc76659e54eb77c0e51b6b79cade19 share/web/static/js/rico.js
+SHA1 164bc59cf75fe943edc80da65b19246fc9b9643e share/web/static/js/scriptaculous/builder.js
+SHA1 afa5b63db51fc4c3c4ff2535d3af5fe5b00add19 share/web/static/js/scriptaculous/controls.js
+SHA1 28f001d3c48395daf0de22876a70d918db3a461e share/web/static/js/scriptaculous/dragdrop.js
+SHA1 21ce51daa693e3716678ac4190369b499b35e8de share/web/static/js/scriptaculous/effects.js
+SHA1 914db330c7fe585dfeddce713558f04328fb51db share/web/static/js/scriptaculous/scriptaculous.js
+SHA1 cc2e31820eed69ae87b1b2befa50e8c4a8519342 share/web/static/js/scriptaculous/slider.js
+SHA1 6b42a40cac7d45f9fd6665e18c4e494704eff9e3 share/web/static/js/scriptaculous/unittest.js
+SHA1 f254696f59ab11c2373c79ba0e6f303d8ac4f71e share/web/static/js/setup_jsan.js
+SHA1 9872547d7c43a3ddb3280fe4e022912b06d59239 share/web/static/js/yui/calendar.js
+SHA1 b378c19c0bbde98f1c7873ca61bb749a63159235 share/web/static/js/yui/container.js
+SHA1 7ddb98d87fa5e228e19c0ce9da2c8d14c8fb8be1 share/web/static/js/yui/dom.js
+SHA1 cb5c1c0e7e8803c95c2f0e313bbeb5a3431f1fba share/web/static/js/yui/event.js
+SHA1 2d81827326f37e25ba95c248498096759f3433c5 share/web/static/js/yui/tabview.js
+SHA1 71c27fdb9e3d24f628a820638ff529098cdd7821 share/web/static/js/yui/yahoo.js
+SHA1 05359f0e32b4bebd965707788228704167689d3c share/web/templates/=/subs
+SHA1 5cfcf2d84b5548b2990efa52e51d3f15a47816b4 share/web/templates/__jifty/admin/_elements/nav
+SHA1 6a096f8d324464e6ad6407442faf7b2af0ecdc7e share/web/templates/__jifty/admin/action/dhandler
+SHA1 1b55e3945405d09df59f0a40182f06f8f59a2e97 share/web/templates/__jifty/admin/autohandler
+SHA1 51eb5ec4ebe6ad25eac8461c132193ded8ca2640 share/web/templates/__jifty/admin/fragments/list/header
+SHA1 80a5f7d081589dba73766f86a79145e997500655 share/web/templates/__jifty/admin/fragments/list/list
+SHA1 a73b777585f562210eccba19f007e2ac89b428c4 share/web/templates/__jifty/admin/fragments/list/new_item
+SHA1 ed176f653007f8a08e88355bfd68e1b0fc645723 share/web/templates/__jifty/admin/fragments/list/search
+SHA1 a118ac016c645629ed720d9626b36266089eee58 share/web/templates/__jifty/admin/fragments/list/update
+SHA1 9d339e7acebf3e929b15c1d8b4642ecbddf7f4b6 share/web/templates/__jifty/admin/fragments/list/view
+SHA1 559940ee5c2e5b56f3a438f377ea110018e20b18 share/web/templates/__jifty/admin/index.html
+SHA1 b0ceaf320862d14064c55a17f72e91024690371d share/web/templates/__jifty/admin/model/dhandler
+SHA1 bdaeeff0c2522a8509d4da45be703d1e8cf5c96c share/web/templates/__jifty/autocomplete.xml
+SHA1 bfeb6c28df0bc0c78119c9ff90f8051e5f6adcc2 share/web/templates/__jifty/css/dhandler
+SHA1 da39a3ee5e6b4b0d3255bfef95601890afd80709 share/web/templates/__jifty/empty
+SHA1 f85d8cae8a2df3ee51b868a744a9e9af21925e0c share/web/templates/__jifty/error/_elements/error_text
+SHA1 e2d761b0b92f818eb2bbb91a15cef0a2471d2245 share/web/templates/__jifty/error/_elements/wrapper
+SHA1 2e8a971eb5623b245d6ed8f551315842a6bfb251 share/web/templates/__jifty/error/autohandler
+SHA1 0cf3e3f2f8447ea5f66fd22d325c578448129718 share/web/templates/__jifty/error/dhandler
+SHA1 78e1e0af483fa3bdac2de4e5a9d82486d67b8537 share/web/templates/__jifty/error/error.css
+SHA1 6834dbbfe494846bb3a70f1f8d6735c4f8c1b326 share/web/templates/__jifty/error/mason_internal_error
+SHA1 b8793db1dd47943dc83173f02f2227f9ca310235 share/web/templates/__jifty/halo
+SHA1 7fbdc70a9c0481d1e67b6154178173d434206fd9 share/web/templates/__jifty/js/dhandler
+SHA1 6a50927b6d7c7f5f2048a691299585cb2dd05677 share/web/templates/__jifty/online_docs/autohandler
+SHA1 d0116574b44622720db7a9efc7fafdf4002ed012 share/web/templates/__jifty/online_docs/content.html
+SHA1 bd81ff4e458c5e1a76c131dce40ffd71fd6a76f7 share/web/templates/__jifty/online_docs/index.html
+SHA1 630b516dede6767e8185de8211e6affd7b564cfe share/web/templates/__jifty/online_docs/toc.html
+SHA1 c31026ba4fa88814a705651878cb89f086f43f9d share/web/templates/__jifty/validator.xml
+SHA1 8ec2abf3fb43be8217f7a0af4054cf40f7e1e47e share/web/templates/__jifty/webservices/json
+SHA1 bbe1d4af8ab26a9e7d528d819bb271b591172f3c share/web/templates/__jifty/webservices/xml
+SHA1 c7384fcdf1ee7a3e347388c6619f6aa2f297656e share/web/templates/__jifty/webservices/yaml
+SHA1 8145ab6043a7bbd70e1bfa33e068fb741f4ee3a5 share/web/templates/_elements/header
+SHA1 f36e8e0557117d8fdcebad74694fac718101ce27 share/web/templates/_elements/keybindings
+SHA1 0d84d7af43685d7161fc800a2c8b464b8586c57d share/web/templates/_elements/menu
+SHA1 4da6700ff1fdc390436ff05906f4df979c44d572 share/web/templates/_elements/nav
+SHA1 b74c8647eb89e1e189d3cefbbfae51da608edcff share/web/templates/_elements/page_nav
+SHA1 c255d8da7c3eb68fc66f9f7c041c92b247489fcc share/web/templates/_elements/sidebar
+SHA1 bc8991085ddd0c664bb57a1ad4a79e9bca1807ea share/web/templates/_elements/wrapper
+SHA1 35adfc3fd3cbf1c2c3310dd2c2a7eb7317495ced share/web/templates/autohandler
+SHA1 106fc0286e2aff5a01d9a623c37fc807451f2037 share/web/templates/dhandler
+SHA1 347e3ad8491b742c4cd8e63e77fb4cae2152034c share/web/templates/helpers/calendar.html
+SHA1 1bd17a07884f71740a048c41b67ac9b06915bf76 share/web/templates/index.html
+SHA1 7f9dae91a9bfc2743eec1d7aaf78e16fc9f1baba t/00-load.t
+SHA1 1e1a7b63b3ea8d2712214eb28b5fe69aae76da1d t/01-dependencies.t
+SHA1 ade22974f54a6e0991e14be587be0c9797e72ed5 t/01-test-web.t
+SHA1 95fe956e7bae756a7bc25e65a6761ee0c64981e7 t/01-version_checks.t
+SHA1 4fa0e0143339298278c5e22a58236c6b71555508 t/02-connect.t
+SHA1 46221e3b0272c3ef2f5ce0032239dc3aba1d2e04 t/03-form-protocol.t
+SHA1 411bf10441c2c9312b0a245c6a7bef73e001875e t/03-is_passing-no_plan.t
+SHA1 70d3ae1817b53aca414debcdede37425538b3c0a t/03-is_passing.t
+SHA1 69172edb1ef6e20ec71a08ca49b7bed474c3fb07 t/03-test-mailbox.t
+SHA1 53a150bc6dff7517e22624008baff4ed3bec993d t/04-test_file.t
+SHA1 b3e2d70996dbbe82510a8e75646b83b96d0b566a t/05-dispatcher.t
+SHA1 e53c8d489eb565025b1a5ab2eda6e9757ccaf0a8 t/06-forms.t
+SHA1 0712de44cbe60eea251a1955b0bcb218f22adf4a t/07-limit-actions.t
+SHA1 38ab90a10fc0cbbbfc3205e543312950302f37a2 t/08-client.t
+SHA1 ea9587b57587f6b9b5e02e3d30b96807f7b62200 t/09-url.t
+SHA1 a7e9e7792684ccbd1500b4ad88c97a5bc1f7dd54 t/10-i18n.t
+SHA1 d571f6fae9d1a33060fda8c89951492a02b1af01 t/11-config-files.t
+SHA1 3b834f5b8a6371c502eb0dc1f1cb9d79a5257c7a t/12-param-schema.t
+SHA1 59c44900b1cb957d262f96363ceff21b46e0d598 t/99-pod-coverage.t
+SHA1 bb0da54f2b3f2d7955baa41ee458cb3d1887f475 t/99-pod.t
+SHA1 a7dc1f376cac630ea28d2965e561469deb951cc7 t/Continuations/bin/jifty
+SHA1 adbc53cbd328b4d49d3336586fe8f7b7124da970 t/Continuations/lib/Continuations/Action/CrossBridge.pm
+SHA1 01ebcf50d361afff117bfbb14125470da3010f90 t/Continuations/lib/Continuations/Action/GetGrail.pm
+SHA1 55c7de13306c111504b1c9a10fb3147a3d8be79f t/Continuations/lib/Continuations/Dispatcher.pm
+SHA1 904ccf244ddafa2cf756e2de1f251b0962399750 t/Continuations/share/web/templates/autohandler
+SHA1 3b7dfa8465eba725b1322a16c89e86db5aeda1e0 t/Continuations/share/web/templates/black-knight-color.html
+SHA1 33dec4df44d11fb3c62a83a2bbb9e21b82942a35 t/Continuations/share/web/templates/black-knight-name.html
+SHA1 3b57df6661dd414469de257a9229b0c64a86f028 t/Continuations/share/web/templates/black-knight-quest.html
+SHA1 b69550b92c17e7749ca64b299e7e15bcd8596eae t/Continuations/share/web/templates/black-knight.html
+SHA1 a57494ba5021699868a520313332b08eee3bb1e9 t/Continuations/share/web/templates/help-help.html
+SHA1 6831427bd1a041b49a320d60ef7baf2e2e62be1a t/Continuations/share/web/templates/index-help.html
+SHA1 4acb52a5373144d2cb5ccb7a39961e5306c8b5ee t/Continuations/share/web/templates/index.html
+SHA1 3b7b51b4428dcbf0b9b1d55c39fd139a3ee4868a t/Continuations/t/00-prototype.t
+SHA1 c36179582e4dfabdc7b39cbd8196f187140e24eb t/Continuations/t/01-raw-api.t
+SHA1 313bd1afbbd9e066db03080e99766961f9fba2a8 t/Continuations/t/02-api.t
+SHA1 f68f215bb0d9eae9054185b1335ae1fdd0f82708 t/Continuations/t/03-gc.t
+SHA1 acb9008e28ca12dfdc63d007f4f9cad74144b09f t/Continuations/t/04-before-blocks.t
+SHA1 5919e0929f27b3abcd3b6ee4148d2306594ee7dd t/DateTime.t
+SHA1 29a9d0b63d274805fe33c3123faf1a5f871a0e24 t/Jifty.pm
+SHA1 a7dc1f376cac630ea28d2965e561469deb951cc7 t/Mapper/bin/jifty
+SHA1 b381fb60f53d16f8846f7011b8f8a862eaa834c0 t/Mapper/lib/Mapper/Action/CrossBridge.pm
+SHA1 6bee8bba7db76902f300f69bbc7ffbd045380074 t/Mapper/lib/Mapper/Action/GetGrail.pm
+SHA1 904ccf244ddafa2cf756e2de1f251b0962399750 t/Mapper/share/web/templates/autohandler
+SHA1 14a865ad9c903f69dffa595c463f343dd29f62e2 t/Mapper/share/web/templates/index.html
+SHA1 3b7b51b4428dcbf0b9b1d55c39fd139a3ee4868a t/Mapper/t/00-prototype.t
+SHA1 548bf96ee16a84e3793d89cc0dd68ab67bd03f66 t/Mapper/t/01-raw-api.t
+SHA1 c9c9c8fa7e4284baecf87967eef108715068d249 t/Mapper/t/02-api.t
+SHA1 a7dc1f376cac630ea28d2965e561469deb951cc7 t/TestApp-Plugin-REST/bin/jifty
+SHA1 4762d5e154fcbeb0b188a1ecb90c4997403c9d24 t/TestApp-Plugin-REST/etc/config.yml
+SHA1 61845f11966aadecf3bb885fcc5b33ef66e9637f t/TestApp-Plugin-REST/lib/TestApp/Plugin/REST/Action/DoSomething.pm
+SHA1 3670c345f54846479d42b9636e0484130e1e72c1 t/TestApp-Plugin-REST/lib/TestApp/Plugin/REST/Dispatcher.pm
+SHA1 2bc709eb73c4f72267835a06f07de3bc9fe0adba t/TestApp-Plugin-REST/lib/TestApp/Plugin/REST/Model/Group.pm
+SHA1 4ed01e5665fe265e1d45bfcce37a57e8c3087605 t/TestApp-Plugin-REST/lib/TestApp/Plugin/REST/Model/User.pm
+SHA1 5184bbae7c9a4653841156f54b34bac4abf7d54f t/TestApp-Plugin-REST/t/00-model-User.t
+SHA1 3b7b51b4428dcbf0b9b1d55c39fd139a3ee4868a t/TestApp-Plugin-REST/t/00-prototype.t
+SHA1 b6c65e7f47ff136c7d370b85cf01f27537dd81ff t/TestApp-Plugin-REST/t/01-config.t
+SHA1 3e915c7d6a7c7a0fee3246da9b1f8e782b5a317a t/TestApp-Plugin-REST/t/02-basic-use.t
+SHA1 a7dc1f376cac630ea28d2965e561469deb951cc7 t/TestApp/bin/jifty
+SHA1 f9a9321b803e4f248ecdd86fd71613164c01bd86 t/TestApp/lib/TestApp/Action/DoSomething.pm
+SHA1 f93118ca17be86a7c171ee47864d7149baf7344c t/TestApp/lib/TestApp/Action/DoSomethingElse.pm
+SHA1 6e27f855429d18181d6c5a0de6b83492fa5c6219 t/TestApp/lib/TestApp/CurrentUser.pm
+SHA1 de8a0bb9c5dfe2ceb00f38c6baf66627f3b361b2 t/TestApp/lib/TestApp/Dispatcher.pm
+SHA1 3424b48c4def8e714a6508afa7a43569075131c8 t/TestApp/lib/TestApp/Model/User.pm
+SHA1 67f41db40d62b81d71cb60c542695e0d7e6d393d t/TestApp/share/web/static/images/pony.jpg
+SHA1 1e4b29a138e61f49c1ceffe50c15ed0a087613fc t/TestApp/share/web/templates/currentuser
+SHA1 a2e7bf8d2d52bbaf360af24b4ffc00c68d7e31f2 t/TestApp/share/web/templates/dispatch/basic
+SHA1 d1e244371109ce216bfd6b9ac03374737461577c t/TestApp/share/web/templates/dispatch/basic-show
+SHA1 44795ddb863c9c32c05678bf8288c9816e3366a9 t/TestApp/share/web/templates/dosomethingelse
+SHA1 f5870c2fb3222b86d97f14bdf8155821c887987b t/TestApp/share/web/templates/editform
+SHA1 ef0db81c421ba89231ea6d72f355b7dd8fd5e8e2 t/TestApp/share/web/templates/index.html
+SHA1 2f721db97a3b571d0006f6ed9a0d0c8bffef8642 t/TestApp/share/web/templates/manual_redirect
+SHA1 9a50bb56338896f9cd50b7098a9e28397ad28a34 t/TestApp/share/web/templates/somedir/dhandler
+SHA1 350ab77f7c18d826ed91eaf251f3f80ebd9605ba t/TestApp/t/00-model-User.t
+SHA1 3b7b51b4428dcbf0b9b1d55c39fd139a3ee4868a t/TestApp/t/00-prototype.t
+SHA1 94a1fe86cc34fbdce9087f30a69a859063ca8714 t/TestApp/t/01-config.t
+SHA1 6c6726cd87697675c80828825ff34109daec7f86 t/TestApp/t/02-dispatch.t
+SHA1 d438a2c8aa2fa15c80da4f2a44ecfe65856b58f8 t/TestApp/t/03-static.t
+SHA1 dc8e0ea29839c6dd50843d7c95a907874f6d5472 t/TestApp/t/04-sessions.t
+SHA1 071288e6e1c64cef819f8e3adb7b20a8c7044804 t/TestApp/t/05-actions-before-redirect.pm
+SHA1 79dc79df5690e3d7b418bf6475c13ea0d4c1f8a4 t/TestApp/t/05-editactions-Cachable.t
+SHA1 47ac4941336e8bc00821e89b0ccfdf9232be53ca t/TestApp/t/05-editactions-Record.t
+SHA1 1a425b17fe88ed3c6783e7894bc514641ad0fffa t/TestApp/t/06-validation.t
+SHA1 0a73294c477197748994580ed1615cbe42bfa335 t/TestApp/t/07-sandboxing.t
+SHA1 842377402228a26ff444c565831bc560a66c0302 t/TestApp/t/08-notifications.t
+SHA1 1fce112ee319adb146b787ad23ef3b050759063b t/TestApp/t/09-redirect.t
+SHA1 55ba141d6c73a6dfa7ccccb6cb9f32253ed8decb t/TestApp/t/10-compress.t
+SHA1 18667b3bdcbe7b9dd2715e16c8bbffe51c28548f t/TestApp/t/11-current_user.t
+SHA1 019605c6e627bf65ee3d2ed1b8d2b34fc8e10853 t/TestApp/t/12-search.t
+SHA1 69401ad0579fa743f087731536229d2806dd1d6a t/TestApp/t/config-Cachable
+SHA1 710c4b0faaea46f90a7b071e5396541a59ed0ff1 t/TestApp/t/config-Record
+SHA1 30274351a6eb9342daef843ffb8a2aafee38afb4 t/TestApp/t/instance_id.t
+SHA1 ee548850452b377e08f36a9269c1b8f7911bdb2d t/TestApp/t/regex_meta_in_path_info.t
+SHA1 c8fb21f31b593627b38129ee9dd41eaf9c556ced t/lib/Jifty/SubTest.pm
+-----BEGIN PGP SIGNATURE-----
+Version: GnuPG v1.4.3 (GNU/Linux)
+
+iD4DBQFFromfEi9d9xCOQEYRAjV1AJ9gxbyucs3vXDll+msp25TGsP4ZlwCUDDbz
+1ktLZJXD6wX2Hkn/232QNg==
+=ItK4
+-----END PGP SIGNATURE-----

Added: jifty/branches/schema-plugins/bin/build_par
==============================================================================
--- (empty file)
+++ jifty/branches/schema-plugins/bin/build_par	Mon Jan 29 21:05:02 2007
@@ -0,0 +1,23 @@
+#!/bin/sh
+pp  -z 9 -s \
+	-o ../par/jifty-`perl -e'print $^O'`-`grep '^version' META.yml|cut -d" " -f 2` \
+	-M `grep :: Makefile.PL  |cut -d\' -f 2|grep -v '^use' |xargs -n 1  echo -n " -M "` \
+	-I lib -I inc\
+	-M `(cd inc ;find -type f -name \*.pm|cut -c 3-| grep -v '^Module/Install.pm$'|xargs -n 1  echo -n " -M ")` \
+	-M `(cd lib ;find -type f -name \*.pm|cut -c 3-| xargs -n 1  echo -n " -M ")` \
+	-a 'share/;lib/auto/Jifty/' \
+	bin/jifty
+
+
+# Make a parball
+# Execute code to get dependencies
+# Compress it a lot
+# -s 
+# name it as "jifty-platform-version" in jifty/par (next to jifty-trunk)
+# include all our dependencies from Makefile.PL
+# use the "lib" directory
+# include all of Jifty's libs to pick up dependencies
+# include Jifty's share directory in the par
+# do all this by sourcing bin/jifty
+
+

Added: jifty/branches/schema-plugins/bin/jifty
==============================================================================
--- (empty file)
+++ jifty/branches/schema-plugins/bin/jifty	Mon Jan 29 21:05:02 2007
@@ -0,0 +1,15 @@
+#!/usr/bin/env perl
+use warnings;
+use strict;
+use File::Basename qw(dirname); 
+use UNIVERSAL::require;
+
+BEGIN {
+    Jifty::Util->require or die $UNIVERSAL::require::ERROR;
+    my $root = Jifty::Util->app_root;
+    unshift @INC, "$root/lib" if ($root);
+}
+
+use Jifty::Script;
+local $SIG{INT} = sub { warn "Stopped\n"; exit; };
+Jifty::Script->dispatch();

Added: jifty/branches/schema-plugins/bin/runcover
==============================================================================
--- (empty file)
+++ jifty/branches/schema-plugins/bin/runcover	Mon Jan 29 21:05:02 2007
@@ -0,0 +1,4 @@
+#!/bin/sh
+# XXX: this should be in makefile target, but i have no idea about how to do that in M::I
+
+env JIFTY_TESTSERVER_COVERAGE=-db,`pwd`/cover_db HARNESS_PERL_SWITCHES=-MDevel::Cover make test

Added: jifty/branches/schema-plugins/bin/service
==============================================================================
--- (empty file)
+++ jifty/branches/schema-plugins/bin/service	Mon Jan 29 21:05:02 2007
@@ -0,0 +1,32 @@
+#!/usr/bin/env perl
+
+use strict;
+use warnings;
+use LWP::UserAgent;
+use Getopt::Long;
+
+my($class, $host, $path, $format, $moniker);
+GetOptions("class=s" => \$class,
+           "host=s" => \$host,
+           "path=s" => \$path,
+           "format=s" => \$format,
+           "moniker=s" => \$moniker);
+$format  ||= "yaml";
+$host    ||= "http://localhost:8888";
+$path    ||= "/__jifty/webservices/$format";
+$moniker ||= "moniker";
+
+my %args = @ARGV;
+
+my $ua = LWP::UserAgent->new;
+my $res = $ua->post("$host$path", {
+                           "J:A-$moniker" => $class,
+                           map {("J:A:F-$_-$moniker" => $args{$_})} keys %args
+                          });
+
+if ($res->is_success) {
+    print $res->content;
+} else {
+    die $res->status_line;
+}
+

Added: jifty/branches/schema-plugins/bin/xgettext
==============================================================================
--- (empty file)
+++ jifty/branches/schema-plugins/bin/xgettext	Mon Jan 29 21:05:02 2007
@@ -0,0 +1 @@
+find {bin,lib,share/web/templates/} -type f |xargs xgettext.pl -p share/po -o en.po

Added: jifty/branches/schema-plugins/debian/README
==============================================================================
--- (empty file)
+++ jifty/branches/schema-plugins/debian/README	Mon Jan 29 21:05:02 2007
@@ -0,0 +1,15 @@
+This directory contains Debian packaging files for Jifty.
+
+There is a debian repository at:
+
+ deb http://debian.jifty.org/debian sarge jifty
+
+It contains jifty packages as well as some jifty plugins, updates for
+sarge and ubuntu 6.06 LTS
+
+Please let us know if there are any issues by sending mail to the
+jifty mailing list and we'll try and fix them.
+
+Bart Bunting
+Yves Agostini
+

Added: jifty/branches/schema-plugins/debian/changelog
==============================================================================
--- (empty file)
+++ jifty/branches/schema-plugins/debian/changelog	Mon Jan 29 21:05:02 2007
@@ -0,0 +1,50 @@
+jifty (0.70117-1) unstable; urgency=low
+
+  * New cpan release
+
+ -- AGOSTINI Yves <agostini at univ-metz.fr>  Thu, 18 Jan 2007 08:52:53 +0100
+
+jifty (0.70116-1) unstable; urgency=low
+
+  * New cpan release
+
+ -- AGOSTINI Yves <agostini at univ-metz.fr>  Wed, 17 Jan 2007 08:46:31 +0100
+
+jifty (0.61123-1) unstable; urgency=low
+
+  * New cpan release 
+
+ -- AGOSTINI Yves <agostini at univ-metz.fr>  Wed, 24 Nov 2006 21:08:26 +0200
+
+jifty (0.60912-2) unstable; urgency=low
+
+  * Add missing dependencies, 
+  * Add fr.po 
+
+ -- AGOSTINI Yves <agostini at univ-metz.fr>  Wed, 25 Oct 2006 09:46:26 +0200
+
+jifty (0.60912-1) unstable; urgency=low
+
+  * Change version and clean dependencies on module-refresh-perl and
+    locale-maketext-lexicon for sarge
+
+ -- AGOSTINI Yves <agostini at univ-metz.fr>  Mon, 23 Oct 2006 10:55:17 +0200
+
+jifty (0.60728-3) unstable; urgency=low
+
+  * Missed some date dependencies
+
+ -- Bart Bunting <bart at ursys.com.au>  Fri, 25 Aug 2006 09:30:28 +1000
+
+jifty (0.60728-2) unstable; urgency=low
+
+  * More dependencies, we're nearly there seems I missed some.
+
+ -- Bart Bunting <bart at bunting.net.au>  Fri, 25 Aug 2006 06:55:04 +1000
+
+jifty (0.60728-1) unstable; urgency=low
+
+  * Initial debianisation.
+
+ -- Bart Bunting <bart at ursys.com.au>  Tue, 22 Aug 2006 10:39:31 +1000
+

Added: jifty/branches/schema-plugins/debian/compat
==============================================================================
--- (empty file)
+++ jifty/branches/schema-plugins/debian/compat	Mon Jan 29 21:05:02 2007
@@ -0,0 +1 @@
+5

Added: jifty/branches/schema-plugins/debian/control
==============================================================================
--- (empty file)
+++ jifty/branches/schema-plugins/debian/control	Mon Jan 29 21:05:02 2007
@@ -0,0 +1,118 @@
+Source: jifty
+Section: web
+Priority: optional
+Maintainer: Bart Bunting <bart at debian.org>
+Build-Depends-Indep: debhelper (>> 5), libmodule-corelist-perl,
+ libdevel-cover-perl, libmodule-scandeps-perl, libpod-simple-perl,
+ libtest-base-perl, libtest-www-mechanize-perl (>> 1.04),
+ libtest-pod-coverage-perl
+
+Package: jifty
+Section: perl
+Architecture: all
+Depends: ${perl:Depends}, libjifty-perl
+Description: Jifty perl libraries
+ Yet another web framework.
+ .
+ What's cool about Jifty? (Buzzwords)
+ .
+ DRY (Don't Repeat Yourself)
+        Jifty tries not to make you say things more than once.
+ .
+ Full-stack
+        Out of the proverbial box, Jifty comes with one way to do everything
+        you should need to do: One database mapper, one templating system,
+        one web services layer, one AJAX toolkit, one set of handlers for
+        standalone or FastCGI servers. We work hard to make all the bits
+        play well together, so you don't have to.
+ .
+ Continuations
+        With Jifty, it's easy to let the user go off and do something else,
+        like fill out a wizard, look something up in the help system or go
+        twiddle their preferences and come right back to where they were.
+ .
+ Form-based dispatch
+        This is one of the things that Jifty does that we've not seen
+        anywhere else. Jifty owns your form rendering and processing. This
+        means you never need to write form handling logic. All you say is "I
+        want an input for this argument here" and Jifty takes care of the
+        rest. (Even autocomplete and validation)
+ .
+ A Pony
+        Jifty is the only web application framework that comes with a pony.
+ .
+ This package provides Jifty scripts.
+
+Package: libjifty-perl
+Section: perl
+Architecture: all
+Depends: ${perl:Depends}, perl (>> 5.8.3),
+ libapp-cli-perl (>> 0.03), libcache-cache-perl,
+ libcalendar-simple-perl, libclass-accessor-perl,
+ libclass-container-perl, libclass-data-inheritable-perl,
+ perl-modules, libcgi-cookie-splitter-perl, libcgi-simple-perl,
+ libcrypt-cbc-perl, libcrypt-rijndael-perl,
+ libcompress-zlib-perl, libcss-squish-perl (>> 0.05), 
+ libdbd-sqlite3-perl, libdata-page-perl, libossp-uuid-perl,
+ libdatetime-perl, libdate-manip-perl, libemail-folder-perl,
+ libemail-localdelivery-perl, libemail-mime-perl,
+ libemail-mime-creator-perl, libemail-mime-contenttype-perl,
+ libemail-send-perl (>> 1.99_01), libemail-simple-perl,
+ libemail-simple-creator-perl, libexporter-lite-perl,
+ libfile-find-rule-perl, libfile-mmagic-perl,
+ libfile-sharedir-perl (>> 0.04), libhtml-parser-perl,
+ libhtml-lint-perl, libhtml-mason-perl (>> 1.31), 
+ libwww-perl, libhttp-server-simple-perl (>> 0.26), 
+ libhttp-server-simple-recorder-perl, libhash-merge-perl, libhook-lexwrap-perl,
+ libipc-pubsub-perl (>> 0.22), libjifty-dbi-perl (>> 0.31),
+ liblocale-maketext-lexicon-perl, liblog-log4perl-perl,
+ libmime-types-perl, libmodule-pluggable-perl (>> 3.1),
+ libmodule-corelist-perl, libmodule-refresh-perl,
+ libmodule-scandeps-perl, libobject-declare-perl (>> 0.13),
+ libparams-validate-perl, libscalar-defer-perl (>> 0.06),
+ libstring-koremutake-perl, libsql-reservedwords-perl,
+ libtest-base-perl, libuniversal-require-perl, liburi-perl,
+ libxml-writer-perl (>> 0.601), libxml-simple-perl,
+ libxml-xpath-perl, libversion-perl, libyaml-syck-perl (>> 0.72), 
+ libyaml-perl (>> 0.35), libjson-perl (>> 0.01),
+ libpod-simple-perl, 
+ libsub-exporter-perl, libcache-memcached-perl, liblog-dispatch-perl
+Recommends: libmodule-install-perl,
+ libtest-pod-coverage-perl, libtest-www-mechanize-perl (>> 1.04), libwww-mechanize-perl (>> 1.12),
+ libclass-accessor-named-perl, libdevel-cover-perl,
+ libmodule-install-perl, libpar-dist-fromcpan-perl, libtest-mockobject-perl,
+ libtest-mockmodule-perl,
+ libcgi-fast-perl, libapache-mod-fastcgi,
+ libjifty-plugin-editinplace-perl, libjifty-plugin-login-perl
+Description: Jifty perl libraries
+ Yet another web framework.
+ .
+ What's cool about Jifty? (Buzzwords)
+ .
+ DRY (Don't Repeat Yourself)
+        Jifty tries not to make you say things more than once.
+ .
+ Full-stack
+        Out of the proverbial box, Jifty comes with one way to do everything
+        you should need to do: One database mapper, one templating system,
+        one web services layer, one AJAX toolkit, one set of handlers for
+        standalone or FastCGI servers. We work hard to make all the bits
+        play well together, so you don't have to.
+ .
+ Continuations
+        With Jifty, it's easy to let the user go off and do something else,
+        like fill out a wizard, look something up in the help system or go
+        twiddle their preferences and come right back to where they were.
+ .
+ Form-based dispatch
+        This is one of the things that Jifty does that we've not seen
+        anywhere else. Jifty owns your form rendering and processing. This
+        means you never need to write form handling logic. All you say is "I
+        want an input for this argument here" and Jifty takes care of the
+        rest. (Even autocomplete and validation)
+ .
+ A Pony
+        Jifty is the only web application framework that comes with a pony.
+ .
+ This package provides the Jifty perl libraries.
+

Added: jifty/branches/schema-plugins/debian/rules
==============================================================================
--- (empty file)
+++ jifty/branches/schema-plugins/debian/rules	Mon Jan 29 21:05:02 2007
@@ -0,0 +1,80 @@
+#!/usr/bin/make -f
+# This debian/rules file is provided as a template for normal perl
+# packages. It was created by Marc Brockschmidt <marc at dch-faq.de> for
+# the Debian Perl Group (http://pkg-perl.alioth.debian.org/) but may
+# be used freely wherever it is useful.
+#
+# It was later modified by Jason Kohles <email at jasonkohles.com>
+# http://www.jasonkohles.com/ to support Module::Build installed modules
+
+# Uncomment this to turn on verbose mode.
+#export DH_VERBOSE=1
+
+# If set to a true value then MakeMaker's prompt function will
+# always return the default without waiting for user input.
+export PERL_MM_USE_DEFAULT=1
+
+PACKAGE=$(shell dh_listpackages)
+
+ifndef PERL
+PERL = /usr/bin/perl
+endif
+
+#TMP     =$(CURDIR)/debian/$(PACKAGE)
+TMP     =$(CURDIR)/debian/libjifty-dbi-perl
+
+build: build-stamp
+build-stamp:
+	dh_testdir
+
+	# Add commands to compile the package here
+	$(PERL) Makefile.PL installdirs=vendor
+	$(MAKE)
+	$(MAKE) test
+	touch build-stamp
+
+clean:
+	dh_testdir
+	dh_testroot
+
+	# Add commands to clean up after the build process here
+	-$(MAKE) clean
+	dh_clean build-stamp install-stamp
+
+install: build install-stamp
+install-stamp:
+	dh_testdir
+	dh_testroot
+	dh_clean -k
+
+	# Add commands to install the package into debian/$PACKAGE_NAME here
+	$(MAKE) install DESTDIR=$(CURDIR)/debian/libjifty-perl
+	find debian/libjifty-perl --name "*.svn*" | xargs rm -rf
+	touch install-stamp
+
+binary-arch:
+# We have nothing to do by default.
+
+binary-indep: build install
+	dh_testdir
+	dh_testroot
+#	dh_installcron
+#	dh_installmenu
+#	dh_installexamples
+	dh_installdocs README
+	dh_installchangelogs Changelog
+	dh_perl
+	dh_link
+	dh_strip
+	dh_compress
+	dh_fixperms
+	dh_installdeb
+	dh_gencontrol
+	dh_md5sums
+	dh_builddeb
+
+source diff:                                                                  
+	@echo >&2 'source and diff are obsolete - use dpkg-source -b'; false
+
+binary: binary-indep binary-arch
+.PHONY: build clean binary-indep binary-arch binary

Added: jifty/branches/schema-plugins/doc/ajax-upgraded-links
==============================================================================
--- (empty file)
+++ jifty/branches/schema-plugins/doc/ajax-upgraded-links	Mon Jan 29 21:05:02 2007
@@ -0,0 +1,39 @@
+When I click "next page", 
+
+
+    If I don't have ajax, reload the whole page, with the changed helper parameters.
+
+
+        To reload the whole page, I'm going to need:
+
+            * All args to the current page.
+            * Which args should go away
+            * Which new args should be added.
+
+
+
+        Basically, this is 
+        
+            BASE PATH: framework->current_url
+            
+            PARAMS:  framework->current_request_args
+                with this_element->new_version_params replacing
+                      this_element->current_version_params
+                
+
+
+    if I have ajax, refetch the enclosing div, with the changed parameters.
+        To reload just that section of the page, I'm going to need:
+
+            * The path to the bit I want to replace.
+            * The name of the surrounding div to replace it with?
+            * The moniker? of the section to replace.
+            * The parameters I should pass to that section.
+             Are those the same as the things for the next-page link?
+
+
+        Basically, this would be: 
+        
+            BASE PATH this_element->direct_url (no params?)
+                  and replace  this_element->current_version_params
+                  with this_element->new_version_params

Added: jifty/branches/schema-plugins/doc/building_a_par
==============================================================================
--- (empty file)
+++ jifty/branches/schema-plugins/doc/building_a_par	Mon Jan 29 21:05:02 2007
@@ -0,0 +1,93 @@
+Incomplete instructions
+
+ $ pp `find lib/ -name \*pm |perl -ne '$_ =~ s/.pm$//;print "-M ". join("::",grep { ! /(?:lib|\-)/ } split("/",$_)) '`  -I lib bin/jifty
+use warnings;
+use strict;
+use Cwd qw(cwd);
+use Module::CoreList;
+use File::Copy;
+use File::Path qw(mkpath);
+use File::Spec::Functions qw(splitdir catfile catdir);
+use CPAN;
+use CPAN::Config;
+use YAML;
+use Time::Local;
+
+ at INC = grep {! /local/} @INC; # don't want cpan.pm to make decisions based locally installed modules;
+use vars qw/$INSTALLED $FAILED $SKIP_DEPS_FOR/;
+$INSTALLED     = {};
+$FAILED        = {};
+$SKIP_DEPS_FOR = { };
+process_cpan();
+
+sub process_cpan {
+
+    #    my $self = shift;
+    my $path = cwd();
+    my @modules = @ARGV;
+
+    # We install Scalar::Util first to break a scary dependency loop.
+    mkdir "$path/.cpan";
+    mkdir "$path/.cpan/build";
+    print join "\n", @modules, "\n";
+
+    unshift @INC, '$path/lib';
+    $ENV{'PERL5LIB'} = "$path/lib";
+
+    $CPAN::Config->{build_dir}            = "$path/.cpan/build";
+    $CPAN::Config->{cpan_home}            = "$path/.cpan/build";
+    $CPAN::Config->{histfile}             = "$path/.cpan/histfile;";
+    $CPAN::Config->{keep_source_where}    = "$path/.cpan/sources";
+    $CPAN::Config->{prerequisites_policy} = "follow";
+    $CPAN::Config->{makepl_arg}
+        = "PREFIX=$path PERL5LIB=$path/lib LIB=$path/lib INSTALLMAN1DIR=$path/man/man1 INSTALLMAN3DIR=$path/man/man3 INSTALLBIN=$path/bin INSTALLSCRIPT=$path/bin";
+    $CPAN::Config->{make_install_arg} =~ s/UNINST=1//;
+
+    my @objs = map { CPAN::Shell->expand( 'Module', $_ ) } @modules;
+    for my $i ( 0 .. $#objs ) {
+        delete $objs[$i]
+            if grep { $_->{RO}->{CPAN_FILE} eq $objs[$i]->{RO}->{CPAN_FILE} }
+            @objs[ $i + 1 .. $#objs ];
+    }
+
+    foreach my $mod (@modules) {
+
+        #foreach my $mod ( grep { defined $_ } @objs ) {
+        install_mod($mod);
+    }
+    print YAML::Dump($FAILED);
+}
+
+sub install_mod {
+    my $mod_name = shift;
+    my $version = shift;
+    my $mod = CPAN::Shell->expand( 'Module', $mod_name );
+    my $first_in = Module::CoreList->first_release($mod_name => $version);
+    if ( defined $first_in and $first_in <= 5.00803 ) { print "Skipping $mod_name. It's been core since $first_in\n"; return }
+    if ( $mod->distribution->isa_perl ) { print "Skipping $mod_name. It's only in the core. OOPS\n";return}
+    if ( $INSTALLED->{ $mod->cpan_file } ) { print "Skipping $mod_name. We've already installed it\n";return}
+
+    if ( $FAILED->{ $mod->cpan_file } >= 3 ) {
+        print YAML::Dump($INSTALLED);
+        print YAML::Dump($FAILED);
+
+        die "We've tried to install "
+            . $mod->distribution->as_string
+            . " twice";
+
+    }
+
+    # Install to local
+    unless ( $SKIP_DEPS_FOR->{$mod_name} ) {
+        $mod->make;
+        my $deps = $mod->distribution->prereq_pm;
+        foreach my $dep ( keys %$deps ) {
+            install_mod($dep => $deps->{$dep});
+        }
+    }
+    #$mod->force();
+    $mod->install;
+    $INSTALLED->{ $mod->cpan_file } = 1;
+}
+
+1;

Added: jifty/branches/schema-plugins/doc/client_side_continuations
==============================================================================
--- (empty file)
+++ jifty/branches/schema-plugins/doc/client_side_continuations	Mon Jan 29 21:05:02 2007
@@ -0,0 +1,129 @@
+01:01 <audreyt> I think DNS is your programming language of choice ;)
+01:01 <obra> *snicker*
+01:01 <obra> . o O {You must have seen the cname on quit.fsck.com }
+01:02 <audreyt> rofl
+01:02 <audreyt> mm, instead of passing cookies
+01:02 <audreyt> and maintain url transparency across post and get
+01:03 <audreyt> just pass the J:C and session token in DNS!]
+01:03 <obra> *groan*
+01:03 <audreyt> deadbeef18405930.hiveminder.com/
+01:03 <obra> alex and I were talking about client-side continuation serialization today
+01:03 <obra> We're about to do continuation garbage collection
+01:03 <audreyt> instead of passing it as part of request_uri
+01:03 <audreyt> in pathinfo
+01:04 <audreyt> this guarantees auth zone separation etc
+01:04 <audreyt> (very bad idea.)
+01:04 <obra> laugh
+01:04 <obra> definitely "Worst Impractical"
+01:04 <audreyt> this is not unlike .NET Passport
+01:05 <audreyt> where you visit something.microsoft.com that redispatch to your domain
+01:05 <audreyt> but there is a reason why it failed.
+01:05 <obra> *nod* OpenId seems to be doing a bit better at it
+01:05 <audreyt> right
+01:05 <audreyt> so, client side CC
+01:05 <audreyt> in hidden fields
+01:05 <obra> I worry about the amount of content you might need to pass around. and the fact that you lose GET support
+01:05 <audreyt> HMAC_SHA1 with server digest
+01:06 <audreyt> for small continuations (practically everything)
+01:06 <audreyt> you can embed it as part of pathuri
+01:06 <obra> except our continuations aren't that small. and when deeply nested you totally lose
+01:06 <audreyt> /=/deadbeefdeadbeefbeefbeef1982398102957190824091840984124/moose.html
+01:06 <audreyt> yeah. in which case you fallback to cookie storage.
+01:07 <obra> oh. you mean having a continuation id in the url and a cookie with the content?
+01:07 <audreyt> yeah
+01:07 <audreyt> the id is the cookie key
+01:07 <audreyt> you can have multipel cookies
+01:07 <audreyt> they can expire using normal cookie expiry semantics
+01:07 <obra> and then every GET or POST pushes all the cookies to the server
+01:07 <audreyt> not neccessarily
+01:08 <obra> using the path restriction in the cookie?
+01:08 <audreyt> the path component protects you
+01:08 <audreyt> the path component protects yothat's what cookies are for
+01:08 <audreyt> ys
+01:08 <obra> hm.
+01:08 <audreyt> self validating
+01:08 <audreyt> in a sense.
+01:08 <obra> you have a compelling argument, madam.
+01:08 <obra> hm
+01:08 <audreyt> I believe it's somewhat original
+01:08 <audreyt> or at least independent invention :)
+01:08 <obra> :)
+01:09 <obra> So. the first step is that alex is getting continuations into their own database table
+01:09 <obra> alex really wanted to sign them, rather than do digest validation
+01:09 <obra> because he wants _no_ server state for a continuation
+01:09 <audreyt> a private key is a state.
+01:09 <audreyt> same as a server secret.
+01:09 <obra> er. sorry. no unique state
+01:09 <audreyt> same.
+01:10 <audreyt> if you do HMAC_SHA1, only the server secret is required
+01:10 <audreyt> not nonce
+01:10 <audreyt> global shared secret
+01:10 <obra> ahhh.
+01:10 <audreyt> cheaper than signing.
+01:10 <obra> I missed that. sorry
+01:10 <audreyt> equally strong.
+01:10 <audreyt> np :)
+01:11 <obra> It's certainly an interesting argument for "how jifty can scale up"
+01:12 <obra> if we have the cookie and url scheme, is there a reason to complicate it with sometimes having hidden form fields?
+01:12 <audreyt> only if you want per-form, as in region, continuation
+01:13 <obra> regions have their own paths ;)
+01:13 <audreyt> good then
+01:14 <audreyt> so, cookie is specced to be min 4k
+01:14 <obra> I will admit that I get twitchy about how easily this is remotely 0wnable if you capture the server secret.
+01:14 <audreyt> and at least 20 per thing
+01:14 <audreyt> that gives 80k min storage
+01:14 <audreyt> in practice the 20 limit is not enforced
+01:14 <audreyt> so you get effectively unlimited storage with splitting
+01:15 <audreyt> I'll note that if you get server secret then you can set up fake forms.
+01:15 <audreyt> both requires owner permission on the share/
+01:16 <audreyt> and really there's little point in worrying at that stage.
+01:16 <obra> that also requires dHa willing dispatcher
+01:16 <obra> Alex's proposed attack was:
+01:16 <audreyt> nod.
+01:16 <obra> push a results message at the user containing "You must change your password. click here"
+01:16 <obra> phishing attack with a valid url
+01:17 <obra> I'd probably be mollified with a randomly generated session key 
+01:17 <obra> and actually have the session key stored server-side and ~nothing else
+01:18 <obra> (Does that make sense?)
+01:19 <audreyt> thinking
+01:19 <audreyt> how is it any different than the old cookie sessionid scheme?
+01:19 <audreyt> I mean the attack
+01:20 <audreyt> persumably the action will always need old passwd as input
+01:20 <audreyt> so it can't be automated
+01:21 <audreyt> I fail to see why client side state has anything to do with this.
+01:21 <obra> jifty action results contain messages.
+01:21 <obra> jifty apps display those messages
+01:21 <obra> the messages are defined to be able to contain html
+01:21 <audreyt> you mean rogue action classes?
+01:21 <obra> imagine an attack that pushes a mini form submitting to a third party into that html
+01:22 <obra> no, someone who redirects you back to hiveminder with a continuation constructed to make it appear that you needed to change your pw
+01:22 <audreyt> it is clearly result-message scrubbing thing...
+01:22 <audreyt> anyway. back
+01:22 <audreyt> if you want to have login/logout
+01:22 <audreyt> and continuations never work across logouts
+01:23 <audreyt> then the server secret is just the session id.
+01:23 <audreyt> i.e. nonce.
+01:23 <audreyt> which you don't give the user in entirety
+01:23 <audreyt> just as you observed
+01:23 <obra> nod
+01:23 <obra> I think that works
+01:23 <audreyt> and for public non-currentuser-related requests
+01:23 <audreyt> it may make sense to have a sessionless form
+01:24 <audreyt> where bookmarks may be shared.
+01:24 <obra> The case that didn't work in my head was with a global nonce.
+01:24 <audreyt> but I think the use case is rarer
+01:24 <audreyt> I think per-session makes most sense.
+01:24 <obra> indeed. It's been my conjecture that even anonymous users can be given sessions.
+01:24 <audreyt> if Inever logout, my bookmarks always work
+01:25 <audreyt> if I logout, they only work if I-or the server- explicitly requested affinity
+01:25 <obra> and the server has the option to deny that request 
+01:25 <audreyt> otherwise it's thrown away, and the logout link should reset the continuation cookies.
+01:25 <audreyt> yes.
+01:25 <audreyt> ok, very good design, I think.
+01:25 <obra> I'm reasonably happy with that, I think
+01:26 <audreyt> woot :)
+01:26 <audreyt> now I must run to $job
+01:26 <obra> shall we throw this log in jifty/doc?
+01:26 <audreyt> already horribly late ;)
+01:26 <audreyt> sure, please do
+01:26 <obra> oops. so sorry.

Added: jifty/branches/schema-plugins/doc/command_naming
==============================================================================
--- (empty file)
+++ jifty/branches/schema-plugins/doc/command_naming	Mon Jan 29 21:05:02 2007
@@ -0,0 +1,10 @@
+Current commands are all nouns. we should be moving to simple active verbs
+    
+    jifty server -> jifty run
+    jifty fastcgi -> jifty run --fastcgi
+    jifty action -> jifty create --action=
+    jifty app   -> jifty create --app=
+    jifty model -> Jifty create --model=
+
+    jifty schema -> jifty setup --schema
+    jifty po    -> jifty setup --lexicon / jifty create --lexicon

Added: jifty/branches/schema-plugins/doc/declarative-test-design
==============================================================================
--- (empty file)
+++ jifty/branches/schema-plugins/doc/declarative-test-design	Mon Jan 29 21:05:02 2007
@@ -0,0 +1,128 @@
+# -*- mode: cperl -*-
+
+# A ``setup'' block indicates tests that must pass for any of the
+# remaining tests to continue.
+
+setup {
+    BTDT::Test->log_in;
+    expect_url(qr{/todo});
+    follow_link 'Groups';
+    expect_url(qr{/groups});
+    expect_content('alpha');
+
+    # These are custom local methods; not Test::WWW::Whatever ones.
+    make_and_verify_group($mech, name => 'my folks', desc => 'stuff');
+    make_and_verify_group($mech, name => 'blue pants', desc => 'some description');
+    make_and_verify_group_trimming($mech, name => '   leading and trailing spaces   ', desc => '  more spaces here  ');
+
+    make_and_verify_group($mech, name => 'other folks');
+}
+
+# Each ``test'' block is its own test. If anything fails, we abort the
+# current test block, and continue with the next one.
+
+test {
+    follow_link 'Groups';
+    follow_link 'New Group';
+    submit_action 'newgroup', { name => 'my folks' };
+
+    expect_url { not => qr{groups/\d+/members} };
+    expect_url qr{/groups/create};
+    find_input { value => "my folks" };
+    expect_content qr{Sorry, but someone else beat you to that name};
+};
+
+test {
+    follow_link 'my folks';
+    follow_link 'Members';
+
+    expect_url qr{/groups/\d+/members};
+    expect_content 'Manage group members';
+    expect_content 'my folks';
+    expect_content qr{Good Test *organizer}
+};
+
+test {
+    follow_link 'my folks';
+    follow_link 'My tasks';
+    follow_link 'Braindump';
+    expect_content 'See more syntax for braindump';
+
+    fill_action 'quickcreate', { text => 'Buy new computer [personal money]' };
+    click { button => 'Create' };
+
+    expect { content => 'Buy new computer' };
+    expect_content_not 'See more syntax for braindump';
+
+    follow_link 'my folks' => 'My tasks' => 'Braindump';
+    submit_action 'quickcreate',
+      { text => 'Buy new computer [personal money]' },
+      { button => 'Create' };
+
+    click 'Edit';
+
+    submit_action find_action('BTDT::Action::UpdateTask'),
+        { owner_id => 'otheruser at example.com' };
+}
+
+test {
+    new_session {
+        log_in 'otheruser at example.com', 'something';
+        click 'unaccepted';
+        page { content => 'Pay off Mafia' };
+        click 'Pay off Mafia';
+
+        # Manual submit_action
+        find_element { name => qr{J:A-(?:\d+)?accept} };
+        submit_form { 'J:A:F-accepted-accept' => 1 };
+
+        page { content       => 'Task accepted',
+               content_lacks => 'denied' };
+
+    };
+};
+
+# Various ways of specifying tests should only run under certain
+# platforms
+
+with ('javascript') => test {
+    
+};
+
+test {
+    browser 'iexplore';
+};
+
+test {
+    browser 'WWW::Mechanize';
+};
+
+test {
+    need_feature 'XMLHTTPRequest';
+};
+
+
+run_all;
+
+
+# A syntax idea from jesse:
+
+flow "Check to see if the user can login" => test {
+    get '/';
+    element '//body' matches /You're not logged in/;
+
+    follow link 'Login';
+
+    my $login_form = element id 'login-form'
+
+    fill $login_form  =>  { 
+        email => 'jesse at fsck.com',
+        password => 'I hate you'
+    }
+
+    click button 'Login!';
+
+}
+
+
+

Added: jifty/branches/schema-plugins/doc/edit-in-place
==============================================================================
--- (empty file)
+++ jifty/branches/schema-plugins/doc/edit-in-place	Mon Jan 29 21:05:02 2007
@@ -0,0 +1,22 @@
+# These are dispatcher rules that halos and error handling need to be
+# able to edit files in place.  These should become a plugin of some
+# sort, when we have that infrastructure.
+
+before '*', run {
+    Jifty->api->allow(qr/^Jifty::Action::Devel/)
+      if Jifty->config->framework('DevelMode');
+};
+
+on qr'^/__jifty/edit/(.*?)/(.*)$', run {
+    my $editor = Jifty->web->new_action(
+        class     => 'Jifty::Action::Devel::FileEditor',
+        moniker   => 'editpage',
+        arguments => {
+            source_path => $2,
+            file_type   => $1,
+        }
+    );
+
+    set editor => $editor;
+    show '/__jifty/edit_file';
+};

Added: jifty/branches/schema-plugins/doc/examples/CounterDemo/Makefile.PL
==============================================================================
--- (empty file)
+++ jifty/branches/schema-plugins/doc/examples/CounterDemo/Makefile.PL	Mon Jan 29 21:05:02 2007
@@ -0,0 +1,6 @@
+use inc::Module::Install;
+name('CounterDemo');
+version('0.01');
+requires('Jifty' => '0.60615');
+
+WriteAll;

Added: jifty/branches/schema-plugins/doc/examples/CounterDemo/bin/jifty
==============================================================================
--- (empty file)
+++ jifty/branches/schema-plugins/doc/examples/CounterDemo/bin/jifty	Mon Jan 29 21:05:02 2007
@@ -0,0 +1,18 @@
+#!/usr/bin/env perl
+
+eval 'exec /usr/bin/env perl  -S $0 ${1+"$@"}'
+    if 0; # not running under some shell
+use warnings;
+use strict;
+use File::Basename qw(dirname); 
+use UNIVERSAL::require;
+
+BEGIN {
+    Jifty::Util->require or die $UNIVERSAL::require::ERROR;
+    my $root = Jifty::Util->app_root;
+    unshift @INC, "$root/lib" if ($root);
+}
+
+use Jifty::Script;
+$SIG{INT} = $SIG{TERM} = sub { warn "Stopped\n"; exit; };
+Jifty::Script->dispatch();

Added: jifty/branches/schema-plugins/doc/examples/CounterDemo/etc/config.yml
==============================================================================
--- (empty file)
+++ jifty/branches/schema-plugins/doc/examples/CounterDemo/etc/config.yml	Mon Jan 29 21:05:02 2007
@@ -0,0 +1,36 @@
+--- 
+framework: 
+  AdminMode: 0
+  ApplicationClass: CounterDemo
+  ApplicationName: CounterDemo
+  Database: 
+    Database: counterdemo
+    Driver: SQLite
+    Host: localhost
+    Password: ''
+    RecordBaseClass: Jifty::DBI::Record::Cachable
+    User: ''
+    Version: 0.0.1
+  DevelMode: 1
+  L10N: 
+    PoDir: share/po
+  LogLevel: INFO
+  Mailer: Sendmail
+  MailerArgs: []
+
+  Plugins: []
+
+  Web: 
+    BaseURL: http://localhost
+    DataDir: var/mason
+    Globals: []
+
+    MasonConfig: 
+      autoflush: 0
+      default_escape_flags: h
+      error_format: text
+      error_mode: fatal
+    Port: 8888
+    ServeStaticFiles: 1
+    StaticRoot: share/web/static
+    TemplateRoot: share/web/templates

Added: jifty/branches/schema-plugins/doc/examples/CounterDemo/share/web/templates/index.html
==============================================================================
--- (empty file)
+++ jifty/branches/schema-plugins/doc/examples/CounterDemo/share/web/templates/index.html	Mon Jan 29 21:05:02 2007
@@ -0,0 +1,23 @@
+<%args>
+$counter => 0
+</%args>
+<%init>
+my $request;
+
+$request = Jifty::Request->new( path => Jifty->web->request->path );
+$request->argument( counter => $counter + 1 );
+my $up = Jifty::Continuation->new( request => $request );
+
+$request = Jifty::Request->new( path => Jifty->web->request->path );
+$request->argument( counter => $counter - 1 );
+my $down = Jifty::Continuation->new( request => $request );
+</%init>
+
+<&| /_elements/wrapper, title => "Continuations counter demo" &>
+
+<h1> The counter is: <% $counter %></h1>
+
+<% Jifty->web->link(call => $down, label => '--') %>
+<% Jifty->web->link(call => $up, label => '++') %>
+
+</&>

Added: jifty/branches/schema-plugins/doc/examples/CounterDemo/t/00-counter-test.t
==============================================================================
--- (empty file)
+++ jifty/branches/schema-plugins/doc/examples/CounterDemo/t/00-counter-test.t	Mon Jan 29 21:05:02 2007
@@ -0,0 +1,53 @@
+#!/usr/bin/env perl
+use strict;
+use warnings;
+
+=head1 DESCRIPTION
+
+Basic continuation counter test.
+
+=cut
+
+use Jifty::Test tests => 20;
+use Jifty::Test::WWW::Mechanize;
+
+my $server = Jifty::Test->make_server;
+
+my $URL = $server->started_ok();
+
+ok($URL, "Started the test server");
+
+my $mech = Jifty::Test::WWW::Mechanize->new();
+
+$mech->get_ok($URL, "Got the home page");
+
+$mech->content_contains('The counter is: 0', "Counter starts at 0");
+ok($mech->find_link(text => "++"), "Found the increment link");
+
+$mech->follow_link_ok(text => "++");
+$mech->content_contains('The counter is: 1', "Incremented the counter");
+
+$mech->follow_link_ok(text => "++");
+$mech->content_contains('The counter is: 2', "Incremented the counter");
+
+$mech->follow_link_ok(text => "--");
+$mech->content_contains('The counter is: 1', "Decremented the counter");
+
+$mech->follow_link_ok(text => "--");
+$mech->follow_link_ok(text => "--");
+$mech->follow_link_ok(text => "--");
+$mech->follow_link_ok(text => "--");
+
+$mech->content_contains('The counter is: -3', "Decremented the counter 4 times");
+
+$mech->back;
+$mech->back;
+
+$mech->content_contains('The counter is: -1', "Back at -1");
+
+$mech->follow_link_ok(text => "--");
+
+$mech->content_contains('The counter is: -2', "Going back then following links DTRT");
+
+$mech->get($URL);
+$mech->content_contains('The counter is: 0', "Loading the initial page again resets the counter");

Added: jifty/branches/schema-plugins/doc/jifty-action-record-search
==============================================================================
--- (empty file)
+++ jifty/branches/schema-plugins/doc/jifty-action-record-search	Mon Jan 29 21:05:02 2007
@@ -0,0 +1,59 @@
+-*- mode: outline; outline-regexp: "\\s *\\*+" -*-
+
+Jifty::Action::Record::Search should take arguments and return a
+FooCollection as the q{search} field of its q{content}.
+
+It will generate arguments for each field, according to the SQL type
+of the field:
+
+* text
+ * I<field>, I<field>_not
+  * Do substring searching on the given field
+  * This is case sensitive.
+
+ * I<field_is>
+  * ? Does exact matching ?
+
+* time, date, or datetime
+ * T<field>_after, I<field>_before
+ * T<field> for exact matching?
+
+* int
+ * I<field>
+  * Exact matching
+
+ * I<field_gt>
+ * I<field_lt>
+  * Less than/greater than
+
+ * I<field_gte>
+ * I<field_lte>
+  * These are perhaps superfluous, but could be convenient.
+  * (I want auto-loaded arguments ...)
+
+* boolean
+ * I<field>
+  * Can be true, false, or undefined
+
+
+* refers_to an object
+ * I<field>
+ * I<field_not>
+ * Accept ids
+  * ? Generate valid_values for this ?
+
+* refers_to a collection
+ * Do nothing?
+ * I<field>_contains ?
+ * I<field>_lacks ?
+
+******* 
+
+* Validators and canonicalizers
+ * Never use validators
+ * Use canonicalizers on any "exact match" fields
+ * What's the right behaviour on substring/comparison match?
+
+* valid_values
+ * valid_values should remain valid_values for any exact match fields,
+ * become available_values otherwise

Added: jifty/branches/schema-plugins/doc/jifty-dispatcher.graffle
==============================================================================
--- (empty file)
+++ jifty/branches/schema-plugins/doc/jifty-dispatcher.graffle	Mon Jan 29 21:05:02 2007
@@ -0,0 +1,2641 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>ActiveLayerIndex</key>
+	<integer>0</integer>
+	<key>AutoAdjust</key>
+	<true/>
+	<key>CanvasColor</key>
+	<dict>
+		<key>w</key>
+		<string>1</string>
+	</dict>
+	<key>CanvasOrigin</key>
+	<string>{0, 0}</string>
+	<key>CanvasScale</key>
+	<real>1</real>
+	<key>ColumnAlign</key>
+	<integer>1</integer>
+	<key>ColumnSpacing</key>
+	<real>36</real>
+	<key>CreationDate</key>
+	<string>2006-07-09 18:16:50 -0400</string>
+	<key>Creator</key>
+	<string>Audrey Tang</string>
+	<key>DisplayScale</key>
+	<string>1 cm = 1 cm</string>
+	<key>GraphDocumentVersion</key>
+	<integer>5</integer>
+	<key>GraphicsList</key>
+	<array>
+		<dict>
+			<key>Bounds</key>
+			<string>{{1835, 198}, {72, 45}}</string>
+			<key>Class</key>
+			<string>ShapedGraphic</string>
+			<key>FontInfo</key>
+			<dict>
+				<key>Color</key>
+				<dict>
+					<key>w</key>
+					<string>0</string>
+				</dict>
+				<key>Font</key>
+				<string>Helvetica</string>
+				<key>NSKern</key>
+				<real>0.0</real>
+				<key>Size</key>
+				<real>12</real>
+			</dict>
+			<key>ID</key>
+			<integer>56</integer>
+			<key>Shape</key>
+			<string>Rectangle</string>
+			<key>Style</key>
+			<dict>
+				<key>fill</key>
+				<dict>
+					<key>GradientColor</key>
+					<dict>
+						<key>w</key>
+						<string>0.666667</string>
+					</dict>
+				</dict>
+			</dict>
+			<key>Text</key>
+			<dict>
+				<key>Text</key>
+				<string>{\rtf1\mac\ansicpg10002\cocoartf824\cocoasubrtf410
+{\fonttbl\f0\fswiss\fcharset77 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc
+
+\f0\fs24 \cf0 \expnd0\expndtw0\kerning0
+Partial orders between mounted dispatchers}</string>
+			</dict>
+		</dict>
+		<dict>
+			<key>Bounds</key>
+			<string>{{1835, 117}, {72, 45}}</string>
+			<key>Class</key>
+			<string>ShapedGraphic</string>
+			<key>FontInfo</key>
+			<dict>
+				<key>Color</key>
+				<dict>
+					<key>w</key>
+					<string>0</string>
+				</dict>
+				<key>Font</key>
+				<string>Helvetica</string>
+				<key>NSKern</key>
+				<real>0.0</real>
+				<key>Size</key>
+				<real>12</real>
+			</dict>
+			<key>ID</key>
+			<integer>54</integer>
+			<key>Shape</key>
+			<string>Rectangle</string>
+			<key>Style</key>
+			<dict>
+				<key>fill</key>
+				<dict>
+					<key>GradientColor</key>
+					<dict>
+						<key>w</key>
+						<string>0.666667</string>
+					</dict>
+				</dict>
+			</dict>
+			<key>Text</key>
+			<dict>
+				<key>Text</key>
+				<string>{\rtf1\mac\ansicpg10002\cocoartf824\cocoasubrtf410
+{\fonttbl\f0\fswiss\fcharset77 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc
+
+\f0\fs24 \cf0 \expnd0\expndtw0\kerning0
+plugin}</string>
+			</dict>
+		</dict>
+		<dict>
+			<key>Bounds</key>
+			<string>{{809, 198}, {72, 45}}</string>
+			<key>Class</key>
+			<string>ShapedGraphic</string>
+			<key>FontInfo</key>
+			<dict>
+				<key>Color</key>
+				<dict>
+					<key>w</key>
+					<string>0</string>
+				</dict>
+				<key>Font</key>
+				<string>Helvetica</string>
+				<key>NSKern</key>
+				<real>0.0</real>
+				<key>Size</key>
+				<real>12</real>
+			</dict>
+			<key>ID</key>
+			<integer>123</integer>
+			<key>Shape</key>
+			<string>Rectangle</string>
+			<key>Style</key>
+			<dict>
+				<key>fill</key>
+				<dict>
+					<key>GradientColor</key>
+					<dict>
+						<key>w</key>
+						<string>0.666667</string>
+					</dict>
+				</dict>
+			</dict>
+			<key>Text</key>
+			<dict>
+				<key>Text</key>
+				<string>{\rtf1\mac\ansicpg10002\cocoartf824\cocoasubrtf410
+{\fonttbl\f0\fswiss\fcharset77 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc
+
+\f0\fs24 \cf0 \expnd0\expndtw0\kerning0
+Topic}</string>
+			</dict>
+		</dict>
+		<dict>
+			<key>Bounds</key>
+			<string>{{1673, 198}, {72, 45}}</string>
+			<key>Class</key>
+			<string>ShapedGraphic</string>
+			<key>FontInfo</key>
+			<dict>
+				<key>Color</key>
+				<dict>
+					<key>w</key>
+					<string>0</string>
+				</dict>
+				<key>Font</key>
+				<string>Helvetica</string>
+				<key>NSKern</key>
+				<real>0.0</real>
+				<key>Size</key>
+				<real>12</real>
+			</dict>
+			<key>ID</key>
+			<integer>121</integer>
+			<key>Shape</key>
+			<string>Rectangle</string>
+			<key>Style</key>
+			<dict>
+				<key>fill</key>
+				<dict>
+					<key>GradientColor</key>
+					<dict>
+						<key>w</key>
+						<string>0.666667</string>
+					</dict>
+				</dict>
+			</dict>
+			<key>Text</key>
+			<dict>
+				<key>Text</key>
+				<string>{\rtf1\mac\ansicpg10002\cocoartf824\cocoasubrtf410
+{\fonttbl\f0\fswiss\fcharset77 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc
+
+\f0\fs24 \cf0 \expnd0\expndtw0\kerning0
+Flow control}</string>
+			</dict>
+		</dict>
+		<dict>
+			<key>Bounds</key>
+			<string>{{1565, 198}, {72, 45}}</string>
+			<key>Class</key>
+			<string>ShapedGraphic</string>
+			<key>FontInfo</key>
+			<dict>
+				<key>Color</key>
+				<dict>
+					<key>w</key>
+					<string>0</string>
+				</dict>
+				<key>Font</key>
+				<string>Helvetica</string>
+				<key>NSKern</key>
+				<real>0.0</real>
+				<key>Size</key>
+				<real>12</real>
+			</dict>
+			<key>ID</key>
+			<integer>117</integer>
+			<key>Shape</key>
+			<string>Rectangle</string>
+			<key>Style</key>
+			<dict>
+				<key>fill</key>
+				<dict>
+					<key>GradientColor</key>
+					<dict>
+						<key>w</key>
+						<string>0.666667</string>
+					</dict>
+				</dict>
+			</dict>
+			<key>Text</key>
+			<dict>
+				<key>Text</key>
+				<string>{\rtf1\mac\ansicpg10002\cocoartf824\cocoasubrtf410
+{\fonttbl\f0\fswiss\fcharset77 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc
+
+\f0\fs24 \cf0 \expnd0\expndtw0\kerning0
+Goto (for "before/on" stage)}</string>
+			</dict>
+		</dict>
+		<dict>
+			<key>Bounds</key>
+			<string>{{1457, 198}, {72, 45}}</string>
+			<key>Class</key>
+			<string>ShapedGraphic</string>
+			<key>FontInfo</key>
+			<dict>
+				<key>Color</key>
+				<dict>
+					<key>w</key>
+					<string>0</string>
+				</dict>
+				<key>Font</key>
+				<string>Helvetica</string>
+				<key>NSKern</key>
+				<real>0.0</real>
+				<key>Size</key>
+				<real>12</real>
+			</dict>
+			<key>ID</key>
+			<integer>111</integer>
+			<key>Shape</key>
+			<string>Rectangle</string>
+			<key>Style</key>
+			<dict>
+				<key>fill</key>
+				<dict>
+					<key>GradientColor</key>
+					<dict>
+						<key>w</key>
+						<string>0.666667</string>
+					</dict>
+				</dict>
+			</dict>
+			<key>Text</key>
+			<dict>
+				<key>Text</key>
+				<string>{\rtf1\mac\ansicpg10002\cocoartf824\cocoasubrtf410
+{\fonttbl\f0\fswiss\fcharset77 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc
+
+\f0\fs24 \cf0 \expnd0\expndtw0\kerning0
+=request params initially}</string>
+			</dict>
+		</dict>
+		<dict>
+			<key>Bounds</key>
+			<string>{{1349, 198}, {72, 45}}</string>
+			<key>Class</key>
+			<string>ShapedGraphic</string>
+			<key>FontInfo</key>
+			<dict>
+				<key>Color</key>
+				<dict>
+					<key>w</key>
+					<string>0</string>
+				</dict>
+				<key>Font</key>
+				<string>Helvetica</string>
+				<key>NSKern</key>
+				<real>0.0</real>
+				<key>Size</key>
+				<real>12</real>
+			</dict>
+			<key>ID</key>
+			<integer>109</integer>
+			<key>Shape</key>
+			<string>Rectangle</string>
+			<key>Style</key>
+			<dict>
+				<key>fill</key>
+				<dict>
+					<key>GradientColor</key>
+					<dict>
+						<key>w</key>
+						<string>0.666667</string>
+					</dict>
+				</dict>
+			</dict>
+			<key>Text</key>
+			<dict>
+				<key>Text</key>
+				<string>{\rtf1\mac\ansicpg10002\cocoartf824\cocoasubrtf410
+{\fonttbl\f0\fswiss\fcharset77 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc
+
+\f0\fs24 \cf0 \expnd0\expndtw0\kerning0
+Stash manipulation}</string>
+			</dict>
+		</dict>
+		<dict>
+			<key>Bounds</key>
+			<string>{{1727, 117}, {72, 45}}</string>
+			<key>Class</key>
+			<string>ShapedGraphic</string>
+			<key>FontInfo</key>
+			<dict>
+				<key>Color</key>
+				<dict>
+					<key>w</key>
+					<string>0</string>
+				</dict>
+				<key>Font</key>
+				<string>Helvetica</string>
+				<key>NSKern</key>
+				<real>0.0</real>
+				<key>Size</key>
+				<real>12</real>
+			</dict>
+			<key>ID</key>
+			<integer>131</integer>
+			<key>Shape</key>
+			<string>Rectangle</string>
+			<key>Style</key>
+			<dict>
+				<key>fill</key>
+				<dict>
+					<key>GradientColor</key>
+					<dict>
+						<key>w</key>
+						<string>0.666667</string>
+					</dict>
+				</dict>
+			</dict>
+			<key>Text</key>
+			<dict>
+				<key>Text</key>
+				<string>{\rtf1\mac\ansicpg10002\cocoartf824\cocoasubrtf410
+{\fonttbl\f0\fswiss\fcharset77 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc
+
+\f0\fs24 \cf0 \expnd0\expndtw0\kerning0
+already_run}</string>
+			</dict>
+		</dict>
+		<dict>
+			<key>Bounds</key>
+			<string>{{1619, 117}, {72, 45}}</string>
+			<key>Class</key>
+			<string>ShapedGraphic</string>
+			<key>FontInfo</key>
+			<dict>
+				<key>Color</key>
+				<dict>
+					<key>w</key>
+					<string>0</string>
+				</dict>
+				<key>Font</key>
+				<string>Helvetica</string>
+				<key>NSKern</key>
+				<real>0.0</real>
+				<key>Size</key>
+				<real>12</real>
+			</dict>
+			<key>ID</key>
+			<integer>119</integer>
+			<key>Shape</key>
+			<string>Rectangle</string>
+			<key>Style</key>
+			<dict>
+				<key>fill</key>
+				<dict>
+					<key>GradientColor</key>
+					<dict>
+						<key>w</key>
+						<string>0.666667</string>
+					</dict>
+				</dict>
+			</dict>
+			<key>Text</key>
+			<dict>
+				<key>Text</key>
+				<string>{\rtf1\mac\ansicpg10002\cocoartf824\cocoasubrtf410
+{\fonttbl\f0\fswiss\fcharset77 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc
+
+\f0\fs24 \cf0 \expnd0\expndtw0\kerning0
+next_rule/last_rule/abort}</string>
+			</dict>
+		</dict>
+		<dict>
+			<key>Bounds</key>
+			<string>{{1511, 117}, {72, 45}}</string>
+			<key>Class</key>
+			<string>ShapedGraphic</string>
+			<key>FontInfo</key>
+			<dict>
+				<key>Color</key>
+				<dict>
+					<key>w</key>
+					<string>0</string>
+				</dict>
+				<key>Font</key>
+				<string>Helvetica</string>
+				<key>NSKern</key>
+				<real>0.0</real>
+				<key>Size</key>
+				<real>12</real>
+			</dict>
+			<key>ID</key>
+			<integer>113</integer>
+			<key>Shape</key>
+			<string>Rectangle</string>
+			<key>Style</key>
+			<dict>
+				<key>fill</key>
+				<dict>
+					<key>GradientColor</key>
+					<dict>
+						<key>w</key>
+						<string>0.666667</string>
+					</dict>
+				</dict>
+			</dict>
+			<key>Text</key>
+			<dict>
+				<key>Text</key>
+				<string>{\rtf1\mac\ansicpg10002\cocoartf824\cocoasubrtf410
+{\fonttbl\f0\fswiss\fcharset77 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc
+
+\f0\fs24 \cf0 \expnd0\expndtw0\kerning0
+show/redirect/dispatch}</string>
+			</dict>
+		</dict>
+		<dict>
+			<key>Bounds</key>
+			<string>{{1403, 117}, {72, 45}}</string>
+			<key>Class</key>
+			<string>ShapedGraphic</string>
+			<key>FontInfo</key>
+			<dict>
+				<key>Color</key>
+				<dict>
+					<key>w</key>
+					<string>0</string>
+				</dict>
+				<key>Font</key>
+				<string>Helvetica</string>
+				<key>NSKern</key>
+				<real>0.0</real>
+				<key>Size</key>
+				<real>12</real>
+			</dict>
+			<key>ID</key>
+			<integer>106</integer>
+			<key>Shape</key>
+			<string>Rectangle</string>
+			<key>Style</key>
+			<dict>
+				<key>fill</key>
+				<dict>
+					<key>GradientColor</key>
+					<dict>
+						<key>w</key>
+						<string>0.666667</string>
+					</dict>
+				</dict>
+			</dict>
+			<key>Text</key>
+			<dict>
+				<key>Text</key>
+				<string>{\rtf1\mac\ansicpg10002\cocoartf824\cocoasubrtf410
+{\fonttbl\f0\fswiss\fcharset77 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc
+
+\f0\fs24 \cf0 \expnd0\expndtw0\kerning0
+get/set/default/del}</string>
+			</dict>
+		</dict>
+		<dict>
+			<key>Bounds</key>
+			<string>{{1295, 117}, {72, 45}}</string>
+			<key>Class</key>
+			<string>ShapedGraphic</string>
+			<key>FontInfo</key>
+			<dict>
+				<key>Color</key>
+				<dict>
+					<key>w</key>
+					<string>0</string>
+				</dict>
+				<key>Font</key>
+				<string>Helvetica</string>
+				<key>NSKern</key>
+				<real>0.0</real>
+				<key>Size</key>
+				<real>12</real>
+			</dict>
+			<key>ID</key>
+			<integer>2</integer>
+			<key>Shape</key>
+			<string>Rectangle</string>
+			<key>Style</key>
+			<dict>
+				<key>fill</key>
+				<dict>
+					<key>GradientColor</key>
+					<dict>
+						<key>w</key>
+						<string>0.666667</string>
+					</dict>
+				</dict>
+			</dict>
+			<key>Text</key>
+			<dict>
+				<key>Text</key>
+				<string>{\rtf1\mac\ansicpg10002\cocoartf824\cocoasubrtf410
+{\fonttbl\f0\fswiss\fcharset77 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc
+
+\f0\fs24 \cf0 \expnd0\expndtw0\kerning0
+when/under}</string>
+			</dict>
+		</dict>
+		<dict>
+			<key>Bounds</key>
+			<string>{{1295, 279}, {72, 45}}</string>
+			<key>Class</key>
+			<string>ShapedGraphic</string>
+			<key>FontInfo</key>
+			<dict>
+				<key>Color</key>
+				<dict>
+					<key>w</key>
+					<string>0</string>
+				</dict>
+				<key>Font</key>
+				<string>Helvetica</string>
+				<key>NSKern</key>
+				<real>0.0</real>
+				<key>Size</key>
+				<real>12</real>
+			</dict>
+			<key>ID</key>
+			<integer>103</integer>
+			<key>Shape</key>
+			<string>Rectangle</string>
+			<key>Style</key>
+			<dict>
+				<key>fill</key>
+				<dict>
+					<key>GradientColor</key>
+					<dict>
+						<key>w</key>
+						<string>0.666667</string>
+					</dict>
+				</dict>
+			</dict>
+			<key>Text</key>
+			<dict>
+				<key>Text</key>
+				<string>{\rtf1\mac\ansicpg10002\cocoartf824\cocoasubrtf410
+{\fonttbl\f0\fswiss\fcharset77 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc
+
+\f0\fs24 \cf0 \expnd0\expndtw0\kerning0
+\{child; child\}}</string>
+			</dict>
+		</dict>
+		<dict>
+			<key>Bounds</key>
+			<string>{{1187, 279}, {72, 45}}</string>
+			<key>Class</key>
+			<string>ShapedGraphic</string>
+			<key>FontInfo</key>
+			<dict>
+				<key>Color</key>
+				<dict>
+					<key>w</key>
+					<string>0</string>
+				</dict>
+				<key>Font</key>
+				<string>Helvetica</string>
+				<key>NSKern</key>
+				<real>0.0</real>
+				<key>Size</key>
+				<real>12</real>
+			</dict>
+			<key>ID</key>
+			<integer>101</integer>
+			<key>Shape</key>
+			<string>Rectangle</string>
+			<key>Style</key>
+			<dict>
+				<key>fill</key>
+				<dict>
+					<key>GradientColor</key>
+					<dict>
+						<key>w</key>
+						<string>0.666667</string>
+					</dict>
+				</dict>
+			</dict>
+			<key>Text</key>
+			<dict>
+				<key>Text</key>
+				<string>{\rtf1\mac\ansicpg10002\cocoartf824\cocoasubrtf410
+{\fonttbl\f0\fswiss\fcharset77 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc
+
+\f0\fs24 \cf0 \expnd0\expndtw0\kerning0
+[child, child]}</string>
+			</dict>
+		</dict>
+		<dict>
+			<key>Bounds</key>
+			<string>{{1241, 198}, {72, 45}}</string>
+			<key>Class</key>
+			<string>ShapedGraphic</string>
+			<key>FontInfo</key>
+			<dict>
+				<key>Color</key>
+				<dict>
+					<key>w</key>
+					<string>0</string>
+				</dict>
+				<key>Font</key>
+				<string>Helvetica</string>
+				<key>NSKern</key>
+				<real>0.0</real>
+				<key>Size</key>
+				<real>12</real>
+			</dict>
+			<key>ID</key>
+			<integer>99</integer>
+			<key>Shape</key>
+			<string>Rectangle</string>
+			<key>Style</key>
+			<dict>
+				<key>fill</key>
+				<dict>
+					<key>GradientColor</key>
+					<dict>
+						<key>w</key>
+						<string>0.666667</string>
+					</dict>
+				</dict>
+			</dict>
+			<key>Text</key>
+			<dict>
+				<key>Text</key>
+				<string>{\rtf1\mac\ansicpg10002\cocoartf824\cocoasubrtf410
+{\fonttbl\f0\fswiss\fcharset77 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc
+
+\f0\fs24 \cf0 \expnd0\expndtw0\kerning0
+Numerous children}</string>
+			</dict>
+		</dict>
+		<dict>
+			<key>Bounds</key>
+			<string>{{1133, 198}, {72, 45}}</string>
+			<key>Class</key>
+			<string>ShapedGraphic</string>
+			<key>FontInfo</key>
+			<dict>
+				<key>Color</key>
+				<dict>
+					<key>w</key>
+					<string>0</string>
+				</dict>
+				<key>Font</key>
+				<string>Helvetica</string>
+				<key>NSKern</key>
+				<real>0.0</real>
+				<key>Size</key>
+				<real>12</real>
+			</dict>
+			<key>ID</key>
+			<integer>89</integer>
+			<key>Shape</key>
+			<string>Rectangle</string>
+			<key>Style</key>
+			<dict>
+				<key>fill</key>
+				<dict>
+					<key>GradientColor</key>
+					<dict>
+						<key>w</key>
+						<string>0.666667</string>
+					</dict>
+				</dict>
+			</dict>
+			<key>Text</key>
+			<dict>
+				<key>Text</key>
+				<string>{\rtf1\mac\ansicpg10002\cocoartf824\cocoasubrtf410
+{\fonttbl\f0\fswiss\fcharset77 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc
+
+\f0\fs24 \cf0 \expnd0\expndtw0\kerning0
+run \{...\} \\&amp;sub 'sub'}</string>
+			</dict>
+		</dict>
+		<dict>
+			<key>Bounds</key>
+			<string>{{1025, 360}, {72, 45}}</string>
+			<key>Class</key>
+			<string>ShapedGraphic</string>
+			<key>FontInfo</key>
+			<dict>
+				<key>Color</key>
+				<dict>
+					<key>w</key>
+					<string>0</string>
+				</dict>
+				<key>Font</key>
+				<string>Helvetica</string>
+				<key>NSKern</key>
+				<real>0.0</real>
+				<key>Size</key>
+				<real>12</real>
+			</dict>
+			<key>ID</key>
+			<integer>70</integer>
+			<key>Shape</key>
+			<string>Rectangle</string>
+			<key>Style</key>
+			<dict>
+				<key>fill</key>
+				<dict>
+					<key>GradientColor</key>
+					<dict>
+						<key>w</key>
+						<string>0.666667</string>
+					</dict>
+				</dict>
+			</dict>
+			<key>Text</key>
+			<dict>
+				<key>Text</key>
+				<string>{\rtf1\mac\ansicpg10002\cocoartf824\cocoasubrtf410
+{\fonttbl\f0\fswiss\fcharset77 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc
+
+\f0\fs24 \cf0 \expnd0\expndtw0\kerning0
+/foo/*/\{bar,baz\}}</string>
+			</dict>
+		</dict>
+		<dict>
+			<key>Bounds</key>
+			<string>{{1025, 279}, {72, 45}}</string>
+			<key>Class</key>
+			<string>ShapedGraphic</string>
+			<key>FontInfo</key>
+			<dict>
+				<key>Color</key>
+				<dict>
+					<key>w</key>
+					<string>0</string>
+				</dict>
+				<key>Font</key>
+				<string>Helvetica</string>
+				<key>NSKern</key>
+				<real>0.0</real>
+				<key>Size</key>
+				<real>12</real>
+			</dict>
+			<key>ID</key>
+			<integer>85</integer>
+			<key>Shape</key>
+			<string>Rectangle</string>
+			<key>Style</key>
+			<dict>
+				<key>fill</key>
+				<dict>
+					<key>GradientColor</key>
+					<dict>
+						<key>w</key>
+						<string>0.666667</string>
+					</dict>
+				</dict>
+			</dict>
+			<key>Text</key>
+			<dict>
+				<key>Text</key>
+				<string>{\rtf1\mac\ansicpg10002\cocoartf824\cocoasubrtf410
+{\fonttbl\f0\fswiss\fcharset77 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc
+
+\f0\fs24 \cf0 \expnd0\expndtw0\kerning0
+(may be compiled from shellglob)}</string>
+			</dict>
+		</dict>
+		<dict>
+			<key>Bounds</key>
+			<string>{{1025, 198}, {72, 45}}</string>
+			<key>Class</key>
+			<string>ShapedGraphic</string>
+			<key>FontInfo</key>
+			<dict>
+				<key>Color</key>
+				<dict>
+					<key>w</key>
+					<string>0</string>
+				</dict>
+				<key>Font</key>
+				<string>Helvetica</string>
+				<key>NSKern</key>
+				<real>0.0</real>
+				<key>Size</key>
+				<real>12</real>
+			</dict>
+			<key>ID</key>
+			<integer>68</integer>
+			<key>Shape</key>
+			<string>Rectangle</string>
+			<key>Style</key>
+			<dict>
+				<key>fill</key>
+				<dict>
+					<key>GradientColor</key>
+					<dict>
+						<key>w</key>
+						<string>0.666667</string>
+					</dict>
+				</dict>
+			</dict>
+			<key>Text</key>
+			<dict>
+				<key>Text</key>
+				<string>{\rtf1\mac\ansicpg10002\cocoartf824\cocoasubrtf410
+{\fonttbl\f0\fswiss\fcharset77 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc
+
+\f0\fs24 \cf0 \expnd0\expndtw0\kerning0
+Regex on PATH}</string>
+			</dict>
+		</dict>
+		<dict>
+			<key>Bounds</key>
+			<string>{{917, 198}, {72, 45}}</string>
+			<key>Class</key>
+			<string>ShapedGraphic</string>
+			<key>FontInfo</key>
+			<dict>
+				<key>Color</key>
+				<dict>
+					<key>w</key>
+					<string>0</string>
+				</dict>
+				<key>Font</key>
+				<string>Helvetica</string>
+				<key>NSKern</key>
+				<real>0.0</real>
+				<key>Size</key>
+				<real>12</real>
+			</dict>
+			<key>ID</key>
+			<integer>82</integer>
+			<key>Shape</key>
+			<string>Rectangle</string>
+			<key>Style</key>
+			<dict>
+				<key>fill</key>
+				<dict>
+					<key>GradientColor</key>
+					<dict>
+						<key>w</key>
+						<string>0.666667</string>
+					</dict>
+				</dict>
+			</dict>
+			<key>Text</key>
+			<dict>
+				<key>Text</key>
+				<string>{\rtf1\mac\ansicpg10002\cocoartf824\cocoasubrtf410
+{\fonttbl\f0\fswiss\fcharset77 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc
+
+\f0\fs24 \cf0 \expnd0\expndtw0\kerning0
+GET/POST/etc}</string>
+			</dict>
+		</dict>
+		<dict>
+			<key>Bounds</key>
+			<string>{{1565, 36}, {72, 45}}</string>
+			<key>Class</key>
+			<string>ShapedGraphic</string>
+			<key>FontInfo</key>
+			<dict>
+				<key>Color</key>
+				<dict>
+					<key>w</key>
+					<string>0</string>
+				</dict>
+				<key>Font</key>
+				<string>Helvetica</string>
+				<key>NSKern</key>
+				<real>0.0</real>
+				<key>Size</key>
+				<real>12</real>
+			</dict>
+			<key>ID</key>
+			<integer>105</integer>
+			<key>Shape</key>
+			<string>Rectangle</string>
+			<key>Style</key>
+			<dict>
+				<key>fill</key>
+				<dict>
+					<key>GradientColor</key>
+					<dict>
+						<key>w</key>
+						<string>0.666667</string>
+					</dict>
+					<key>MiddleColor</key>
+					<dict>
+						<key>w</key>
+						<string>0.333333</string>
+					</dict>
+				</dict>
+			</dict>
+			<key>Text</key>
+			<dict>
+				<key>Text</key>
+				<string>{\rtf1\mac\ansicpg10002\cocoartf824\cocoasubrtf410
+{\fonttbl\f0\fswiss\fcharset77 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc
+
+\f0\fs24 \cf0 \expnd0\expndtw0\kerning0
+Body actions}</string>
+			</dict>
+		</dict>
+		<dict>
+			<key>Bounds</key>
+			<string>{{1187, 117}, {72, 45}}</string>
+			<key>Class</key>
+			<string>ShapedGraphic</string>
+			<key>FontInfo</key>
+			<dict>
+				<key>Color</key>
+				<dict>
+					<key>w</key>
+					<string>0</string>
+				</dict>
+				<key>Font</key>
+				<string>Helvetica</string>
+				<key>NSKern</key>
+				<real>0.0</real>
+				<key>Size</key>
+				<real>12</real>
+			</dict>
+			<key>ID</key>
+			<integer>72</integer>
+			<key>Shape</key>
+			<string>Rectangle</string>
+			<key>Style</key>
+			<dict>
+				<key>fill</key>
+				<dict>
+					<key>GradientColor</key>
+					<dict>
+						<key>w</key>
+						<string>0.666667</string>
+					</dict>
+				</dict>
+			</dict>
+			<key>Text</key>
+			<dict>
+				<key>Text</key>
+				<string>{\rtf1\mac\ansicpg10002\cocoartf824\cocoasubrtf410
+{\fonttbl\f0\fswiss\fcharset77 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc
+
+\f0\fs24 \cf0 \expnd0\expndtw0\kerning0
+Body}</string>
+			</dict>
+		</dict>
+		<dict>
+			<key>Bounds</key>
+			<string>{{971, 117}, {72, 45}}</string>
+			<key>Class</key>
+			<string>ShapedGraphic</string>
+			<key>FontInfo</key>
+			<dict>
+				<key>Color</key>
+				<dict>
+					<key>w</key>
+					<string>0</string>
+				</dict>
+				<key>Font</key>
+				<string>Helvetica</string>
+				<key>NSKern</key>
+				<real>0.0</real>
+				<key>Size</key>
+				<real>12</real>
+			</dict>
+			<key>ID</key>
+			<integer>79</integer>
+			<key>Shape</key>
+			<string>Rectangle</string>
+			<key>Style</key>
+			<dict>
+				<key>fill</key>
+				<dict>
+					<key>GradientColor</key>
+					<dict>
+						<key>w</key>
+						<string>0.666667</string>
+					</dict>
+				</dict>
+			</dict>
+			<key>Text</key>
+			<dict>
+				<key>Text</key>
+				<string>{\rtf1\mac\ansicpg10002\cocoartf824\cocoasubrtf410
+{\fonttbl\f0\fswiss\fcharset77 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc
+
+\f0\fs24 \cf0 \expnd0\expndtw0\kerning0
+Condition}</string>
+			</dict>
+		</dict>
+		<dict>
+			<key>Bounds</key>
+			<string>{{1079, 36}, {72, 45}}</string>
+			<key>Class</key>
+			<string>ShapedGraphic</string>
+			<key>FontInfo</key>
+			<dict>
+				<key>Color</key>
+				<dict>
+					<key>w</key>
+					<string>0</string>
+				</dict>
+				<key>Font</key>
+				<string>Helvetica</string>
+				<key>NSKern</key>
+				<real>0.0</real>
+				<key>Size</key>
+				<real>12</real>
+			</dict>
+			<key>ID</key>
+			<integer>78</integer>
+			<key>Shape</key>
+			<string>Rectangle</string>
+			<key>Style</key>
+			<dict>
+				<key>fill</key>
+				<dict>
+					<key>GradientColor</key>
+					<dict>
+						<key>w</key>
+						<string>0.666667</string>
+					</dict>
+					<key>MiddleColor</key>
+					<dict>
+						<key>w</key>
+						<string>0.333333</string>
+					</dict>
+				</dict>
+			</dict>
+			<key>Text</key>
+			<dict>
+				<key>Text</key>
+				<string>{\rtf1\mac\ansicpg10002\cocoartf824\cocoasubrtf410
+{\fonttbl\f0\fswiss\fcharset77 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc
+
+\f0\fs24 \cf0 \expnd0\expndtw0\kerning0
+Rule}</string>
+			</dict>
+		</dict>
+		<dict>
+			<key>Bounds</key>
+			<string>{{539, 36}, {72, 45}}</string>
+			<key>Class</key>
+			<string>ShapedGraphic</string>
+			<key>FontInfo</key>
+			<dict>
+				<key>Color</key>
+				<dict>
+					<key>w</key>
+					<string>0</string>
+				</dict>
+				<key>Font</key>
+				<string>Helvetica</string>
+				<key>NSKern</key>
+				<real>0.0</real>
+				<key>Size</key>
+				<real>12</real>
+			</dict>
+			<key>ID</key>
+			<integer>45</integer>
+			<key>Shape</key>
+			<string>Rectangle</string>
+			<key>Style</key>
+			<dict>
+				<key>fill</key>
+				<dict>
+					<key>GradientColor</key>
+					<dict>
+						<key>w</key>
+						<string>0.666667</string>
+					</dict>
+					<key>MiddleColor</key>
+					<dict>
+						<key>w</key>
+						<string>0.333333</string>
+					</dict>
+				</dict>
+			</dict>
+			<key>Text</key>
+			<dict>
+				<key>Text</key>
+				<string>{\rtf1\mac\ansicpg10002\cocoartf824\cocoasubrtf410
+{\fonttbl\f0\fswiss\fcharset77 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc
+
+\f0\fs24 \cf0 \expnd0\expndtw0\kerning0
+Stages}</string>
+			</dict>
+		</dict>
+		<dict>
+			<key>Bounds</key>
+			<string>{{809, 117}, {72, 45}}</string>
+			<key>Class</key>
+			<string>ShapedGraphic</string>
+			<key>FontInfo</key>
+			<dict>
+				<key>Color</key>
+				<dict>
+					<key>w</key>
+					<string>0</string>
+				</dict>
+				<key>Font</key>
+				<string>Helvetica</string>
+				<key>NSKern</key>
+				<real>0.0</real>
+				<key>Size</key>
+				<real>12</real>
+			</dict>
+			<key>ID</key>
+			<integer>50</integer>
+			<key>Shape</key>
+			<string>Rectangle</string>
+			<key>Style</key>
+			<dict>
+				<key>fill</key>
+				<dict>
+					<key>GradientColor</key>
+					<dict>
+						<key>w</key>
+						<string>0.666667</string>
+					</dict>
+				</dict>
+			</dict>
+			<key>Text</key>
+			<dict>
+				<key>Text</key>
+				<string>{\rtf1\mac\ansicpg10002\cocoartf824\cocoasubrtf410
+{\fonttbl\f0\fswiss\fcharset77 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc
+
+\f0\fs24 \cf0 \expnd0\expndtw0\kerning0
+after}</string>
+			</dict>
+		</dict>
+		<dict>
+			<key>Bounds</key>
+			<string>{{701, 117}, {72, 45}}</string>
+			<key>Class</key>
+			<string>ShapedGraphic</string>
+			<key>FontInfo</key>
+			<dict>
+				<key>Color</key>
+				<dict>
+					<key>w</key>
+					<string>0</string>
+				</dict>
+				<key>Font</key>
+				<string>Helvetica</string>
+				<key>NSKern</key>
+				<real>0.0</real>
+				<key>Size</key>
+				<real>12</real>
+			</dict>
+			<key>ID</key>
+			<integer>129</integer>
+			<key>Shape</key>
+			<string>Rectangle</string>
+			<key>Style</key>
+			<dict>
+				<key>fill</key>
+				<dict>
+					<key>GradientColor</key>
+					<dict>
+						<key>w</key>
+						<string>0.666667</string>
+					</dict>
+				</dict>
+			</dict>
+			<key>Text</key>
+			<dict>
+				<key>Text</key>
+				<string>{\rtf1\mac\ansicpg10002\cocoartf824\cocoasubrtf410
+{\fonttbl\f0\fswiss\fcharset77 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc
+
+\f0\fs24 \cf0 \expnd0\expndtw0\kerning0
+Display new Actions}</string>
+			</dict>
+		</dict>
+		<dict>
+			<key>Bounds</key>
+			<string>{{593, 117}, {72, 45}}</string>
+			<key>Class</key>
+			<string>ShapedGraphic</string>
+			<key>FontInfo</key>
+			<dict>
+				<key>Color</key>
+				<dict>
+					<key>w</key>
+					<string>0</string>
+				</dict>
+				<key>Font</key>
+				<string>Helvetica</string>
+				<key>NSKern</key>
+				<real>0.0</real>
+				<key>Size</key>
+				<real>12</real>
+			</dict>
+			<key>ID</key>
+			<integer>48</integer>
+			<key>Shape</key>
+			<string>Rectangle</string>
+			<key>Style</key>
+			<dict>
+				<key>fill</key>
+				<dict>
+					<key>GradientColor</key>
+					<dict>
+						<key>w</key>
+						<string>0.666667</string>
+					</dict>
+				</dict>
+			</dict>
+			<key>Text</key>
+			<dict>
+				<key>Text</key>
+				<string>{\rtf1\mac\ansicpg10002\cocoartf824\cocoasubrtf410
+{\fonttbl\f0\fswiss\fcharset77 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc
+
+\f0\fs24 \cf0 \expnd0\expndtw0\kerning0
+on}</string>
+			</dict>
+		</dict>
+		<dict>
+			<key>Bounds</key>
+			<string>{{485, 117}, {72, 45}}</string>
+			<key>Class</key>
+			<string>ShapedGraphic</string>
+			<key>FontInfo</key>
+			<dict>
+				<key>Color</key>
+				<dict>
+					<key>w</key>
+					<string>0</string>
+				</dict>
+				<key>Font</key>
+				<string>Helvetica</string>
+				<key>NSKern</key>
+				<real>0.0</real>
+				<key>Size</key>
+				<real>12</real>
+			</dict>
+			<key>ID</key>
+			<integer>125</integer>
+			<key>Shape</key>
+			<string>Rectangle</string>
+			<key>Style</key>
+			<dict>
+				<key>fill</key>
+				<dict>
+					<key>GradientColor</key>
+					<dict>
+						<key>w</key>
+						<string>0.666667</string>
+					</dict>
+				</dict>
+			</dict>
+			<key>Text</key>
+			<dict>
+				<key>Text</key>
+				<string>{\rtf1\mac\ansicpg10002\cocoartf824\cocoasubrtf410
+{\fonttbl\f0\fswiss\fcharset77 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc
+
+\f0\fs24 \cf0 \expnd0\expndtw0\kerning0
+Run prev Actions}</string>
+			</dict>
+		</dict>
+		<dict>
+			<key>Bounds</key>
+			<string>{{377, 117}, {72, 45}}</string>
+			<key>Class</key>
+			<string>ShapedGraphic</string>
+			<key>FontInfo</key>
+			<dict>
+				<key>Color</key>
+				<dict>
+					<key>w</key>
+					<string>0</string>
+				</dict>
+				<key>Font</key>
+				<string>Helvetica</string>
+				<key>NSKern</key>
+				<real>0.0</real>
+				<key>Size</key>
+				<real>12</real>
+			</dict>
+			<key>ID</key>
+			<integer>46</integer>
+			<key>Shape</key>
+			<string>Rectangle</string>
+			<key>Style</key>
+			<dict>
+				<key>fill</key>
+				<dict>
+					<key>GradientColor</key>
+					<dict>
+						<key>w</key>
+						<string>0.666667</string>
+					</dict>
+				</dict>
+			</dict>
+			<key>Text</key>
+			<dict>
+				<key>Text</key>
+				<string>{\rtf1\mac\ansicpg10002\cocoartf824\cocoasubrtf410
+{\fonttbl\f0\fswiss\fcharset77 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc
+
+\f0\fs24 \cf0 \expnd0\expndtw0\kerning0
+before}</string>
+			</dict>
+		</dict>
+		<dict>
+			<key>Class</key>
+			<string>LineGraphic</string>
+			<key>FontInfo</key>
+			<dict>
+				<key>Font</key>
+				<string>LiHeiPro</string>
+				<key>Size</key>
+				<real>24</real>
+			</dict>
+			<key>Head</key>
+			<dict>
+				<key>ID</key>
+				<integer>46</integer>
+			</dict>
+			<key>ID</key>
+			<integer>8</integer>
+			<key>Points</key>
+			<array>
+				<string>{538.553, 76.7236}</string>
+				<string>{449.447, 121.276}</string>
+			</array>
+			<key>Style</key>
+			<dict>
+				<key>stroke</key>
+				<dict>
+					<key>HeadArrow</key>
+					<string>0</string>
+					<key>TailArrow</key>
+					<string>0</string>
+				</dict>
+			</dict>
+			<key>Tail</key>
+			<dict>
+				<key>ID</key>
+				<integer>45</integer>
+			</dict>
+		</dict>
+		<dict>
+			<key>Class</key>
+			<string>LineGraphic</string>
+			<key>FontInfo</key>
+			<dict>
+				<key>Font</key>
+				<string>LiHeiPro</string>
+				<key>Size</key>
+				<real>24</real>
+			</dict>
+			<key>Head</key>
+			<dict>
+				<key>ID</key>
+				<integer>48</integer>
+			</dict>
+			<key>ID</key>
+			<integer>47</integer>
+			<key>Points</key>
+			<array>
+				<string>{590.277, 81.416}</string>
+				<string>{613.723, 116.584}</string>
+			</array>
+			<key>Style</key>
+			<dict>
+				<key>stroke</key>
+				<dict>
+					<key>HeadArrow</key>
+					<string>0</string>
+					<key>TailArrow</key>
+					<string>0</string>
+				</dict>
+			</dict>
+			<key>Tail</key>
+			<dict>
+				<key>ID</key>
+				<integer>45</integer>
+			</dict>
+		</dict>
+		<dict>
+			<key>Class</key>
+			<string>LineGraphic</string>
+			<key>FontInfo</key>
+			<dict>
+				<key>Font</key>
+				<string>LiHeiPro</string>
+				<key>Size</key>
+				<real>24</real>
+			</dict>
+			<key>Head</key>
+			<dict>
+				<key>ID</key>
+				<integer>50</integer>
+			</dict>
+			<key>ID</key>
+			<integer>49</integer>
+			<key>Points</key>
+			<array>
+				<string>{611.479, 69.4437}</string>
+				<string>{808.521, 128.556}</string>
+			</array>
+			<key>Style</key>
+			<dict>
+				<key>stroke</key>
+				<dict>
+					<key>HeadArrow</key>
+					<string>0</string>
+					<key>TailArrow</key>
+					<string>0</string>
+				</dict>
+			</dict>
+			<key>Tail</key>
+			<dict>
+				<key>ID</key>
+				<integer>45</integer>
+			</dict>
+		</dict>
+		<dict>
+			<key>Class</key>
+			<string>LineGraphic</string>
+			<key>FontInfo</key>
+			<dict>
+				<key>Font</key>
+				<string>LiHeiPro</string>
+				<key>Size</key>
+				<real>24</real>
+			</dict>
+			<key>Head</key>
+			<dict>
+				<key>ID</key>
+				<integer>79</integer>
+			</dict>
+			<key>ID</key>
+			<integer>80</integer>
+			<key>Points</key>
+			<array>
+				<string>{1084.6, 81.3}</string>
+				<string>{1037.4, 116.7}</string>
+			</array>
+			<key>Style</key>
+			<dict>
+				<key>stroke</key>
+				<dict>
+					<key>HeadArrow</key>
+					<string>0</string>
+					<key>TailArrow</key>
+					<string>0</string>
+				</dict>
+			</dict>
+			<key>Tail</key>
+			<dict>
+				<key>ID</key>
+				<integer>78</integer>
+			</dict>
+		</dict>
+		<dict>
+			<key>Class</key>
+			<string>LineGraphic</string>
+			<key>FontInfo</key>
+			<dict>
+				<key>Font</key>
+				<string>LiHeiPro</string>
+				<key>Size</key>
+				<real>24</real>
+			</dict>
+			<key>Head</key>
+			<dict>
+				<key>ID</key>
+				<integer>82</integer>
+			</dict>
+			<key>ID</key>
+			<integer>81</integer>
+			<key>Points</key>
+			<array>
+				<string>{991.723, 162.416}</string>
+				<string>{968.277, 197.584}</string>
+			</array>
+			<key>Style</key>
+			<dict>
+				<key>stroke</key>
+				<dict>
+					<key>HeadArrow</key>
+					<string>0</string>
+					<key>TailArrow</key>
+					<string>0</string>
+				</dict>
+			</dict>
+			<key>Tail</key>
+			<dict>
+				<key>ID</key>
+				<integer>79</integer>
+			</dict>
+		</dict>
+		<dict>
+			<key>Class</key>
+			<string>LineGraphic</string>
+			<key>FontInfo</key>
+			<dict>
+				<key>Font</key>
+				<string>LiHeiPro</string>
+				<key>Size</key>
+				<real>24</real>
+			</dict>
+			<key>Head</key>
+			<dict>
+				<key>ID</key>
+				<integer>68</integer>
+			</dict>
+			<key>ID</key>
+			<integer>83</integer>
+			<key>Points</key>
+			<array>
+				<string>{1022.28, 162.416}</string>
+				<string>{1045.72, 197.584}</string>
+			</array>
+			<key>Style</key>
+			<dict>
+				<key>stroke</key>
+				<dict>
+					<key>HeadArrow</key>
+					<string>0</string>
+					<key>TailArrow</key>
+					<string>0</string>
+				</dict>
+			</dict>
+			<key>Tail</key>
+			<dict>
+				<key>ID</key>
+				<integer>79</integer>
+			</dict>
+		</dict>
+		<dict>
+			<key>Class</key>
+			<string>LineGraphic</string>
+			<key>FontInfo</key>
+			<dict>
+				<key>Font</key>
+				<string>LiHeiPro</string>
+				<key>Size</key>
+				<real>24</real>
+			</dict>
+			<key>Head</key>
+			<dict>
+				<key>ID</key>
+				<integer>85</integer>
+			</dict>
+			<key>ID</key>
+			<integer>84</integer>
+			<key>Points</key>
+			<array>
+				<string>{1061, 243.5}</string>
+				<string>{1061, 278.5}</string>
+			</array>
+			<key>Style</key>
+			<dict>
+				<key>stroke</key>
+				<dict>
+					<key>HeadArrow</key>
+					<string>0</string>
+					<key>TailArrow</key>
+					<string>0</string>
+				</dict>
+			</dict>
+			<key>Tail</key>
+			<dict>
+				<key>ID</key>
+				<integer>68</integer>
+			</dict>
+		</dict>
+		<dict>
+			<key>Class</key>
+			<string>LineGraphic</string>
+			<key>FontInfo</key>
+			<dict>
+				<key>Font</key>
+				<string>LiHeiPro</string>
+				<key>Size</key>
+				<real>24</real>
+			</dict>
+			<key>Head</key>
+			<dict>
+				<key>ID</key>
+				<integer>70</integer>
+			</dict>
+			<key>ID</key>
+			<integer>86</integer>
+			<key>Points</key>
+			<array>
+				<string>{1061, 324.5}</string>
+				<string>{1061, 359.5}</string>
+			</array>
+			<key>Style</key>
+			<dict>
+				<key>stroke</key>
+				<dict>
+					<key>HeadArrow</key>
+					<string>0</string>
+					<key>TailArrow</key>
+					<string>0</string>
+				</dict>
+			</dict>
+			<key>Tail</key>
+			<dict>
+				<key>ID</key>
+				<integer>85</integer>
+			</dict>
+		</dict>
+		<dict>
+			<key>Class</key>
+			<string>LineGraphic</string>
+			<key>FontInfo</key>
+			<dict>
+				<key>Font</key>
+				<string>LiHeiPro</string>
+				<key>Size</key>
+				<real>24</real>
+			</dict>
+			<key>Head</key>
+			<dict>
+				<key>ID</key>
+				<integer>72</integer>
+			</dict>
+			<key>ID</key>
+			<integer>87</integer>
+			<key>Points</key>
+			<array>
+				<string>{1145.4, 81.3}</string>
+				<string>{1192.6, 116.7}</string>
+			</array>
+			<key>Style</key>
+			<dict>
+				<key>stroke</key>
+				<dict>
+					<key>HeadArrow</key>
+					<string>0</string>
+					<key>TailArrow</key>
+					<string>0</string>
+				</dict>
+			</dict>
+			<key>Tail</key>
+			<dict>
+				<key>ID</key>
+				<integer>78</integer>
+			</dict>
+		</dict>
+		<dict>
+			<key>Class</key>
+			<string>LineGraphic</string>
+			<key>FontInfo</key>
+			<dict>
+				<key>Font</key>
+				<string>LiHeiPro</string>
+				<key>Size</key>
+				<real>24</real>
+			</dict>
+			<key>Head</key>
+			<dict>
+				<key>ID</key>
+				<integer>89</integer>
+			</dict>
+			<key>ID</key>
+			<integer>88</integer>
+			<key>Points</key>
+			<array>
+				<string>{1207.72, 162.416}</string>
+				<string>{1184.28, 197.584}</string>
+			</array>
+			<key>Style</key>
+			<dict>
+				<key>stroke</key>
+				<dict>
+					<key>HeadArrow</key>
+					<string>0</string>
+					<key>TailArrow</key>
+					<string>0</string>
+				</dict>
+			</dict>
+			<key>Tail</key>
+			<dict>
+				<key>ID</key>
+				<integer>72</integer>
+			</dict>
+		</dict>
+		<dict>
+			<key>Class</key>
+			<string>LineGraphic</string>
+			<key>FontInfo</key>
+			<dict>
+				<key>Font</key>
+				<string>LiHeiPro</string>
+				<key>Size</key>
+				<real>24</real>
+			</dict>
+			<key>Head</key>
+			<dict>
+				<key>ID</key>
+				<integer>99</integer>
+			</dict>
+			<key>ID</key>
+			<integer>98</integer>
+			<key>Points</key>
+			<array>
+				<string>{1238.28, 162.416}</string>
+				<string>{1261.72, 197.584}</string>
+			</array>
+			<key>Style</key>
+			<dict>
+				<key>stroke</key>
+				<dict>
+					<key>HeadArrow</key>
+					<string>0</string>
+					<key>TailArrow</key>
+					<string>0</string>
+				</dict>
+			</dict>
+			<key>Tail</key>
+			<dict>
+				<key>ID</key>
+				<integer>72</integer>
+			</dict>
+		</dict>
+		<dict>
+			<key>Class</key>
+			<string>LineGraphic</string>
+			<key>FontInfo</key>
+			<dict>
+				<key>Font</key>
+				<string>LiHeiPro</string>
+				<key>Size</key>
+				<real>24</real>
+			</dict>
+			<key>Head</key>
+			<dict>
+				<key>ID</key>
+				<integer>101</integer>
+			</dict>
+			<key>ID</key>
+			<integer>100</integer>
+			<key>Points</key>
+			<array>
+				<string>{1261.72, 243.416}</string>
+				<string>{1238.28, 278.584}</string>
+			</array>
+			<key>Style</key>
+			<dict>
+				<key>stroke</key>
+				<dict>
+					<key>HeadArrow</key>
+					<string>0</string>
+					<key>TailArrow</key>
+					<string>0</string>
+				</dict>
+			</dict>
+			<key>Tail</key>
+			<dict>
+				<key>ID</key>
+				<integer>99</integer>
+			</dict>
+		</dict>
+		<dict>
+			<key>Class</key>
+			<string>LineGraphic</string>
+			<key>FontInfo</key>
+			<dict>
+				<key>Font</key>
+				<string>LiHeiPro</string>
+				<key>Size</key>
+				<real>24</real>
+			</dict>
+			<key>Head</key>
+			<dict>
+				<key>ID</key>
+				<integer>103</integer>
+			</dict>
+			<key>ID</key>
+			<integer>102</integer>
+			<key>Points</key>
+			<array>
+				<string>{1292.28, 243.416}</string>
+				<string>{1315.72, 278.584}</string>
+			</array>
+			<key>Style</key>
+			<dict>
+				<key>stroke</key>
+				<dict>
+					<key>HeadArrow</key>
+					<string>0</string>
+					<key>TailArrow</key>
+					<string>0</string>
+				</dict>
+			</dict>
+			<key>Tail</key>
+			<dict>
+				<key>ID</key>
+				<integer>99</integer>
+			</dict>
+		</dict>
+		<dict>
+			<key>Class</key>
+			<string>LineGraphic</string>
+			<key>FontInfo</key>
+			<dict>
+				<key>Font</key>
+				<string>LiHeiPro</string>
+				<key>Size</key>
+				<real>24</real>
+			</dict>
+			<key>Head</key>
+			<dict>
+				<key>ID</key>
+				<integer>106</integer>
+			</dict>
+			<key>ID</key>
+			<integer>107</integer>
+			<key>Points</key>
+			<array>
+				<string>{1564.55, 76.7236}</string>
+				<string>{1475.45, 121.276}</string>
+			</array>
+			<key>Style</key>
+			<dict>
+				<key>stroke</key>
+				<dict>
+					<key>HeadArrow</key>
+					<string>0</string>
+					<key>TailArrow</key>
+					<string>0</string>
+				</dict>
+			</dict>
+			<key>Tail</key>
+			<dict>
+				<key>ID</key>
+				<integer>105</integer>
+			</dict>
+		</dict>
+		<dict>
+			<key>Class</key>
+			<string>LineGraphic</string>
+			<key>FontInfo</key>
+			<dict>
+				<key>Font</key>
+				<string>LiHeiPro</string>
+				<key>Size</key>
+				<real>24</real>
+			</dict>
+			<key>Head</key>
+			<dict>
+				<key>ID</key>
+				<integer>109</integer>
+			</dict>
+			<key>ID</key>
+			<integer>108</integer>
+			<key>Points</key>
+			<array>
+				<string>{1423.72, 162.416}</string>
+				<string>{1400.28, 197.584}</string>
+			</array>
+			<key>Style</key>
+			<dict>
+				<key>stroke</key>
+				<dict>
+					<key>HeadArrow</key>
+					<string>0</string>
+					<key>TailArrow</key>
+					<string>0</string>
+				</dict>
+			</dict>
+			<key>Tail</key>
+			<dict>
+				<key>ID</key>
+				<integer>106</integer>
+			</dict>
+		</dict>
+		<dict>
+			<key>Class</key>
+			<string>LineGraphic</string>
+			<key>FontInfo</key>
+			<dict>
+				<key>Font</key>
+				<string>LiHeiPro</string>
+				<key>Size</key>
+				<real>24</real>
+			</dict>
+			<key>Head</key>
+			<dict>
+				<key>ID</key>
+				<integer>111</integer>
+			</dict>
+			<key>ID</key>
+			<integer>110</integer>
+			<key>Points</key>
+			<array>
+				<string>{1454.28, 162.416}</string>
+				<string>{1477.72, 197.584}</string>
+			</array>
+			<key>Style</key>
+			<dict>
+				<key>stroke</key>
+				<dict>
+					<key>HeadArrow</key>
+					<string>0</string>
+					<key>TailArrow</key>
+					<string>0</string>
+				</dict>
+			</dict>
+			<key>Tail</key>
+			<dict>
+				<key>ID</key>
+				<integer>106</integer>
+			</dict>
+		</dict>
+		<dict>
+			<key>Class</key>
+			<string>LineGraphic</string>
+			<key>FontInfo</key>
+			<dict>
+				<key>Font</key>
+				<string>LiHeiPro</string>
+				<key>Size</key>
+				<real>24</real>
+			</dict>
+			<key>Head</key>
+			<dict>
+				<key>ID</key>
+				<integer>113</integer>
+			</dict>
+			<key>ID</key>
+			<integer>112</integer>
+			<key>Points</key>
+			<array>
+				<string>{1585.72, 81.416}</string>
+				<string>{1562.28, 116.584}</string>
+			</array>
+			<key>Style</key>
+			<dict>
+				<key>stroke</key>
+				<dict>
+					<key>HeadArrow</key>
+					<string>0</string>
+					<key>TailArrow</key>
+					<string>0</string>
+				</dict>
+			</dict>
+			<key>Tail</key>
+			<dict>
+				<key>ID</key>
+				<integer>105</integer>
+			</dict>
+		</dict>
+		<dict>
+			<key>Class</key>
+			<string>LineGraphic</string>
+			<key>FontInfo</key>
+			<dict>
+				<key>Font</key>
+				<string>LiHeiPro</string>
+				<key>Size</key>
+				<real>24</real>
+			</dict>
+			<key>Head</key>
+			<dict>
+				<key>ID</key>
+				<integer>117</integer>
+			</dict>
+			<key>ID</key>
+			<integer>116</integer>
+			<key>Points</key>
+			<array>
+				<string>{1562.28, 162.416}</string>
+				<string>{1585.72, 197.584}</string>
+			</array>
+			<key>Style</key>
+			<dict>
+				<key>stroke</key>
+				<dict>
+					<key>HeadArrow</key>
+					<string>0</string>
+					<key>TailArrow</key>
+					<string>0</string>
+				</dict>
+			</dict>
+			<key>Tail</key>
+			<dict>
+				<key>ID</key>
+				<integer>113</integer>
+			</dict>
+		</dict>
+		<dict>
+			<key>Class</key>
+			<string>LineGraphic</string>
+			<key>FontInfo</key>
+			<dict>
+				<key>Font</key>
+				<string>LiHeiPro</string>
+				<key>Size</key>
+				<real>24</real>
+			</dict>
+			<key>Head</key>
+			<dict>
+				<key>ID</key>
+				<integer>119</integer>
+			</dict>
+			<key>ID</key>
+			<integer>118</integer>
+			<key>Points</key>
+			<array>
+				<string>{1616.28, 81.416}</string>
+				<string>{1639.72, 116.584}</string>
+			</array>
+			<key>Style</key>
+			<dict>
+				<key>stroke</key>
+				<dict>
+					<key>HeadArrow</key>
+					<string>0</string>
+					<key>TailArrow</key>
+					<string>0</string>
+				</dict>
+			</dict>
+			<key>Tail</key>
+			<dict>
+				<key>ID</key>
+				<integer>105</integer>
+			</dict>
+		</dict>
+		<dict>
+			<key>Class</key>
+			<string>LineGraphic</string>
+			<key>FontInfo</key>
+			<dict>
+				<key>Font</key>
+				<string>LiHeiPro</string>
+				<key>Size</key>
+				<real>24</real>
+			</dict>
+			<key>Head</key>
+			<dict>
+				<key>ID</key>
+				<integer>121</integer>
+			</dict>
+			<key>ID</key>
+			<integer>120</integer>
+			<key>Points</key>
+			<array>
+				<string>{1670.28, 162.416}</string>
+				<string>{1693.72, 197.584}</string>
+			</array>
+			<key>Style</key>
+			<dict>
+				<key>stroke</key>
+				<dict>
+					<key>HeadArrow</key>
+					<string>0</string>
+					<key>TailArrow</key>
+					<string>0</string>
+				</dict>
+			</dict>
+			<key>Tail</key>
+			<dict>
+				<key>ID</key>
+				<integer>119</integer>
+			</dict>
+		</dict>
+		<dict>
+			<key>Class</key>
+			<string>LineGraphic</string>
+			<key>FontInfo</key>
+			<dict>
+				<key>Font</key>
+				<string>LiHeiPro</string>
+				<key>Size</key>
+				<real>24</real>
+			</dict>
+			<key>Head</key>
+			<dict>
+				<key>ID</key>
+				<integer>123</integer>
+			</dict>
+			<key>ID</key>
+			<integer>122</integer>
+			<key>Points</key>
+			<array>
+				<string>{845, 162.5}</string>
+				<string>{845, 197.5}</string>
+			</array>
+			<key>Style</key>
+			<dict>
+				<key>stroke</key>
+				<dict>
+					<key>HeadArrow</key>
+					<string>0</string>
+					<key>TailArrow</key>
+					<string>0</string>
+				</dict>
+			</dict>
+			<key>Tail</key>
+			<dict>
+				<key>ID</key>
+				<integer>50</integer>
+			</dict>
+		</dict>
+		<dict>
+			<key>Class</key>
+			<string>LineGraphic</string>
+			<key>FontInfo</key>
+			<dict>
+				<key>Font</key>
+				<string>LiHeiPro</string>
+				<key>Size</key>
+				<real>24</real>
+			</dict>
+			<key>Head</key>
+			<dict>
+				<key>ID</key>
+				<integer>125</integer>
+			</dict>
+			<key>ID</key>
+			<integer>124</integer>
+			<key>Points</key>
+			<array>
+				<string>{559.723, 81.416}</string>
+				<string>{536.277, 116.584}</string>
+			</array>
+			<key>Style</key>
+			<dict>
+				<key>stroke</key>
+				<dict>
+					<key>HeadArrow</key>
+					<string>0</string>
+					<key>TailArrow</key>
+					<string>0</string>
+				</dict>
+			</dict>
+			<key>Tail</key>
+			<dict>
+				<key>ID</key>
+				<integer>45</integer>
+			</dict>
+		</dict>
+		<dict>
+			<key>Class</key>
+			<string>LineGraphic</string>
+			<key>FontInfo</key>
+			<dict>
+				<key>Font</key>
+				<string>LiHeiPro</string>
+				<key>Size</key>
+				<real>24</real>
+			</dict>
+			<key>Head</key>
+			<dict>
+				<key>ID</key>
+				<integer>129</integer>
+			</dict>
+			<key>ID</key>
+			<integer>128</integer>
+			<key>Points</key>
+			<array>
+				<string>{611.447, 76.7236}</string>
+				<string>{700.553, 121.276}</string>
+			</array>
+			<key>Style</key>
+			<dict>
+				<key>stroke</key>
+				<dict>
+					<key>HeadArrow</key>
+					<string>0</string>
+					<key>TailArrow</key>
+					<string>0</string>
+				</dict>
+			</dict>
+			<key>Tail</key>
+			<dict>
+				<key>ID</key>
+				<integer>45</integer>
+			</dict>
+		</dict>
+		<dict>
+			<key>Class</key>
+			<string>LineGraphic</string>
+			<key>FontInfo</key>
+			<dict>
+				<key>Font</key>
+				<string>LiHeiPro</string>
+				<key>Size</key>
+				<real>24</real>
+			</dict>
+			<key>Head</key>
+			<dict>
+				<key>ID</key>
+				<integer>131</integer>
+			</dict>
+			<key>ID</key>
+			<integer>130</integer>
+			<key>Points</key>
+			<array>
+				<string>{1637.45, 76.7236}</string>
+				<string>{1726.55, 121.276}</string>
+			</array>
+			<key>Style</key>
+			<dict>
+				<key>stroke</key>
+				<dict>
+					<key>HeadArrow</key>
+					<string>0</string>
+					<key>TailArrow</key>
+					<string>0</string>
+				</dict>
+			</dict>
+			<key>Tail</key>
+			<dict>
+				<key>ID</key>
+				<integer>105</integer>
+			</dict>
+		</dict>
+		<dict>
+			<key>Class</key>
+			<string>LineGraphic</string>
+			<key>FontInfo</key>
+			<dict>
+				<key>Font</key>
+				<string>LiHeiPro</string>
+				<key>Size</key>
+				<real>24</real>
+			</dict>
+			<key>Head</key>
+			<dict>
+				<key>ID</key>
+				<integer>54</integer>
+			</dict>
+			<key>ID</key>
+			<integer>132</integer>
+			<key>Points</key>
+			<array>
+				<string>{1637.48, 69.4437}</string>
+				<string>{1834.52, 128.556}</string>
+			</array>
+			<key>Style</key>
+			<dict>
+				<key>stroke</key>
+				<dict>
+					<key>HeadArrow</key>
+					<string>0</string>
+					<key>TailArrow</key>
+					<string>0</string>
+				</dict>
+			</dict>
+			<key>Tail</key>
+			<dict>
+				<key>ID</key>
+				<integer>105</integer>
+			</dict>
+		</dict>
+		<dict>
+			<key>Class</key>
+			<string>LineGraphic</string>
+			<key>FontInfo</key>
+			<dict>
+				<key>Font</key>
+				<string>LiHeiPro</string>
+				<key>Size</key>
+				<real>24</real>
+			</dict>
+			<key>Head</key>
+			<dict>
+				<key>ID</key>
+				<integer>56</integer>
+			</dict>
+			<key>ID</key>
+			<integer>135</integer>
+			<key>Points</key>
+			<array>
+				<string>{1871, 162.5}</string>
+				<string>{1871, 197.5}</string>
+			</array>
+			<key>Style</key>
+			<dict>
+				<key>stroke</key>
+				<dict>
+					<key>HeadArrow</key>
+					<string>0</string>
+					<key>TailArrow</key>
+					<string>0</string>
+				</dict>
+			</dict>
+			<key>Tail</key>
+			<dict>
+				<key>ID</key>
+				<integer>54</integer>
+			</dict>
+		</dict>
+		<dict>
+			<key>Class</key>
+			<string>LineGraphic</string>
+			<key>FontInfo</key>
+			<dict>
+				<key>Font</key>
+				<string>LiHeiPro</string>
+				<key>Size</key>
+				<real>24</real>
+			</dict>
+			<key>Head</key>
+			<dict>
+				<key>ID</key>
+				<integer>2</integer>
+			</dict>
+			<key>ID</key>
+			<integer>137</integer>
+			<key>Points</key>
+			<array>
+				<string>{1564.52, 69.4437}</string>
+				<string>{1367.48, 128.556}</string>
+			</array>
+			<key>Style</key>
+			<dict>
+				<key>stroke</key>
+				<dict>
+					<key>HeadArrow</key>
+					<string>0</string>
+					<key>TailArrow</key>
+					<string>0</string>
+				</dict>
+			</dict>
+			<key>Tail</key>
+			<dict>
+				<key>ID</key>
+				<integer>105</integer>
+			</dict>
+		</dict>
+	</array>
+	<key>GridInfo</key>
+	<dict/>
+	<key>GuidesLocked</key>
+	<string>NO</string>
+	<key>GuidesVisible</key>
+	<string>YES</string>
+	<key>HPages</key>
+	<integer>4</integer>
+	<key>ImageCounter</key>
+	<integer>1</integer>
+	<key>IsPalette</key>
+	<string>NO</string>
+	<key>KeepToScale</key>
+	<false/>
+	<key>Layers</key>
+	<array>
+		<dict>
+			<key>Lock</key>
+			<string>NO</string>
+			<key>Name</key>
+			<string>Layer 1</string>
+			<key>Print</key>
+			<string>YES</string>
+			<key>View</key>
+			<string>YES</string>
+		</dict>
+	</array>
+	<key>LayoutInfo</key>
+	<dict>
+		<key>LayoutTarget</key>
+		<integer>3</integer>
+		<key>LineLength</key>
+		<real>0.10000000149011612</real>
+		<key>Spring</key>
+		<real>1.8235714435577393</real>
+	</dict>
+	<key>LinksVisible</key>
+	<string>NO</string>
+	<key>MagnetsVisible</key>
+	<string>NO</string>
+	<key>MasterSheet</key>
+	<string>Master 1</string>
+	<key>MasterSheets</key>
+	<array>
+		<dict>
+			<key>ActiveLayerIndex</key>
+			<integer>0</integer>
+			<key>AutoAdjust</key>
+			<true/>
+			<key>CanvasColor</key>
+			<dict>
+				<key>w</key>
+				<string>1</string>
+			</dict>
+			<key>CanvasOrigin</key>
+			<string>{0, 0}</string>
+			<key>CanvasScale</key>
+			<real>1</real>
+			<key>ColumnAlign</key>
+			<integer>1</integer>
+			<key>ColumnSpacing</key>
+			<real>36</real>
+			<key>DisplayScale</key>
+			<string>1 cm = 1 cm</string>
+			<key>GraphicsList</key>
+			<array/>
+			<key>GridInfo</key>
+			<dict/>
+			<key>HPages</key>
+			<integer>1</integer>
+			<key>IsPalette</key>
+			<string>NO</string>
+			<key>KeepToScale</key>
+			<false/>
+			<key>Layers</key>
+			<array>
+				<dict>
+					<key>Lock</key>
+					<string>NO</string>
+					<key>Name</key>
+					<string>Layer 1</string>
+					<key>Print</key>
+					<string>YES</string>
+					<key>View</key>
+					<string>YES</string>
+				</dict>
+			</array>
+			<key>LayoutInfo</key>
+			<dict>
+				<key>LayoutTarget</key>
+				<integer>3</integer>
+			</dict>
+			<key>Orientation</key>
+			<integer>2</integer>
+			<key>OutlineStyle</key>
+			<string>Basic</string>
+			<key>RowAlign</key>
+			<integer>1</integer>
+			<key>RowSpacing</key>
+			<real>36</real>
+			<key>SheetTitle</key>
+			<string>Master 1</string>
+			<key>UniqueID</key>
+			<integer>1</integer>
+			<key>VPages</key>
+			<integer>1</integer>
+		</dict>
+	</array>
+	<key>ModificationDate</key>
+	<string>2006-07-09 19:23:03 -0400</string>
+	<key>Modifier</key>
+	<string>Audrey Tang</string>
+	<key>NotesVisible</key>
+	<string>NO</string>
+	<key>Orientation</key>
+	<integer>2</integer>
+	<key>OriginVisible</key>
+	<string>NO</string>
+	<key>OutlineStyle</key>
+	<string>Basic</string>
+	<key>PageBreaks</key>
+	<string>YES</string>
+	<key>PrintInfo</key>
+	<dict>
+		<key>NSBottomMargin</key>
+		<array>
+			<string>float</string>
+			<string>0</string>
+		</array>
+		<key>NSLeftMargin</key>
+		<array>
+			<string>float</string>
+			<string>0</string>
+		</array>
+		<key>NSRightMargin</key>
+		<array>
+			<string>float</string>
+			<string>0</string>
+		</array>
+		<key>NSTopMargin</key>
+		<array>
+			<string>float</string>
+			<string>0</string>
+		</array>
+	</dict>
+	<key>ReadOnly</key>
+	<string>NO</string>
+	<key>RowAlign</key>
+	<integer>1</integer>
+	<key>RowSpacing</key>
+	<real>36</real>
+	<key>SheetTitle</key>
+	<string>Canvas 1</string>
+	<key>SmartAlignmentGuidesActive</key>
+	<string>YES</string>
+	<key>SmartDistanceGuidesActive</key>
+	<string>YES</string>
+	<key>UniqueID</key>
+	<integer>1</integer>
+	<key>UseEntirePage</key>
+	<true/>
+	<key>VPages</key>
+	<integer>1</integer>
+	<key>WindowInfo</key>
+	<dict>
+		<key>CurrentSheet</key>
+		<string>0</string>
+		<key>DrawerOpen</key>
+		<true/>
+		<key>DrawerTab</key>
+		<string>Outline</string>
+		<key>DrawerWidth</key>
+		<real>209</real>
+		<key>FitInWindow</key>
+		<false/>
+		<key>Frame</key>
+		<string>{{500, 4}, {586, 742}}</string>
+		<key>ShowRuler</key>
+		<false/>
+		<key>ShowStatusBar</key>
+		<true/>
+		<key>VisibleRegion</key>
+		<string>{{1496, 4}, {571, 628}}</string>
+		<key>Zoom</key>
+		<string>1</string>
+	</dict>
+</dict>
+</plist>

Added: jifty/branches/schema-plugins/doc/jifty-dispatcher.svg
==============================================================================
--- (empty file)
+++ jifty/branches/schema-plugins/doc/jifty-dispatcher.svg	Mon Jan 29 21:05:02 2007
@@ -0,0 +1,11 @@
+<?xml version="1.0"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xl="http://www.w3.org/1999/xlink" version="1.1" viewBox="357 20 1570 409" width="1570pt" height="409pt"><metadata xmlns:dc="http://purl.org/dc/elements/1.1/"><dc:date>2006-07-11 00:19Z</dc:date><!-- Produced by OmniGraffle Professional 4.1.2 beta 2 --></metadata><defs><filter id="Shadow" filterUnits="userSpaceOnUse"><feGaussianBlur in="SourceAlpha" result="blur" stdDeviation="3.488"/><feOffset in="blur" result="offset" dx="0" dy="4"/><feFlood flood-color="Black" flood-opacity=".75" result="flood"/><feComposite in="flood" in2="offset" operator="in"/></filter><font-face font-size="12pt" units-per-em="1000" underline-position="-75.683594" underline-thickness="49.316406" slope="0" x-height="583.33337" cap-height="750" ascent="770.01953" descent="-229.98047" font-weight="500"><!--{
+    NSCTFontTraitsAttribute = {
+        NSCTFontProportionTrait = 0; 
+        NSCTFontSlantTrait = 0; 
+        NSCTFontSymbolicTrait = 0; 
+        NSCTFontWeightTrait = 0; 
+    }; 
+    NSFontNameAttribute = Helvetica; 
+}--><font-face-src><font-face-name name="Helvetica"/></font-face-src></font-face></defs><g stroke="none" stroke-opacity="1" stroke-dasharray="none" fill="none" fill-opacity="1"><title>Canvas 1</title><g><title>Layer 1</title><g><use xl:href="#id46_Graphic" filter="url(#Shadow)"/><use xl:href="#id125_Graphic" filter="url(#Shadow)"/><use xl:href="#id48_Graphic" filter="url(#Shadow)"/><use xl:href="#id129_Graphic" filter="url(#Shadow)"/><use xl:href="#id50_Graphic" filter="url(#Shadow)"/><use xl:href="#id45_Graphic" filter="url(#Shadow)"/><use xl:href="#id78_Graphic" filter="url(#Shadow)"/><use xl:href="#id79_Graphic" filter="url(#Shadow)"/><use xl:href="#id72_Graphic" filter="url(#Shadow)"/><use xl:href="#id105_Graphic" filter="url(#Shadow)"/><use xl:href="#id82_Graphic" filter="url(#Shadow)"/><use xl:href="#id68_Graphic" filter="url(#Shadow)"/><use xl:href="#id85_Graphic" filter="url(#Shadow)"/><use xl:href="#id70_Graphic" filter="url(#Shadow)"/><use xl:href="#id89_Graphic" filter="url(#Shadow)"/><use xl:href="#id99_Graphic" filter="url(#Shadow)"/><use xl:href="#id101_Graphic" filter="url(#Shadow)"/><use xl:href="#id103_Graphic" filter="url(#Shadow)"/><use xl:href="#id2_Graphic" filter="url(#Shadow)"/><use xl:href="#id106_Graphic" filter="url(#Shadow)"/><use xl:href="#id113_Graphic" filter="url(#Shadow)"/><use xl:href="#id119_Graphic" filter="url(#Shadow)"/><use xl:href="#id131_Graphic" filter="url(#Shadow)"/><use xl:href="#id109_Graphic" filter="url(#Shadow)"/><use xl:href="#id111_Graphic" filter="url(#Shadow)"/><use xl:href="#id117_Graphic" filter="url(#Shadow)"/><use xl:href="#id121_Graphic" filter="url(#Shadow)"/><use xl:href="#id54_Graphic" filter="url(#Shadow)"/><use xl:href="#id56_Graphic" filter="url(#Shadow)"/></g><line x1="1564.5211" y1="69.44368" x2="1367.4789" y2="128.556335" stroke="Black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><line x1="1871" y1="162.5" x2="1871" y2="197.5" stroke="Black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><line x1="1637.4789" y1="69.44368" x2="1834.5211" y2="128.556335" stroke="Black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><line x1="1637.4473" y1="76.72361" x2="1726.5527" y2="121.276405" stroke="Black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><line x1="611.4472" y1="76.72361" x2="700.5528" y2="121.27638" stroke="Black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><line x1="559.72266" y1="81.416023" x2="536.27734" y2="116.58398" stroke="Black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><line x1="1670.2773" y1="162.41603" x2="1693.7227" y2="197.58397" stroke="Black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><line x1="1616.2773" y1="81.416023" x2="1639.7227" y2="116.58398" stroke="Black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><line x1="1562.2773" y1="162.41603" x2="1585.7227" y2="197.58397" stroke="Black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><line x1="1585.7227" y1="81.416023" x2="1562.2773" y2="116.58398" stroke="Black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><line x1="1454.27734" y1="162.41603" x2="1477.7227" y2="197.58397" stroke="Black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><line x1="1423.72266" y1="162.41603" x2="1400.27734" y2="197.58397" stroke="Black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><line x1="1564.5527" y1="76.72361" x2="1475.4473" y2="121.276405" stroke="Black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><line x1="1292.27734" y1="243.41603" x2="1315.72266" y2="278.58398" stroke="Black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><line x1="1261.72266" y1="243.41603" x2="1238.27734" y2="278.58398" stroke="Black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><line x1="1238.27734" y1="162.41603" x2="1261.72266" y2="197.58397" stroke="Black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><line x1="1207.72266" y1="162.41603" x2="1184.27734" y2="197.58397" stroke="Black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><line x1="1145.4" y1="81.300003" x2="1192.6" y2="116.7" stroke="Black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><line x1="1061" y1="347.5" x2="1061" y2="359.5" stroke="Black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><line x1="1061" y1="243.5" x2="1061" y2="278.5" stroke="Black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><line x1="1022.27734" y1="162.41603" x2="1045.72266" y2="197.58397" stroke="Black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><line x1="991.72266" y1="162.41603" x2="968.27734" y2="197.58397" stroke="Black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><line x1="1084.6" y1="81.300003" x2="1037.4" y2="116.7" stroke="Black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><line x1="611.47894" y1="69.44368" x2="808.52106" y2="128.55632" stroke="Black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><line x1="590.27734" y1="81.416023" x2="613.72266" y2="116.58398" stroke="Black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><line x1="538.5528" y1="76.72361" x2="449.44724" y2="121.27638" stroke="Black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><g id="id46_Graphic"><rect x="377" y="117" width="72" height="45" fill="White"/><rect x="377" y="117" width="72" height="45" stroke="Black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><text transform="translate(382 133)" fill="Black"><tspan font-size="12pt" fill="Black" x="13.987305" y="11" textLength="34.025002">before</tspan></text></g><g id="id125_Graphic"><rect x="485" y="117" width="72" height="45" fill="White"/><rect x="485" y="117" width="72" height="45" stroke="Black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><text transform="translate(490 126)" fill="Black"><tspan font-size="12pt" fill="Black" x="6.654297" y="11" textLength="52.025">Run prev </tspan><tspan font-size="12pt" fill="Black" x="11.324219" y="25" textLength="39.351002">Actions</tspan></text></g><g id="id48_Graphic"><rect x="593" y="117" width="72" height="45" fill="White"/><rect x="593" y="117" width="72" height="45" stroke="Black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><text transform="translate(598 133)" fill="Black"><tspan font-size="12pt" fill="Black" x="24.326172" y="11" textLength="13.347">on</tspan></text></g><g id="id129_Graphic"><rect x="701" y="117" width="72" height="45" fill="White"/><rect x="701" y="117" width="72" height="45" stroke="Black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><text transform="translate(706 119)" fill="Black"><tspan font-size="12pt" fill="Black" x="11.3271484" y="11" textLength="42.679">Display </tspan><tspan font-size="12pt" fill="Black" x="19.993164" y="25" textLength="25.347">new </tspan><tspan font-size="12pt" fill="Black" x="11.324219" y="39" textLength="39.351002">Actions</tspan></text></g><g id="id50_Graphic"><rect x="809" y="117" width="72" height="45" fill="White"/><rect x="809" y="117" width="72" height="45" stroke="Black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><text transform="translate(814 133)" fill="Black"><tspan font-size="12pt" fill="Black" x="18.994141" y="11" textLength="24.011">after</tspan></text></g><g id="id45_Graphic"><rect x="539" y="36" width="72" height="45" fill="White"/><rect x="539" y="36" width="72" height="45" stroke="Black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><text transform="translate(544 52)" fill="Black"><tspan font-size="12pt" fill="Black" x="12.3203125" y="11" textLength="37.359001">Stages</tspan></text></g><g id="id78_Graphic"><rect x="1079" y="36" width="72" height="45" fill="White"/><rect x="1079" y="36" width="72" height="45" stroke="Black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><text transform="translate(1084 52)" fill="Black"><tspan font-size="12pt" fill="Black" x="18.660156" y="11" textLength="24.679001">Rule</tspan></text></g><g id="id79_Graphic"><rect x="971" y="117" width="72" height="45" fill="White"/><rect x="971" y="117" width="72" height="45" stroke="Black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><text transform="translate(976 133)" fill="Black"><tspan font-size="12pt" fill="Black" x="5.649414" y="11" textLength="50.701">Condition</tspan></text></g><g id="id72_Graphic"><rect x="1187" y="117" width="72" height="45" fill="White"/><rect x="1187" y="117" width="72" height="45" stroke="Black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><text transform="translate(1192 133)" fill="Black"><tspan font-size="12pt" fill="Black" x="17.324219" y="11" textLength="27.351">Body</tspan></text></g><g id="id105_Graphic"><rect x="1565" y="36" width="72" height="45" fill="White"/><rect x="1565" y="36" width="72" height="45" stroke="Black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><text transform="translate(1570 45)" fill="Black"><tspan font-size="12pt" fill="Black" x="17.324219" y="11" textLength="30.685">Body </tspan><tspan font-size="12pt" fill="Black" x="11.989258" y="25" textLength="38.021">actions</tspan></text></g><g id="id82_Graphic"><rect x="917" y="198" width="72" height="45" fill="White"/><rect x="917" y="198" width="72" height="45" stroke="Black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><text transform="translate(922 207)" fill="Black"><tspan font-size="12pt" fill="Black" x="16.999023" y="11" textLength="28.001">GET/</tspan><tspan font-size="12pt" fill="Black" x="4.993164" y="25" textLength="52.013">POST/etc</tspan></text></g><g id="id68_Graphic"><rect x="1025" y="198" width="72" height="45" fill="White"/><rect x="1025" y="198" width="72" height="45" stroke="Black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><text transform="translate(1030 207)" fill="Black"><tspan font-size="12pt" fill="Black" x="5.3154297" y="11" textLength="54.703">Regex on </tspan><tspan font-size="12pt" fill="Black" x="14.998047" y="25" textLength="30.234">PATH</tspan></text></g><g id="id85_Graphic"><rect x="1025" y="279" width="72" height="68" fill="White"/><rect x="1025" y="279" width="72" height="68" stroke="Black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><text transform="translate(1030 285.5)" fill="Black"><tspan font-size="12pt" fill="Black" x="9.326172" y="11" textLength="46.681">(may be </tspan><tspan font-size="12pt" fill="Black" x="6.9882812" y="25" textLength="51.356998">compiled </tspan><tspan font-size="12pt" fill="Black" x="19" y="39" textLength="27.333">from </tspan><tspan font-size="12pt" fill="Black" x="5.3183594" y="53" textLength="51.363">shellglob)</tspan></text></g><g id="id70_Graphic"><rect x="1025" y="360" width="72" height="45" fill="White"/><rect x="1025" y="360" width="72" height="45" stroke="Black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><text transform="translate(1030 369)" fill="Black"><tspan font-size="12pt" fill="Black" x="15.323242" y="11" textLength="31.353">/foo/*/</tspan><tspan font-size="12pt" fill="Black" x="6.979492" y="25" textLength="47.384">{bar,baz}</tspan></text></g><g id="id89_Graphic"><rect x="1133" y="198" width="72" height="45" fill="White"/><rect x="1133" y="198" width="72" height="45" stroke="Black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><text transform="translate(1138 207)" fill="Black"><tspan font-size="12pt" fill="Black" x="11.652344" y="11" textLength="42.029">run {...} </tspan><tspan font-size="12pt" fill="Black" x="2.0253906" y="25" textLength="57.949">\&amp;sub 'sub'</tspan></text></g><g id="id99_Graphic"><rect x="1241" y="198" width="72" height="45" fill="White"/><rect x="1241" y="198" width="72" height="45" stroke="Black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><text transform="translate(1246 207)" fill="Black"><tspan font-size="12pt" fill="Black" x="3.3232422" y="11" textLength="58.687">Numerous </tspan><tspan font-size="12pt" fill="Black" x="9.988281" y="25" textLength="42.023">children</tspan></text></g><g id="id101_Graphic"><rect x="1187" y="279" width="72" height="45" fill="White"/><rect x="1187" y="279" width="72" height="45" stroke="Black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><text transform="translate(1192 288)" fill="Black"><tspan font-size="12pt" fill="Black" x="15.326172" y="11" textLength="34.681">[child, </tspan><tspan font-size="12pt" fill="Black" x="16.993164" y="25" textLength="28.013">child]</tspan></text></g><g id="id103_Graphic"><rect x="1295" y="279" width="72" height="45" fill="White"/><rect x="1295" y="279" width="72" height="45" stroke="Black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><text transform="translate(1300 288)" fill="Black"><tspan font-size="12pt" fill="Black" x="14.989258" y="11" textLength="35.355">{child; </tspan><tspan font-size="12pt" fill="Black" x="16.65625" y="25" textLength="28.687">child}</tspan></text></g><g id="id2_Graphic"><rect x="1295" y="117" width="72" height="45" fill="White"/><rect x="1295" y="117" width="72" height="45" stroke="Black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><text transform="translate(1300 126)" fill="Black"><tspan font-size="12pt" fill="Black" x="14.989258" y="11" textLength="32.021">when/</tspan><tspan font-size="12pt" fill="Black" x="15.654297" y="25" textLength="30.691">under</tspan></text></g><g id="id106_Graphic"><rect x="1403" y="117" width="72" height="45" fill="White"/><rect x="1403" y="117" width="72" height="45" stroke="Black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><text transform="translate(1408 126)" fill="Black"><tspan font-size="12pt" fill="Black" x="11.321289" y="11" textLength="39.356998">get/set/</tspan><tspan font-size="12pt" fill="Black" x="3.3115234" y="25" textLength="55.376">default/del</tspan></text></g><g id="id113_Graphic"><rect x="1511" y="117" width="72" height="45" fill="White"/><rect x="1511" y="117" width="72" height="45" stroke="Black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><text transform="translate(1516 119)" fill="Black"><tspan font-size="12pt" fill="Black" x="15.326172" y="11" textLength="31.347">show/</tspan><tspan font-size="12pt" fill="Black" x="9.326172" y="25" textLength="43.347">redirect/</tspan><tspan font-size="12pt" fill="Black" x="8.652344" y="39" textLength="44.695">dispatch</tspan></text></g><g id="id119_Graphic"><rect x="1619" y="117" width="72" height="45" fill="White"/><rect x="1619" y="117" width="72" height="45" stroke="Black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><text transform="translate(1624 119)" fill="Black"><tspan font-size="12pt" fill="Black" x="4.6503906" y="11" textLength="52.699">next_rule/</tspan><tspan font-size="12pt" fill="Black" x="6.654297" y="25" textLength="48.691002">last_rule/</tspan><tspan font-size="12pt" fill="Black" x="17.324219" y="39" textLength="27.351">abort</tspan></text></g><g id="id131_Graphic"><rect x="1727" y="117" width="72" height="45" fill="White"/><rect x="1727" y="117" width="72" height="45" stroke="Black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><text transform="translate(1732 126)" fill="Black"><tspan font-size="12pt" fill="Black" x="2.649414" y="11" textLength="56.701">already_ru</tspan><tspan font-size="12pt" fill="Black" x="27.663086" y="25" textLength="6.673">n</tspan></text></g><g id="id109_Graphic"><rect x="1349" y="198" width="72" height="45" fill="White"/><rect x="1349" y="198" width="72" height="45" stroke="Black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><text transform="translate(1354 200)" fill="Black"><tspan font-size="12pt" fill="Black" x="15.657227" y="11" textLength="34.019">Stash </tspan><tspan font-size="12pt" fill="Black" x=".31445312" y="25" textLength="61.371">manipulatio</tspan><tspan font-size="12pt" fill="Black" x="27.663086" y="39" textLength="6.673">n</tspan></text></g><g id="id111_Graphic"><rect x="1457" y="198" width="72" height="45" fill="White"/><rect x="1457" y="198" width="72" height="45" stroke="Black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><text transform="translate(1462 200)" fill="Black"><tspan font-size="12pt" fill="Black" x="5.4853516" y="11" textLength="54.363">(=request </tspan><tspan font-size="12pt" fill="Black" x="10.993164" y="25" textLength="43.347">params </tspan><tspan font-size="12pt" fill="Black" x="10.996094" y="39" textLength="40.007">initially)</tspan></text></g><g id="id117_Graphic"><rect x="1565" y="198" width="72" height="45" fill="White"/><rect x="1565" y="198" width="72" height="45" stroke="Black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><text transform="translate(1570 200)" fill="Black"><tspan font-size="12pt" fill="Black" x="7.3251953" y="11" textLength="50.683">Goto (for </tspan><tspan font-size="12pt" fill="Black" x="1.38671875" y="25" textLength="62.56">"before/on" </tspan><tspan font-size="12pt" fill="Black" x="14.324219" y="39" textLength="33.351002">stage)</tspan></text></g><g id="id121_Graphic"><rect x="1673" y="198" width="72" height="45" fill="White"/><rect x="1673" y="198" width="72" height="45" stroke="Black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><text transform="translate(1678 207)" fill="Black"><tspan font-size="12pt" fill="Black" x="18.332031" y="11" textLength="28.669">Flow </tspan><tspan font-size="12pt" fill="Black" x="12.991211" y="25" textLength="36.016998">control</tspan></text></g><g id="id54_Graphic"><rect x="1835" y="117" width="72" height="45" fill="White"/><rect x="1835" y="117" width="72" height="45" stroke="Black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><text transform="translate(1840 133)" fill="Black"><tspan font-size="12pt" fill="Black" x="14.986328" y="11" textLength="32.027">plugin</tspan></text></g><g id="id56_Graphic"><rect x="1835" y="198" width="72" height="97" fill="White"/><rect x="1835" y="198" width="72" height="97" stroke="Black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><text transform="translate(1840 212)" fill="Black"><tspan font-size="12pt" fill="Black" x="13.993164" y="11" textLength="37.347">Partial </tspan><tspan font-size="12pt" fill="Black" x="13.993164" y="25" textLength="37.347">orders </tspan><tspan font-size="12pt" fill="Black" x="8.3154297" y="39" textLength="48.703">between </tspan><tspan font-size="12pt" fill="Black" x="7.6503906" y="53" textLength="50.033">mounted </tspan><tspan font-size="12pt" fill="Black" x=".31738281" y="67" textLength="61.365">dispatchers</tspan></text></g></g></g></svg>

Added: jifty/branches/schema-plugins/doc/jifty-model-svk
==============================================================================
--- (empty file)
+++ jifty/branches/schema-plugins/doc/jifty-model-svk	Mon Jan 29 21:05:02 2007
@@ -0,0 +1,154 @@
+=head1 name
+
+Jifty SVK Model docs
+
+=head1 SUMMARY
+
+
+
+=head1 IMPLEMENTATION
+
+=head2 Reading and writing from the data store
+
+- Upon each mount, read everything, expiry-keyed by revnum
+    - Build in-memory index for common accesses
+    - Encourage ->begin and ->commit to take advantage of svk txns
+    - Otherwise it's autocommit
+        - svn:author is $ApplicationClass-$ApplicationUser
+
+=head2 Implementation plan
+
+=head3 Functionality
+
+=over
+
+=item  create objects
+
+=item  read objects
+
+=item  find objects
+
+=item  update objects
+
+=item  delete objects
+
+=back
+
+
+=head3 API
+
+- First step is a memory-only, svn-compatible layout backend store
+    - Composed of alternate implementation of APIs of:
+        - Jifty::Record
+        - Jifty::Collection
+
+
+=head4 Jifty::Record
+
+Methods:
+
+=over
+
+=item create
+
+=item set
+
+=item value (get)
+
+=item delete
+
+=item 
+
+
+
+=back
+
+
+=head4 Jifty::Collection
+
+=over
+
+=item next
+
+=item items_array_ref
+
+=item unlimit
+
+=item search 
+
+This is a new API. It replaces Jifty::DBI::Record's "limit"
+
+
+My $tasks = MyApp::Model::TaskCollection->new();
+
+grep { $_->summary =~ 'foo'} grep { $_->owner 
+
+
+# Tasks with a summary matching 'patch' AND  with patches (computed)
+
+$tasks->with( summary => qr/patch/)->with( sub { $_->has_patches()  } ) 
+
+# Tasks with a summary matching 'patch' or with patches (computed)
+
+$tasks->in( $tasks->with(summary => qr/patch), $tasks->with(sub {$_->has_patches}))
+
+# Tasks with a summary that doesn't match 'patch' with patches
+$tasks->without( summary => qr/patch/)->with( sub { $_->has_patches()  } ) 
+
+
+=back
+
+=head2 Data storage format (In SVN)
+
+- Subversion based object store, using headless YAML::Syck for now
+    - Each object is a /UUID/ directory
+        - Optionally encoded as /U/UUID/ or /U/UU/UUID/ etc
+    - Each field is a /UUID/field_name file
+        - If it has a jifty:class then it's going to be blessed into that
+    - Type the object is encoded as the dirprop jifty:table
+        - It's blessed into the "class" name defined in the jifty-table repository
+    - Time of creation object is encoded as the dirprop jifty:created
+        - A simple floating number of Time::HiRes::time()
+    - The jifty:table themselves are but UUIDs of table-objects
+        - Also stored in the data store
+        - They are of the builtin table "Jifty::Model::Table"
+            - "class"   : [ "Perl::Land::Class" ]   # Record Class
+        - They are of the builtin table "Jifty::Model::Column"
+            - "table"   : the Table it's associated of
+            - "name"    : field name
+            - "type"    : jifty type-tag
+            - ...other column info...
+        - J::M::T and J::M::C (recursively defined) are always present in any data store
+        - Consequently, jifty model --create must do a uuidgen when backending SVN.
+
+
+=head3 Runtime storage format (in memory)
+
+    - In-memory structure looks like this:
+        {$type-uuid}
+            [objects-sorted-by-timestamp]
+                - inside-out objects comprised of a single UUID as payload
+        {$object-uuid}
+            - real stuff, blessed hashes of
+                field       => value-or-object
+                '.'         => UUID
+                '.created'  => timestamp
+                '.table'    => table name
+    - Column/schema info is encoded in the store itself as {$type-uuid-of-Jifty::Model::Type}{*}
+        - Introspect/modifiable as any regular model
+
+=head2 Limitations
+
+
+=head3 Runtime Typecasting
+
+my $uuid = $typed_record->id;   # concat of time and uuid
+# ...somebody retypes it and stores it...
+$typed_record->load_by_id($uuid); # oops
+
+=head3 Performance
+
+=head3 Search
+
+=head3 Scalability
+

Added: jifty/branches/schema-plugins/doc/jifty-plugins-2.0
==============================================================================
--- (empty file)
+++ jifty/branches/schema-plugins/doc/jifty-plugins-2.0	Mon Jan 29 21:05:02 2007
@@ -0,0 +1,141 @@
+* Plugins and actions need to work better
+* Plugins should be able to create model classes
+* So should applications
+* Plugins can add columns to model classes
+* Plugins can add logic to model classes (before_*, after_* hooks)
+* Plugins should be able to add properties to columns
+* The app always overrides plugins
+* Plugins are loaded and evaluated in order
+* Models should become mixins when appropriate
+  - But if the app doesn't define one, they can create classes/tables #'
+
+
+The plugins we want in our ponyverse:
+* ::Users
+* ::Users::Identity::EmailedToken
+*                  ::UsernamePassword
+*                  ::OpenID
+*                  ::Certs
+*                  ::{Assertion,Kerberos,...}
+*        ::ResetIdentity (change password for any identity once logged in / add identity)
+* ::Users::Signup
+* ::Users::Login
+* ::Users::EmailAddress
+
+::Users
+* unique ID
+* created_date, update_date, created_by, updated_by
+* display_name field (which you can force to something -- e.g. email, openid, name from cert)
+ * (Jifty::Record _brief_description returns this?)
+* last_login (?)
+* Do superuser and nobody live in the database? (That's authz)
+
+Where do identity plugins hook?
+* Add columns
+* Get credentials, return:
+    * These are valid
+    * These are invalid
+    * Other auth error ``I don't know''
+  * bounce trips go through continuations
+* load_by_unique_id
+
+* ::Login
+* /login =>
+  * list of identity types
+   * for each, fields for login columns declared by the ::Identity::Foo plugin
+  * submit button
+* Login action
+  * load_by_unique_id
+  * if the user doesn't exist, callback (to signup) or error
+  * Passes credentials to the identity plugin's auth method
+   * Identities that need confirmation error here if needed
+  * frob the session as appropriate
+  * frob CurrentUser
+  * Adds Dispatcher variables
+* Logout action
+  * frob the session and current user
+  * dispatcher rule on /logout redirects
+
+* ::Signup
+* Signup action
+  * verifies credentials - validates fields (inc. uniqueness)
+  * Creates a record
+  * Add a message, and push the user to the login page with a filled-out login action
+
+* What do ``mixins'' *mean*?
+ * We want injection, not actual mixins
+
+
+----- Where is this going to be hard? -----
+* Mixing columns into users
+* Getting the autogenerated actions to DTRT
+* hooks look kinda like Plagger
+* If there are multiple plugin models with no app model,
+  they all get mixed into the null model
+
+
+----- Username/password plugin ------
+
+# Model (Jifty::Plugin::User::Identity::UsernamePassword::Model::User)
+
+column 'username' =>
+  type is 'text',
+  is unique;
+
+column 'password' =>
+  type is 'text',
+  render_as 'Password',
+  filters are qw(Jifty::DBI::Filter::SaltHash);
+
+sub password_is {
+    my $self = shift;
+    my $pass = shift;
+
+    return undef unless $self->_value('password');
+
+    my ($hash, $salt) = @{$self->_value('password')};
+
+    return 1 if ( $hash eq Digest::MD5::md5_hex($pass . $salt) );
+    return undef;
+
+}
+
+# ``exports''
+sub load_by_unique_id {
+    my $self = shift;
+    my %args = (username => undef, @_);
+    return $self->load_by_columns(username => $args{username});
+}
+
+sub validate_credentials {
+    my $self = shift;
+    my %args = (username => undef, @_);
+    return unless $self->id;
+    return $self->password_is($args{password});
+}
+
+# Jifty::Plugin::User::Identity::UsernamePassword::Action::Login
+
+param username =>
+  render_as 'Text';
+
+param password =>
+  render_as 'Password';
+
+
+
+# Login plugin Action::Login
+sub check_credentials {
+    my $self = shift;
+    my $userobj = MyApp::Model::User->new;
+    my $user;
+    foreach my $identity_type ($userobj->identity_plugins) {
+        if($userobj->($identity_type . "::load_by_unique_id")($self->argument_values)) {
+            if($userobj->($identity_type . "::validate_credentials")($self->argument_values)) {
+                ...
+            } else {
+                ...
+            }
+        }
+    }
+}

Added: jifty/branches/schema-plugins/doc/jifty-web-form-etc
==============================================================================
--- (empty file)
+++ jifty/branches/schema-plugins/doc/jifty-web-form-etc	Mon Jan 29 21:05:02 2007
@@ -0,0 +1,69 @@
+The Jifty::Web::Form::* classes are currently a bit of a mess. This is
+an effort to document their internals so they make some sense to
+whoever finally gets motivates to fix them (which may well be me).
+
+C<Jifty::Web::Form::Element> is the base of *every* class in the
+hierarchy. Virtually any widget that Jifty renders, be it a link,
+button, or form field, comes from some subclass of
+C<Jifty::Web::Form::Element>
+
+C<Element> itself deals essentially only with writing out javascript
+event handlers for widgets. Its <javascript> method walks the
+C<onclick> argument to all those buttons and links, building up a data
+structure that is eventually serialized using JSON and passed to
+jifty.js's C<update> function in an C<onclick=> wrapper.
+
+Form fields (usually created by C<form_field> calls on a
+C<Jifty::Action> are all subclasses of C<Jifty::Web::Form::Field>,
+(C<Jifty::Web::Form::Field::I<something>).
+
+C<Field> takes care of most of the work of rendering form fields. It
+renders the label, autocompletion, placeholders, hints, validation
+errors and warnings, and so on. Subclasses override methods as
+appropriate to add or alter details of the rendering. Note that
+subclasses need *not* concern themselves with making sure that the
+field is rendered as the correct kind of widget (field, select, etc.),
+assuming they represent a standard, single, HTML C<input> tag (as
+opposed to, say, C<Combobox>). That is dealt with by the C<type>
+magic:
+
+Whenever you create a C<Field>, it has a C<type>. Normally, this
+represents the C<type> property on the C<input> tag. In order to make
+the system extensible, however, it *also* indicates what perl class
+this widget will be. C<Jifty::Web::Form::Field::new> blesses the
+returned object into C<'Jifty::Web::Form::Field::' . ucfirst
+$type>. The stock rendering renders an input field with
+C<type="$type">, but subclasses can override C<render_widget> to
+render something else -- see C<Jifty::Web::Form::Field::Combobox> for
+an example of doing this.
+
+Simple links are instances of C<Jifty::Web::Form::Field::Link>. This
+class is fairly simple -- it merely renders as a HTML C<a> tag with
+the appropriate attributes.
+
+The only detail that remains is the non-javascript state-variable
+emulation of AJAX support on links and buttons. This is
+C<Jifty::Web::Form::Field::Clickable>'s job. C<Clickable> is also a
+C<Element>, which means it inherits the Javascript hooks. Its
+constructor builds up a list of state variables that need to be
+B<saved> from the previous request, while its C<generate> method walks
+the javascript hooks inherited from C<Element> and generates new state
+variables that will need to be sent by this button to simulate the
+AJAX effects given in the C<onclick>. If the clickable needs to submit
+actions, C<generate> creates it as a button, and otherwise it creates
+a link. It does this by creating a *new*
+C<Jifty::Web::Form::Field::Link> or C<Jifty::Web::Form::Field::Field>
+object, and serializing all the state variables it's built up onto
+that object appropriately (in the name, if it's a button, as GET
+parameters if it's a link).
+
+This final step, where a C<Clickable> (which is not renderable) clones
+itself into a different class that can be rendered, makes use of the
+C<accessors> method defined in C<Element>. Every subclass of
+C<Element> keeps a list of the accessors defined on that class
+(typically these are defined using C<Class::Accessor::Fast>, but not
+always). When C<Clickable> needs to clone itself, it walks the list
+C<($self->accessors)>, building up a hash of all the accessor
+key-value pairs on itself, and passes these to C<new> on C<Field> or
+C<Link>, which calls accessors on itself for every C<key => value>
+pair in its argument list.

Added: jifty/branches/schema-plugins/doc/packaging
==============================================================================
--- (empty file)
+++ jifty/branches/schema-plugins/doc/packaging	Mon Jan 29 21:05:02 2007
@@ -0,0 +1,78 @@
+For Jifty:
+
+* It should be possible for Jifty's developers to package bin/jifty as a 
+  single platform-specifc "runnable" application, including lib/ share/ and all
+  non-core perl dependencies. (+ libraries?)
+
+
+
+For any Jifty application:
+
+* It should be possible for an end-user to package the source code of a Jifty 
+  application as a single platform-specific "runnable" application.
+
+* Ideally, it should be possible to turn a packaged application into 
+  an unpacked copy of the application's source code and dependent libraries.
+
+* It should be possible to install a Jifty application on a local disk 
+  such that multiple instances of the application can run with only
+  a site_config.yml file. (or without it)
+
+* It should be possible for an end user of one of these installed
+  applications to snapshot the application and all its assets, internal
+  libraries and dependencies to a private directory)
+
+    In all cases:
+        * --with-deps includes the installed versions of our dependencies.
+        * plugins are treated as CPAN dists for the purposes of dependency management
+
+    jifty package --file /tmp/myapp.exe --with-deps
+        * Takes multiple forms of targets
+        * Defaults to the zipped form
+        * --file is the path of the output file 
+
+    jifty dist --with-deps
+        * make a source distribution of this application, suitable for handing to a developer
+    jifty isolate  --with-deps 
+        * needs a better name 
+        * Pull in all dependencies, as well as jifty.
+
+    jifty install/uninstall
+        * some sort of management. will also work on plugins
+
+
+
+# A dist blib builder
+
+# A dist blib packager (->zip with a makefile.pl - it works as a par and as a dist)
+
+# Package multiple dists as a single dist.
+
+# Pony: an automatic deps-writer that will design a list of deps for 
+the systemwide currently installed modules.
+
+
+# Must include shared libs (expat, svn, etc)
+
+# Some way to deal with systemwide shared libs, like Pg
+
+# an alien extractor that analyzes already-built XS libs (in either blib/ or sitelib)
+with platform-specific tools (ldd, xtools, etc) and pull in shared libraries, similar
+to how Alien::* currentl does it in a case-by-case basis.
+
+# A dist blib upgrader
+
+# A cpan workalike for jifty dists
+
+# An installation scheme for
+
+    {$INSTALL_DIR,$APP_DIR}/share/jifty/deps/{`archname`,noarch}
+
+
+# one blib/ directory for the tuple of
+    (dist, version, `arch` or "noarch" , perl version?)
+
+# an @INC populator     
+    pushes a glob for arch-independent  (rename this: blib-noarch/*
+    pushes a glob for per-arch libs  blib-`arch`/*
+

Added: jifty/branches/schema-plugins/doc/plugin-requirements
==============================================================================
--- (empty file)
+++ jifty/branches/schema-plugins/doc/plugin-requirements	Mon Jan 29 21:05:02 2007
@@ -0,0 +1,52 @@
+21:36 <obra> so. what would people like to see out of a jifty plugin framework?
+21:39 <audreyt> I'd like to see that a dispatcher plugin cannot affect an action plugin
+21:43 <obra> What do you mean? I'd expect that a plugin would be able to install dispatcher rules and actions
+21:43 <obra> so we could make the "EditFile" thing a plugin
+21:44 <audreyt> I'd like to see JiftyX::EditFile::Dispatch
+21:44 <audreyt> er Dispatcher
+21:44 <audreyt> JiftyX::EditFile::Action
+21:44 <audreyt> as separate namespaces (maybe inside the same EditFile.pm)
+21:44 <audreyt> of course, JiftyX is better spelled as Jifty::Plugin
+21:44 <obra> Jiftyhashi?
+21:45 <audreyt> Java has coffee beans
+21:45 <audreyt> maybe Jifty has tea bags
+21:45 <audreyt> Jif::Tea::Bag
+21:45 <obra> *groan*
+21:46 <obra> so. about plugins
+21:46 <obra> I guess there are two different things here
+21:46 <obra> 1) plugins for parts of jifty should be in the right namespaces
+21:46 <obra> 2) should a plugin be able to install dispatcher rules directly?
+21:46 <obra> ie, "use this plugin and it adds rules at these trigger points"
+21:48 <obra> I want "Login" and "Signup" to become plugins
+21:48 <obra> so I can stop cargo culting them between apps
+21:48 <audreyt> so sorta like rt callbacks
+21:48 <obra> yeah. was thinking more like plagger's system. it looks pretty
+21:48 <obra> named points. so even if they move between files, you don't lose
+21:48 <audreyt> yup
+21:49 <obra> so. this means I need to be able to:
+21:49 <obra> install actions
+21:49 <obra> install dispatcher rules at all stages
+21:49 <obra> install static content
+21:49 <obra> install templates
+21:49 <obra> possibly install widgets (aka form fields)
+21:49 <obra> install javascript libs and css files
+21:50 <obra> (special cases of static content)
+21:50 <obra> (but also hooks to add those things to the generated header)
+21:50 <audreyt> right
+21:50 <obra> what else am I missing? ;)
+21:50 <obra> oh. new jifty commands?
+21:51 <audreyt> po files are considered templates?
+21:51 <obra> # ./bin/jifty fooplugin
+21:51 <obra> no. pofiles are anotehr item for the list
+21:51 <audreyt> declare dependency? (normal cpan semantics?)
+21:51 <obra> another
+21:51 <obra> yeah. I'd just use perl require lines
+21:51 <audreyt> partial ordering? (run this before that)
+21:52 <obra> in dispatchers?
+21:52 <obra> or actions?
+21:52 <obra> or what?
+21:57 <audreyt> sorry
+21:57 <audreyt> from callbacks
+21:57 <obra> nod. I worry a little bit about the complexity. when would we want it for callbacks other than the dispatcher rules?
+21:58 <audreyt> if all your login etc are in well known places
+

Added: jifty/branches/schema-plugins/doc/plugin-syntax
==============================================================================
--- (empty file)
+++ jifty/branches/schema-plugins/doc/plugin-syntax	Mon Jan 29 21:05:02 2007
@@ -0,0 +1,61 @@
+# Login plugin
+package Login::Dispatcher;
+
+on 'login'    => 'login';
+on 'logout'   => 'logout';
+on 'signup'   => 'a_moment';
+
+after 'logout' => run {...clear_cookie...};
+before 'login' => run {...check_for_already_logged_in...};
+
+# RequiredAuth plugin
+package RequiredAuth::Dispatcher;
+
+before '*' => [
+    plugin Login,
+    run { ...check for auth, otherwise 401...  }
+],
+
+on 'auth_required' => run {...}
+
+# Dummy application
+package Dummy::Dispatcher;
+
+## implicit from config.yml:
+##    plugins:
+##       - RequireAuth:
+##           prefix: /blah
+##           args: vals
+##       - Login:
+##           prefix: /blah
+##           args: vals
+# trigger RequireAuth;
+
+after plugins 'Login::*' => [
+    on "logout" => show '/my/logout',
+]
+
+before plugins '*' => [
+    on "logout" => show '/my/logout',
+]
+
+on 'logout' => [
+    show '/my/logout',
+    plugin Login,
+]
+
+after 'login' => [
+]
+after PUT 'login' => [
+]
+
+after plugin Login => (
+before plugin Login => (
+    on "logout" => show '/my/logout',
+);
+
+
+on 'logout' => [
+    before_plugin Login,
+        show '/my/logout',
+]

Added: jifty/branches/schema-plugins/doc/plugins-restated-assumptions
==============================================================================
--- (empty file)
+++ jifty/branches/schema-plugins/doc/plugins-restated-assumptions	Mon Jan 29 21:05:02 2007
@@ -0,0 +1,80 @@
+* Plugins should be able to provide
+
+    * New actions
+    * New templates
+    * New models?
+
+* Plugins should be configurable
+    * should be able to be told about your  
+        * actions
+        * templates
+        * models
+
+* Plugins should be able to add dispatcher rules
+
+* The application should be able to spec what order 
+  dispatcher rules are run in. This gets sticky. 
+
+* If you don't spec explicit dispatcher rule ordering, what do you get?
+
+    for each of (before, on, after) {
+        run the plugin rules in the order plugins are defined
+        run my app's rules
+
+    }
+
+
+
+        before plugin Jifty::Login => {
+            before 'login' => {
+                .....
+            }
+        }
+
+
+
+Plugins provide templates.
+
+
+    auto/Jifty/Plugin/Login/share  (module::sharedir. wherever it puts stuff)
+
+
+    plugins have a default path they expose templates at.
+
+    so, Plugin::Login would expose templates at
+
+    /=/Login/
+
+    That path is 100% overridable by the app when it loads the plugin
+
+    An app's content always overrides a plugin's content.
+
+    If two plugins provide PO files or (templates to the same location,
+        either a built in location or an app-driven location), the most
+        recently loaded plugin's content override the older plugin's
+        content.
+
+
+Anatomy of a plugin -  In the end, plugins are apps. and apps are plugins.
+
+
+Jifty::Plugin::<name>
+
+    t/
+    lib/
+        Jifty/
+            Plugin/
+                <name>.pm
+                <name>/
+                        Dispatcher.pm
+                        Action/
+                        Model/ 
+    share/
+        po/
+        web/
+            static/
+            templates/
+~
+
+We're defining mount points for templates
+

Added: jifty/branches/schema-plugins/doc/pubsub/backend_message_types
==============================================================================
--- (empty file)
+++ jifty/branches/schema-plugins/doc/pubsub/backend_message_types	Mon Jan 29 21:05:02 2007
@@ -0,0 +1,15 @@
+Payload Types:
+
+ClientAction --> Republisher
+    #subscription
+    - Add Subscription (IP)
+    - Remove Subscription (IP)
+
+Republisher --> ClientRender
+    #pong-$IP
+    - Pong (IP, IS_ALIVE)
+
+Server --> Republisher
+    #pong
+    - Pong (IP, IS_ALIVE)
+

Added: jifty/branches/schema-plugins/doc/pubsub/subscriptions
==============================================================================
--- (empty file)
+++ jifty/branches/schema-plugins/doc/pubsub/subscriptions	Mon Jan 29 21:05:02 2007
@@ -0,0 +1,83 @@
+Subscriptions we want to support
+
+
+
+    Create,Read,Update,Delete
+        
+        Class: MyApp::Record::Foo
+     
+
+
+For hiveminder: NEWS
+
+    * on every page, we have a little box with the 3 most recent news entries:
+
+    <h2>News</h2>
+    <%perl>
+        my $sub = Jifty::ClientSubscription->new( 
+            query_class => 'BTDT::Model::News',
+            query => ['id_not' => undef],
+            # Ordering?
+            on_add => [
+            { render_with => '/fragments/news/item',
+              render => after => 'news.entries.last_child' 
+            },
+            { # how do we remove something if there are more than 3?
+            }
+
+            ]);
+
+
+For hiveminder:
+
+    My page is:
+
+        list of: tasks matching 'owner me, complete is not true'
+        each item is rendered as '/fragments/tasklist/view,  with args %ARGS and record => $found
+
+
+    Subscribe to:
+
+        * creation of things that match 'owner me, complete is not true'
+        * update, delete to anything that matches 'owner me, complete is not true' after the changes
+        * update, delete to anything that matches 'owner me, complete is not true' before the changes
+       
+
+
+    "Render this component as":
+
+        wrapper
+            list of items matching the subscription 'owner me, complete is not true'
+                render each item with '/fragments/tasklist/view', args => %ARGS, item $found
+
+
+            my $subscription = Jifty::ClientSubscription->new(
+                on_add => {
+                    args        => \%ARGS,
+                    render_with => '/fragments/tasklist/view',
+                    render => after => '.parent.last_child'
+                                # before, after, replacing
+                                
+                },
+                on_remove => {
+                    args        => \%ARGS,
+                    render => replacing => 'self'
+                    render_with => '/fragments/tasklist/fade_away'
+                },
+                query_class => 'BTDT::Model::Task',
+                query       => [ owner => 'me', complete_not => 'true' ]
+            );
+
+
+# Session::ClientSide-ish encoding of SIDs to subscribe
+# Each request carries IDs of its existing subs (stashed into ->subs)
+my $sid = Jifty->subs->add(
+    query_class => 'Ping',
+    query       => [ host => '127.0.0.1' ],
+    render_with => '/fragments/pong',
+);
+Jifty->subs->cancel($sid);
+
+# This actually just calls the fragments with Publisher-msg structures as %ARGS
+# Print-on-void-context, return-on-other-contexts
+Jifty->subs->render;

Added: jifty/branches/schema-plugins/doc/pubsub/system_architecture.graffle
==============================================================================
--- (empty file)
+++ jifty/branches/schema-plugins/doc/pubsub/system_architecture.graffle	Mon Jan 29 21:05:02 2007
@@ -0,0 +1,1744 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>ActiveLayerIndex</key>
+	<integer>0</integer>
+	<key>AutoAdjust</key>
+	<true/>
+	<key>CanvasColor</key>
+	<dict>
+		<key>w</key>
+		<string>1</string>
+	</dict>
+	<key>CanvasOrigin</key>
+	<string>{0, 0}</string>
+	<key>CanvasScale</key>
+	<real>1</real>
+	<key>ColumnAlign</key>
+	<integer>1</integer>
+	<key>ColumnSpacing</key>
+	<real>36</real>
+	<key>CreationDate</key>
+	<string>2006-10-24 12:01:34 -0700</string>
+	<key>Creator</key>
+	<string>Jesse Vincent</string>
+	<key>DisplayScale</key>
+	<string>1 in = 1 in</string>
+	<key>GraphDocumentVersion</key>
+	<integer>5</integer>
+	<key>GraphicsList</key>
+	<array>
+		<dict>
+			<key>Bounds</key>
+			<string>{{756, 39.835}, {211, 137}}</string>
+			<key>Class</key>
+			<string>ShapedGraphic</string>
+			<key>ID</key>
+			<integer>82</integer>
+			<key>Shape</key>
+			<string>Rectangle</string>
+			<key>Text</key>
+			<dict>
+				<key>Text</key>
+				<string>{\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf410
+{\fonttbl\f0\fswiss\fcharset77 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural
+
+\f0\fs24 \cf0 Jifty Push System Architecture.\
+A. Tang  and J. Vincent - \
+October 2006}</string>
+			</dict>
+		</dict>
+		<dict>
+			<key>Bounds</key>
+			<string>{{330.451, 150.979}, {256, 14}}</string>
+			<key>Class</key>
+			<string>ShapedGraphic</string>
+			<key>FitText</key>
+			<string>YES</string>
+			<key>FontInfo</key>
+			<dict>
+				<key>Color</key>
+				<dict>
+					<key>w</key>
+					<string>0</string>
+				</dict>
+				<key>Font</key>
+				<string>Helvetica</string>
+				<key>Size</key>
+				<real>12</real>
+			</dict>
+			<key>ID</key>
+			<integer>80</integer>
+			<key>Line</key>
+			<dict>
+				<key>ID</key>
+				<integer>24</integer>
+				<key>Position</key>
+				<real>0.62390816211700439</real>
+				<key>RotationType</key>
+				<integer>0</integer>
+			</dict>
+			<key>Shape</key>
+			<string>Rectangle</string>
+			<key>Style</key>
+			<dict>
+				<key>shadow</key>
+				<dict>
+					<key>Draws</key>
+					<string>NO</string>
+				</dict>
+				<key>stroke</key>
+				<dict>
+					<key>Draws</key>
+					<string>NO</string>
+				</dict>
+			</dict>
+			<key>Text</key>
+			<dict>
+				<key>Text</key>
+				<string>{\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf410
+{\fonttbl\f0\fswiss\fcharset77 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural
+
+\f0\fs24 \cf0 (With a kill-me-when-republish-to-nobody flag)}</string>
+			</dict>
+		</dict>
+		<dict>
+			<key>Class</key>
+			<string>LineGraphic</string>
+			<key>ID</key>
+			<integer>78</integer>
+			<key>Points</key>
+			<array>
+				<string>{822.47, 460.7}</string>
+				<string>{822.329, 431.61}</string>
+			</array>
+			<key>Style</key>
+			<dict>
+				<key>stroke</key>
+				<dict>
+					<key>HeadArrow</key>
+					<string>FilledArrow</string>
+					<key>Pattern</key>
+					<integer>2</integer>
+					<key>TailArrow</key>
+					<string>0</string>
+				</dict>
+			</dict>
+			<key>Tail</key>
+			<dict>
+				<key>ID</key>
+				<integer>77</integer>
+			</dict>
+		</dict>
+		<dict>
+			<key>Bounds</key>
+			<string>{{748.211, 461.2}, {149, 97.8}}</string>
+			<key>Class</key>
+			<string>ShapedGraphic</string>
+			<key>ID</key>
+			<integer>77</integer>
+			<key>Shape</key>
+			<string>Rectangle</string>
+			<key>Style</key>
+			<dict>
+				<key>stroke</key>
+				<dict>
+					<key>Pattern</key>
+					<integer>2</integer>
+				</dict>
+			</dict>
+			<key>Text</key>
+			<dict>
+				<key>Text</key>
+				<string>{\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf410
+{\fonttbl\f0\fswiss\fcharset77 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural
+
+\f0\fs24 \cf0 Publish unsubscription from 'ping' events \
+($SUB into $DEL-SUBS)\
+\
+(May also happen \
+upon session GC)}</string>
+			</dict>
+		</dict>
+		<dict>
+			<key>Bounds</key>
+			<string>{{45.4648, 366.851}, {907.535, 54}}</string>
+			<key>Class</key>
+			<string>ShapedGraphic</string>
+			<key>FontInfo</key>
+			<dict>
+				<key>Color</key>
+				<dict>
+					<key>w</key>
+					<string>0</string>
+				</dict>
+				<key>Font</key>
+				<string>Helvetica</string>
+				<key>NSKern</key>
+				<real>0.0</real>
+				<key>Size</key>
+				<real>12</real>
+			</dict>
+			<key>ID</key>
+			<integer>1</integer>
+			<key>Shape</key>
+			<string>Rectangle</string>
+			<key>Style</key>
+			<dict>
+				<key>fill</key>
+				<dict>
+					<key>GradientColor</key>
+					<dict>
+						<key>w</key>
+						<string>0.666667</string>
+					</dict>
+				</dict>
+			</dict>
+			<key>Text</key>
+			<dict>
+				<key>Text</key>
+				<string>{\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf410
+{\fonttbl\f0\fswiss\fcharset77 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural
+
+\f0\fs24 \cf0 Message Bus}</string>
+			</dict>
+		</dict>
+		<dict>
+			<key>Bounds</key>
+			<string>{{241.567, 505}, {149, 54}}</string>
+			<key>Class</key>
+			<string>ShapedGraphic</string>
+			<key>ID</key>
+			<integer>75</integer>
+			<key>Shape</key>
+			<string>Rectangle</string>
+			<key>Text</key>
+			<dict>
+				<key>Text</key>
+				<string>{\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf410
+{\fonttbl\f0\fswiss\fcharset77 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural
+
+\f0\fs24 \cf0 Publish subscription to 'ping' events \
+($SUB into $ADD-SUBS)}</string>
+			</dict>
+		</dict>
+		<dict>
+			<key>Bounds</key>
+			<string>{{105, 505}, {133, 54}}</string>
+			<key>Class</key>
+			<string>ShapedGraphic</string>
+			<key>ID</key>
+			<integer>74</integer>
+			<key>Shape</key>
+			<string>Rectangle</string>
+			<key>Text</key>
+			<dict>
+				<key>Text</key>
+				<string>{\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf410
+{\fonttbl\f0\fswiss\fcharset77 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural
+
+\f0\fs24 \cf0 Start ping server}</string>
+			</dict>
+		</dict>
+		<dict>
+			<key>Bounds</key>
+			<string>{{398.5, 285.356}, {49, 28}}</string>
+			<key>Class</key>
+			<string>ShapedGraphic</string>
+			<key>FitText</key>
+			<string>YES</string>
+			<key>FontInfo</key>
+			<dict>
+				<key>Color</key>
+				<dict>
+					<key>w</key>
+					<string>0</string>
+				</dict>
+				<key>Font</key>
+				<string>Helvetica</string>
+				<key>Size</key>
+				<real>12</real>
+			</dict>
+			<key>ID</key>
+			<integer>72</integer>
+			<key>Line</key>
+			<dict>
+				<key>ID</key>
+				<integer>71</integer>
+				<key>Position</key>
+				<real>0.51288449764251709</real>
+				<key>RotationType</key>
+				<integer>0</integer>
+			</dict>
+			<key>Shape</key>
+			<string>Rectangle</string>
+			<key>Style</key>
+			<dict>
+				<key>shadow</key>
+				<dict>
+					<key>Draws</key>
+					<string>NO</string>
+				</dict>
+				<key>stroke</key>
+				<dict>
+					<key>Draws</key>
+					<string>NO</string>
+				</dict>
+			</dict>
+			<key>Text</key>
+			<dict>
+				<key>Text</key>
+				<string>{\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf410
+{\fonttbl\f0\fswiss\fcharset77 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural
+
+\f0\fs24 \cf0 Send\
+[$SUB]}</string>
+			</dict>
+		</dict>
+		<dict>
+			<key>Class</key>
+			<string>LineGraphic</string>
+			<key>ID</key>
+			<integer>71</integer>
+			<key>Points</key>
+			<array>
+				<string>{423, 349.516}</string>
+				<string>{423, 251.716}</string>
+			</array>
+			<key>Style</key>
+			<dict>
+				<key>stroke</key>
+				<dict>
+					<key>HeadArrow</key>
+					<string>FilledArrow</string>
+					<key>TailArrow</key>
+					<string>0</string>
+				</dict>
+			</dict>
+		</dict>
+		<dict>
+			<key>Bounds</key>
+			<string>{{784.411, 610.503}, {77, 42}}</string>
+			<key>Class</key>
+			<string>ShapedGraphic</string>
+			<key>FitText</key>
+			<string>YES</string>
+			<key>FontInfo</key>
+			<dict>
+				<key>Color</key>
+				<dict>
+					<key>w</key>
+					<string>0</string>
+				</dict>
+				<key>Font</key>
+				<string>Helvetica</string>
+				<key>Size</key>
+				<real>12</real>
+			</dict>
+			<key>ID</key>
+			<integer>69</integer>
+			<key>Line</key>
+			<dict>
+				<key>ID</key>
+				<integer>68</integer>
+				<key>Position</key>
+				<real>0.42627021670341492</real>
+				<key>RotationType</key>
+				<integer>0</integer>
+			</dict>
+			<key>Shape</key>
+			<string>Rectangle</string>
+			<key>Style</key>
+			<dict>
+				<key>shadow</key>
+				<dict>
+					<key>Draws</key>
+					<string>NO</string>
+				</dict>
+				<key>stroke</key>
+				<dict>
+					<key>Draws</key>
+					<string>NO</string>
+				</dict>
+			</dict>
+			<key>Text</key>
+			<dict>
+				<key>Text</key>
+				<string>{\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf410
+{\fonttbl\f0\fswiss\fcharset77 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural
+
+\f0\fs24 \cf0 Jifty::Action:\
+Unsubscribe\
+Action::Ping}</string>
+			</dict>
+		</dict>
+		<dict>
+			<key>Class</key>
+			<string>LineGraphic</string>
+			<key>Head</key>
+			<dict>
+				<key>ID</key>
+				<integer>77</integer>
+			</dict>
+			<key>ID</key>
+			<integer>68</integer>
+			<key>Points</key>
+			<array>
+				<string>{823, 685}</string>
+				<string>{822.792, 559.5}</string>
+			</array>
+			<key>Style</key>
+			<dict>
+				<key>stroke</key>
+				<dict>
+					<key>HeadArrow</key>
+					<string>FilledArrow</string>
+					<key>Pattern</key>
+					<integer>2</integer>
+					<key>TailArrow</key>
+					<string>0</string>
+				</dict>
+			</dict>
+		</dict>
+		<dict>
+			<key>Bounds</key>
+			<string>{{323.771, 263.402}, {83, 28}}</string>
+			<key>Class</key>
+			<string>ShapedGraphic</string>
+			<key>FitText</key>
+			<string>YES</string>
+			<key>FontInfo</key>
+			<dict>
+				<key>Color</key>
+				<dict>
+					<key>w</key>
+					<string>0</string>
+				</dict>
+				<key>Font</key>
+				<string>Helvetica</string>
+				<key>Size</key>
+				<real>12</real>
+			</dict>
+			<key>ID</key>
+			<integer>62</integer>
+			<key>Line</key>
+			<dict>
+				<key>ID</key>
+				<integer>61</integer>
+				<key>Position</key>
+				<real>0.27589595317840576</real>
+				<key>RotationType</key>
+				<integer>0</integer>
+			</dict>
+			<key>Shape</key>
+			<string>Rectangle</string>
+			<key>Style</key>
+			<dict>
+				<key>shadow</key>
+				<dict>
+					<key>Draws</key>
+					<string>NO</string>
+				</dict>
+				<key>stroke</key>
+				<dict>
+					<key>Draws</key>
+					<string>NO</string>
+				</dict>
+			</dict>
+			<key>Text</key>
+			<dict>
+				<key>Text</key>
+				<string>{\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf410
+{\fonttbl\f0\fswiss\fcharset77 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural
+
+\f0\fs24 \cf0 Poll\
+$ADD-SUBS }</string>
+			</dict>
+		</dict>
+		<dict>
+			<key>Class</key>
+			<string>LineGraphic</string>
+			<key>ID</key>
+			<integer>61</integer>
+			<key>Points</key>
+			<array>
+				<string>{364.995, 247.455}</string>
+				<string>{365.995, 356}</string>
+			</array>
+			<key>Style</key>
+			<dict>
+				<key>stroke</key>
+				<dict>
+					<key>HeadArrow</key>
+					<string>FilledArrow</string>
+					<key>TailArrow</key>
+					<string>0</string>
+				</dict>
+			</dict>
+		</dict>
+		<dict>
+			<key>Bounds</key>
+			<string>{{982.555, 751.48}, {61, 14}}</string>
+			<key>Class</key>
+			<string>ShapedGraphic</string>
+			<key>FitText</key>
+			<string>YES</string>
+			<key>FontInfo</key>
+			<dict>
+				<key>Color</key>
+				<dict>
+					<key>w</key>
+					<string>0</string>
+				</dict>
+				<key>Font</key>
+				<string>Helvetica</string>
+				<key>Size</key>
+				<real>12</real>
+			</dict>
+			<key>ID</key>
+			<integer>60</integer>
+			<key>Line</key>
+			<dict>
+				<key>ID</key>
+				<integer>59</integer>
+				<key>Position</key>
+				<real>0.89849430322647095</real>
+				<key>RotationType</key>
+				<integer>0</integer>
+			</dict>
+			<key>Shape</key>
+			<string>Rectangle</string>
+			<key>Style</key>
+			<dict>
+				<key>shadow</key>
+				<dict>
+					<key>Draws</key>
+					<string>NO</string>
+				</dict>
+				<key>stroke</key>
+				<dict>
+					<key>Draws</key>
+					<string>NO</string>
+				</dict>
+			</dict>
+			<key>Text</key>
+			<dict>
+				<key>Text</key>
+				<string>{\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf410
+{\fonttbl\f0\fswiss\fcharset77 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural
+
+\f0\fs24 \cf0 Time &gt;&gt;&gt;}</string>
+			</dict>
+		</dict>
+		<dict>
+			<key>Class</key>
+			<string>LineGraphic</string>
+			<key>ID</key>
+			<integer>59</integer>
+			<key>Points</key>
+			<array>
+				<string>{30.8634, 757}</string>
+				<string>{1124.02, 758.647}</string>
+			</array>
+			<key>Style</key>
+			<dict>
+				<key>stroke</key>
+				<dict>
+					<key>HeadArrow</key>
+					<string>FilledArrow</string>
+					<key>TailArrow</key>
+					<string>0</string>
+				</dict>
+			</dict>
+		</dict>
+		<dict>
+			<key>Bounds</key>
+			<string>{{652.329, 607.255}, {84, 28}}</string>
+			<key>Class</key>
+			<string>ShapedGraphic</string>
+			<key>FitText</key>
+			<string>YES</string>
+			<key>FontInfo</key>
+			<dict>
+				<key>Color</key>
+				<dict>
+					<key>w</key>
+					<string>0</string>
+				</dict>
+				<key>Font</key>
+				<string>Helvetica</string>
+				<key>Size</key>
+				<real>12</real>
+			</dict>
+			<key>ID</key>
+			<integer>55</integer>
+			<key>Line</key>
+			<dict>
+				<key>ID</key>
+				<integer>54</integer>
+				<key>Position</key>
+				<real>0.51953768730163574</real>
+				<key>RotationType</key>
+				<integer>0</integer>
+			</dict>
+			<key>Shape</key>
+			<string>Rectangle</string>
+			<key>Style</key>
+			<dict>
+				<key>shadow</key>
+				<dict>
+					<key>Draws</key>
+					<string>NO</string>
+				</dict>
+				<key>stroke</key>
+				<dict>
+					<key>Draws</key>
+					<string>NO</string>
+				</dict>
+			</dict>
+			<key>Text</key>
+			<dict>
+				<key>Text</key>
+				<string>{\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf410
+{\fonttbl\f0\fswiss\fcharset77 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural
+
+\f0\fs24 \cf0 Push+Render\
+$EVENT}</string>
+			</dict>
+		</dict>
+		<dict>
+			<key>Class</key>
+			<string>LineGraphic</string>
+			<key>ID</key>
+			<integer>54</integer>
+			<key>Points</key>
+			<array>
+				<string>{694.329, 546.643}</string>
+				<string>{694.329, 690.255}</string>
+			</array>
+			<key>Style</key>
+			<dict>
+				<key>stroke</key>
+				<dict>
+					<key>HeadArrow</key>
+					<string>FilledArrow</string>
+					<key>TailArrow</key>
+					<string>0</string>
+				</dict>
+			</dict>
+		</dict>
+		<dict>
+			<key>Bounds</key>
+			<string>{{655.57, 439.363}, {49, 24}}</string>
+			<key>Class</key>
+			<string>ShapedGraphic</string>
+			<key>FitText</key>
+			<string>YES</string>
+			<key>FontInfo</key>
+			<dict>
+				<key>Color</key>
+				<dict>
+					<key>w</key>
+					<string>0</string>
+				</dict>
+				<key>Font</key>
+				<string>Helvetica-Bold</string>
+				<key>Size</key>
+				<real>10</real>
+			</dict>
+			<key>ID</key>
+			<integer>56</integer>
+			<key>Line</key>
+			<dict>
+				<key>ID</key>
+				<integer>52</integer>
+				<key>Position</key>
+				<real>0.45289328694343567</real>
+				<key>RotationType</key>
+				<integer>0</integer>
+			</dict>
+			<key>Shape</key>
+			<string>Rectangle</string>
+			<key>Style</key>
+			<dict>
+				<key>shadow</key>
+				<dict>
+					<key>Draws</key>
+					<string>NO</string>
+				</dict>
+				<key>stroke</key>
+				<dict>
+					<key>Draws</key>
+					<string>NO</string>
+				</dict>
+			</dict>
+			<key>Text</key>
+			<dict>
+				<key>Text</key>
+				<string>{\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf410
+{\fonttbl\f0\fswiss\fcharset77 Helvetica-Bold;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural
+
+\f0\b\fs20 \cf0 Send\
+$EVENT}</string>
+			</dict>
+		</dict>
+		<dict>
+			<key>Class</key>
+			<string>LineGraphic</string>
+			<key>ID</key>
+			<integer>52</integer>
+			<key>Points</key>
+			<array>
+				<string>{680.07, 424.383}</string>
+				<string>{680.07, 483.957}</string>
+			</array>
+			<key>Style</key>
+			<dict>
+				<key>stroke</key>
+				<dict>
+					<key>HeadArrow</key>
+					<string>FilledArrow</string>
+					<key>TailArrow</key>
+					<string>0</string>
+				</dict>
+			</dict>
+		</dict>
+		<dict>
+			<key>Bounds</key>
+			<string>{{603.273, 452.914}, {52, 28}}</string>
+			<key>Class</key>
+			<string>ShapedGraphic</string>
+			<key>FitText</key>
+			<string>YES</string>
+			<key>FontInfo</key>
+			<dict>
+				<key>Color</key>
+				<dict>
+					<key>w</key>
+					<string>0</string>
+				</dict>
+				<key>Font</key>
+				<string>Helvetica</string>
+				<key>Size</key>
+				<real>12</real>
+			</dict>
+			<key>ID</key>
+			<integer>51</integer>
+			<key>Line</key>
+			<dict>
+				<key>ID</key>
+				<integer>50</integer>
+				<key>Position</key>
+				<real>0.41240772604942322</real>
+				<key>RotationType</key>
+				<integer>0</integer>
+			</dict>
+			<key>Shape</key>
+			<string>Rectangle</string>
+			<key>Style</key>
+			<dict>
+				<key>shadow</key>
+				<dict>
+					<key>Draws</key>
+					<string>NO</string>
+				</dict>
+				<key>stroke</key>
+				<dict>
+					<key>Draws</key>
+					<string>NO</string>
+				</dict>
+			</dict>
+			<key>Text</key>
+			<dict>
+				<key>Text</key>
+				<string>{\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf410
+{\fonttbl\f0\fswiss\fcharset77 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural
+
+\f0\fs24 \cf0 Poll\
+[$SUB] }</string>
+			</dict>
+		</dict>
+		<dict>
+			<key>Class</key>
+			<string>LineGraphic</string>
+			<key>ID</key>
+			<integer>50</integer>
+			<key>Points</key>
+			<array>
+				<string>{629, 489.057}</string>
+				<string>{629.661, 435.363}</string>
+			</array>
+			<key>Style</key>
+			<dict>
+				<key>stroke</key>
+				<dict>
+					<key>HeadArrow</key>
+					<string>FilledArrow</string>
+					<key>TailArrow</key>
+					<string>0</string>
+				</dict>
+			</dict>
+		</dict>
+		<dict>
+			<key>Bounds</key>
+			<string>{{532.773, 447.813}, {52, 28}}</string>
+			<key>Class</key>
+			<string>ShapedGraphic</string>
+			<key>FitText</key>
+			<string>YES</string>
+			<key>FontInfo</key>
+			<dict>
+				<key>Color</key>
+				<dict>
+					<key>w</key>
+					<string>0</string>
+				</dict>
+				<key>Font</key>
+				<string>Helvetica</string>
+				<key>Size</key>
+				<real>12</real>
+			</dict>
+			<key>ID</key>
+			<integer>49</integer>
+			<key>Line</key>
+			<dict>
+				<key>ID</key>
+				<integer>48</integer>
+				<key>Position</key>
+				<real>0.41240772604942322</real>
+				<key>RotationType</key>
+				<integer>0</integer>
+			</dict>
+			<key>Shape</key>
+			<string>Rectangle</string>
+			<key>Style</key>
+			<dict>
+				<key>shadow</key>
+				<dict>
+					<key>Draws</key>
+					<string>NO</string>
+				</dict>
+				<key>stroke</key>
+				<dict>
+					<key>Draws</key>
+					<string>NO</string>
+				</dict>
+			</dict>
+			<key>Text</key>
+			<dict>
+				<key>Text</key>
+				<string>{\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf410
+{\fonttbl\f0\fswiss\fcharset77 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural
+
+\f0\fs24 \cf0 Poll\
+[$SUB] }</string>
+			</dict>
+		</dict>
+		<dict>
+			<key>Class</key>
+			<string>LineGraphic</string>
+			<key>ID</key>
+			<integer>48</integer>
+			<key>Points</key>
+			<array>
+				<string>{558.5, 483.957}</string>
+				<string>{559.161, 430.263}</string>
+			</array>
+			<key>Style</key>
+			<dict>
+				<key>stroke</key>
+				<dict>
+					<key>HeadArrow</key>
+					<string>FilledArrow</string>
+					<key>TailArrow</key>
+					<string>0</string>
+				</dict>
+			</dict>
+		</dict>
+		<dict>
+			<key>Bounds</key>
+			<string>{{432.043, 446.396}, {52, 28}}</string>
+			<key>Class</key>
+			<string>ShapedGraphic</string>
+			<key>FitText</key>
+			<string>YES</string>
+			<key>FontInfo</key>
+			<dict>
+				<key>Color</key>
+				<dict>
+					<key>w</key>
+					<string>0</string>
+				</dict>
+				<key>Font</key>
+				<string>Helvetica</string>
+				<key>Size</key>
+				<real>12</real>
+			</dict>
+			<key>ID</key>
+			<integer>47</integer>
+			<key>Line</key>
+			<dict>
+				<key>ID</key>
+				<integer>46</integer>
+				<key>Position</key>
+				<real>0.36850014328956604</real>
+				<key>RotationType</key>
+				<integer>0</integer>
+			</dict>
+			<key>Shape</key>
+			<string>Rectangle</string>
+			<key>Style</key>
+			<dict>
+				<key>shadow</key>
+				<dict>
+					<key>Draws</key>
+					<string>NO</string>
+				</dict>
+				<key>stroke</key>
+				<dict>
+					<key>Draws</key>
+					<string>NO</string>
+				</dict>
+			</dict>
+			<key>Text</key>
+			<dict>
+				<key>Text</key>
+				<string>{\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf410
+{\fonttbl\f0\fswiss\fcharset77 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural
+
+\f0\fs24 \cf0 Poll\
+[$SUB] }</string>
+			</dict>
+		</dict>
+		<dict>
+			<key>Class</key>
+			<string>LineGraphic</string>
+			<key>ID</key>
+			<integer>46</integer>
+			<key>Points</key>
+			<array>
+				<string>{458, 481}</string>
+				<string>{458.117, 425.087}</string>
+			</array>
+			<key>Style</key>
+			<dict>
+				<key>stroke</key>
+				<dict>
+					<key>HeadArrow</key>
+					<string>FilledArrow</string>
+					<key>TailArrow</key>
+					<string>0</string>
+				</dict>
+			</dict>
+		</dict>
+		<dict>
+			<key>Bounds</key>
+			<string>{{558.5, 256.36}, {57, 42}}</string>
+			<key>Class</key>
+			<string>ShapedGraphic</string>
+			<key>FitText</key>
+			<string>YES</string>
+			<key>FontInfo</key>
+			<dict>
+				<key>Color</key>
+				<dict>
+					<key>w</key>
+					<string>0</string>
+				</dict>
+				<key>Font</key>
+				<string>Helvetica</string>
+				<key>Size</key>
+				<real>12</real>
+			</dict>
+			<key>ID</key>
+			<integer>45</integer>
+			<key>Line</key>
+			<dict>
+				<key>ID</key>
+				<integer>44</integer>
+				<key>Position</key>
+				<real>0.24552829563617706</real>
+				<key>RotationType</key>
+				<integer>0</integer>
+			</dict>
+			<key>Shape</key>
+			<string>Rectangle</string>
+			<key>Style</key>
+			<dict>
+				<key>shadow</key>
+				<dict>
+					<key>Draws</key>
+					<string>NO</string>
+				</dict>
+				<key>stroke</key>
+				<dict>
+					<key>Draws</key>
+					<string>NO</string>
+				</dict>
+			</dict>
+			<key>Text</key>
+			<dict>
+				<key>Text</key>
+				<string>{\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf410
+{\fonttbl\f0\fswiss\fcharset77 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural
+
+\f0\fs24 \cf0 Publish \
+$EVENT\
+to $SUB}</string>
+			</dict>
+		</dict>
+		<dict>
+			<key>Class</key>
+			<string>LineGraphic</string>
+			<key>ID</key>
+			<integer>44</integer>
+			<key>Points</key>
+			<array>
+				<string>{587, 249.615}</string>
+				<string>{587, 362.615}</string>
+			</array>
+			<key>Style</key>
+			<dict>
+				<key>stroke</key>
+				<dict>
+					<key>HeadArrow</key>
+					<string>FilledArrow</string>
+					<key>TailArrow</key>
+					<string>0</string>
+				</dict>
+			</dict>
+		</dict>
+		<dict>
+			<key>Class</key>
+			<string>LineGraphic</string>
+			<key>ID</key>
+			<integer>42</integer>
+			<key>Points</key>
+			<array>
+				<string>{315.076, 504.5}</string>
+				<string>{312.334, 428.426}</string>
+			</array>
+			<key>Style</key>
+			<dict>
+				<key>stroke</key>
+				<dict>
+					<key>HeadArrow</key>
+					<string>FilledArrow</string>
+					<key>TailArrow</key>
+					<string>0</string>
+				</dict>
+			</dict>
+			<key>Tail</key>
+			<dict>
+				<key>ID</key>
+				<integer>75</integer>
+			</dict>
+		</dict>
+		<dict>
+			<key>Bounds</key>
+			<string>{{55.0165, 435.416}, {163, 42}}</string>
+			<key>Class</key>
+			<string>ShapedGraphic</string>
+			<key>FitText</key>
+			<string>YES</string>
+			<key>FontInfo</key>
+			<dict>
+				<key>Color</key>
+				<dict>
+					<key>w</key>
+					<string>0</string>
+				</dict>
+				<key>Font</key>
+				<string>Helvetica</string>
+				<key>Size</key>
+				<real>12</real>
+			</dict>
+			<key>ID</key>
+			<integer>41</integer>
+			<key>Line</key>
+			<dict>
+				<key>ID</key>
+				<integer>40</integer>
+				<key>Position</key>
+				<real>0.48351499438285828</real>
+				<key>RotationType</key>
+				<integer>0</integer>
+			</dict>
+			<key>Shape</key>
+			<string>Rectangle</string>
+			<key>Style</key>
+			<dict>
+				<key>shadow</key>
+				<dict>
+					<key>Draws</key>
+					<string>NO</string>
+				</dict>
+				<key>stroke</key>
+				<dict>
+					<key>Draws</key>
+					<string>NO</string>
+				</dict>
+			</dict>
+			<key>Text</key>
+			<dict>
+				<key>Text</key>
+				<string>{\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf410
+{\fonttbl\f0\fswiss\fcharset77 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural
+
+\f0\fs24 \cf0 Add \
+Subscription Channel $SUB:\
+Action::Ping}</string>
+			</dict>
+		</dict>
+		<dict>
+			<key>Class</key>
+			<string>LineGraphic</string>
+			<key>ID</key>
+			<integer>40</integer>
+			<key>Points</key>
+			<array>
+				<string>{137, 482.62}</string>
+				<string>{136, 428.426}</string>
+			</array>
+			<key>Style</key>
+			<dict>
+				<key>stroke</key>
+				<dict>
+					<key>HeadArrow</key>
+					<string>FilledArrow</string>
+					<key>TailArrow</key>
+					<string>0</string>
+				</dict>
+			</dict>
+		</dict>
+		<dict>
+			<key>Bounds</key>
+			<string>{{383.843, 121.654}, {149, 28}}</string>
+			<key>Class</key>
+			<string>ShapedGraphic</string>
+			<key>FitText</key>
+			<string>YES</string>
+			<key>FontInfo</key>
+			<dict>
+				<key>Color</key>
+				<dict>
+					<key>w</key>
+					<string>0</string>
+				</dict>
+				<key>Font</key>
+				<string>Helvetica</string>
+				<key>Size</key>
+				<real>12</real>
+			</dict>
+			<key>ID</key>
+			<integer>38</integer>
+			<key>Line</key>
+			<dict>
+				<key>ID</key>
+				<integer>24</integer>
+				<key>Position</key>
+				<real>0.42278197407722473</real>
+				<key>RotationType</key>
+				<integer>0</integer>
+			</dict>
+			<key>Shape</key>
+			<string>Rectangle</string>
+			<key>Style</key>
+			<dict>
+				<key>shadow</key>
+				<dict>
+					<key>Draws</key>
+					<string>NO</string>
+				</dict>
+				<key>stroke</key>
+				<dict>
+					<key>Draws</key>
+					<string>NO</string>
+				</dict>
+			</dict>
+			<key>Text</key>
+			<dict>
+				<key>Text</key>
+				<string>{\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf410
+{\fonttbl\f0\fswiss\fcharset77 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural
+
+\f0\fs24 \cf0 Publishes Event $EVENT:\
+PING 127.0.0.1 1ms}</string>
+			</dict>
+		</dict>
+		<dict>
+			<key>Bounds</key>
+			<string>{{30.8634, 623.165}, {71, 28}}</string>
+			<key>Class</key>
+			<string>ShapedGraphic</string>
+			<key>FitText</key>
+			<string>YES</string>
+			<key>FontInfo</key>
+			<dict>
+				<key>Color</key>
+				<dict>
+					<key>w</key>
+					<string>0</string>
+				</dict>
+				<key>Font</key>
+				<string>Helvetica</string>
+				<key>Size</key>
+				<real>12</real>
+			</dict>
+			<key>ID</key>
+			<integer>36</integer>
+			<key>Line</key>
+			<dict>
+				<key>ID</key>
+				<integer>34</integer>
+				<key>Position</key>
+				<real>0.38565847277641296</real>
+				<key>RotationType</key>
+				<integer>0</integer>
+			</dict>
+			<key>Shape</key>
+			<string>Rectangle</string>
+			<key>Style</key>
+			<dict>
+				<key>shadow</key>
+				<dict>
+					<key>Draws</key>
+					<string>NO</string>
+				</dict>
+				<key>stroke</key>
+				<dict>
+					<key>Draws</key>
+					<string>NO</string>
+				</dict>
+			</dict>
+			<key>Text</key>
+			<dict>
+				<key>Text</key>
+				<string>{\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf410
+{\fonttbl\f0\fswiss\fcharset77 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural
+
+\f0\fs24 \cf0 Jifty Action:\
+Ping}</string>
+			</dict>
+		</dict>
+		<dict>
+			<key>Class</key>
+			<string>LineGraphic</string>
+			<key>ID</key>
+			<integer>34</integer>
+			<key>Points</key>
+			<array>
+				<string>{65, 690}</string>
+				<string>{68.5352, 553}</string>
+			</array>
+			<key>Style</key>
+			<dict>
+				<key>stroke</key>
+				<dict>
+					<key>HeadArrow</key>
+					<string>FilledArrow</string>
+					<key>TailArrow</key>
+					<string>0</string>
+				</dict>
+			</dict>
+		</dict>
+		<dict>
+			<key>Bounds</key>
+			<string>{{39, 693.868}, {1051.46, 54}}</string>
+			<key>Class</key>
+			<string>ShapedGraphic</string>
+			<key>ID</key>
+			<integer>31</integer>
+			<key>Shape</key>
+			<string>Rectangle</string>
+			<key>Text</key>
+			<dict>
+				<key>Text</key>
+				<string>{\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf410
+{\fonttbl\f0\fswiss\fcharset77 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural
+
+\f0\fs24 \cf0 Client Browser}</string>
+			</dict>
+		</dict>
+		<dict>
+			<key>Bounds</key>
+			<string>{{470.033, 293.501}, {88.9045, 42}}</string>
+			<key>Class</key>
+			<string>ShapedGraphic</string>
+			<key>FitText</key>
+			<string>Vertical</string>
+			<key>FontInfo</key>
+			<dict>
+				<key>Color</key>
+				<dict>
+					<key>w</key>
+					<string>0</string>
+				</dict>
+				<key>Font</key>
+				<string>Helvetica</string>
+				<key>Size</key>
+				<real>12</real>
+			</dict>
+			<key>ID</key>
+			<integer>29</integer>
+			<key>Line</key>
+			<dict>
+				<key>ID</key>
+				<integer>28</integer>
+				<key>Position</key>
+				<real>0.59332269430160522</real>
+				<key>RotationType</key>
+				<integer>0</integer>
+			</dict>
+			<key>Shape</key>
+			<string>Rectangle</string>
+			<key>Style</key>
+			<dict>
+				<key>shadow</key>
+				<dict>
+					<key>Draws</key>
+					<string>NO</string>
+				</dict>
+				<key>stroke</key>
+				<dict>
+					<key>Draws</key>
+					<string>NO</string>
+				</dict>
+			</dict>
+			<key>Text</key>
+			<dict>
+				<key>Text</key>
+				<string>{\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf410
+{\fonttbl\f0\fswiss\fcharset77 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural
+
+\f0\fs24 \cf0 Publishes to \
+Channel \
+"$SERVER"}</string>
+			</dict>
+			<key>Wrap</key>
+			<string>YES</string>
+		</dict>
+		<dict>
+			<key>Class</key>
+			<string>LineGraphic</string>
+			<key>ID</key>
+			<integer>28</integer>
+			<key>Points</key>
+			<array>
+				<string>{514.486, 247.455}</string>
+				<string>{514.486, 360.455}</string>
+			</array>
+			<key>Style</key>
+			<dict>
+				<key>stroke</key>
+				<dict>
+					<key>HeadArrow</key>
+					<string>FilledArrow</string>
+					<key>TailArrow</key>
+					<string>0</string>
+				</dict>
+			</dict>
+		</dict>
+		<dict>
+			<key>Bounds</key>
+			<string>{{44.4648, 205.059}, {907.535, 36}}</string>
+			<key>Class</key>
+			<string>ShapedGraphic</string>
+			<key>FontInfo</key>
+			<dict>
+				<key>Color</key>
+				<dict>
+					<key>w</key>
+					<string>0</string>
+				</dict>
+				<key>Font</key>
+				<string>Helvetica</string>
+				<key>NSKern</key>
+				<real>0.0</real>
+				<key>Size</key>
+				<real>12</real>
+			</dict>
+			<key>ID</key>
+			<integer>27</integer>
+			<key>Shape</key>
+			<string>Rectangle</string>
+			<key>Style</key>
+			<dict>
+				<key>fill</key>
+				<dict>
+					<key>GradientColor</key>
+					<dict>
+						<key>w</key>
+						<string>0.666667</string>
+					</dict>
+				</dict>
+			</dict>
+			<key>Text</key>
+			<dict>
+				<key>Text</key>
+				<string>{\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf410
+{\fonttbl\f0\fswiss\fcharset77 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural
+
+\f0\fs24 \cf0 Republisher}</string>
+			</dict>
+		</dict>
+		<dict>
+			<key>Class</key>
+			<string>LineGraphic</string>
+			<key>ID</key>
+			<integer>24</integer>
+			<key>Points</key>
+			<array>
+				<string>{458.117, 88.7247}</string>
+				<string>{458.652, 199.725}</string>
+			</array>
+			<key>Style</key>
+			<dict>
+				<key>stroke</key>
+				<dict>
+					<key>HeadArrow</key>
+					<string>FilledArrow</string>
+					<key>TailArrow</key>
+					<string>0</string>
+				</dict>
+			</dict>
+		</dict>
+		<dict>
+			<key>Bounds</key>
+			<string>{{174, 29.3902}, {410.773, 59.5743}}</string>
+			<key>Class</key>
+			<string>ShapedGraphic</string>
+			<key>FontInfo</key>
+			<dict>
+				<key>Color</key>
+				<dict>
+					<key>w</key>
+					<string>0</string>
+				</dict>
+				<key>Font</key>
+				<string>Helvetica</string>
+				<key>NSKern</key>
+				<real>0.0</real>
+				<key>Size</key>
+				<real>12</real>
+			</dict>
+			<key>ID</key>
+			<integer>4</integer>
+			<key>Shape</key>
+			<string>Rectangle</string>
+			<key>Style</key>
+			<dict>
+				<key>fill</key>
+				<dict>
+					<key>GradientColor</key>
+					<dict>
+						<key>w</key>
+						<string>0.666667</string>
+					</dict>
+				</dict>
+			</dict>
+			<key>Text</key>
+			<dict>
+				<key>Text</key>
+				<string>{\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf410
+{\fonttbl\f0\fswiss\fcharset77 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural
+
+\f0\fs24 \cf0 Server $SERVER}</string>
+			</dict>
+		</dict>
+		<dict>
+			<key>Class</key>
+			<string>LineGraphic</string>
+			<key>Head</key>
+			<dict>
+				<key>ID</key>
+				<integer>4</integer>
+			</dict>
+			<key>ID</key>
+			<integer>22</integer>
+			<key>Points</key>
+			<array>
+				<string>{129.731, 504.727}</string>
+				<string>{-23, 405}</string>
+				<string>{344.348, 89.2904}</string>
+			</array>
+			<key>Style</key>
+			<dict>
+				<key>stroke</key>
+				<dict>
+					<key>HeadArrow</key>
+					<string>FilledArrow</string>
+					<key>LineType</key>
+					<integer>1</integer>
+					<key>TailArrow</key>
+					<string>0</string>
+				</dict>
+			</dict>
+			<key>Tail</key>
+			<dict>
+				<key>ID</key>
+				<integer>74</integer>
+			</dict>
+		</dict>
+		<dict>
+			<key>Bounds</key>
+			<string>{{65, 502}, {340.944, 59.5743}}</string>
+			<key>Class</key>
+			<string>ShapedGraphic</string>
+			<key>ID</key>
+			<integer>79</integer>
+			<key>Shape</key>
+			<string>Rectangle</string>
+		</dict>
+		<dict>
+			<key>Bounds</key>
+			<string>{{45.4648, 490.194}, {907.535, 54}}</string>
+			<key>Class</key>
+			<string>ShapedGraphic</string>
+			<key>ID</key>
+			<integer>32</integer>
+			<key>Shape</key>
+			<string>Rectangle</string>
+			<key>Text</key>
+			<dict>
+				<key>Text</key>
+				<string>{\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf410
+{\fonttbl\f0\fswiss\fcharset77 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural
+
+\f0\fs24 \cf0 Jifty Server}</string>
+			</dict>
+		</dict>
+	</array>
+	<key>GridInfo</key>
+	<dict/>
+	<key>GuidesLocked</key>
+	<string>NO</string>
+	<key>GuidesVisible</key>
+	<string>YES</string>
+	<key>HPages</key>
+	<integer>2</integer>
+	<key>ImageCounter</key>
+	<integer>1</integer>
+	<key>IsPalette</key>
+	<string>NO</string>
+	<key>KeepToScale</key>
+	<false/>
+	<key>Layers</key>
+	<array>
+		<dict>
+			<key>Lock</key>
+			<string>NO</string>
+			<key>Name</key>
+			<string>Layer 1</string>
+			<key>Print</key>
+			<string>YES</string>
+			<key>View</key>
+			<string>YES</string>
+		</dict>
+	</array>
+	<key>LayoutInfo</key>
+	<dict>
+		<key>LayoutTarget</key>
+		<integer>3</integer>
+	</dict>
+	<key>LinksVisible</key>
+	<string>NO</string>
+	<key>MagnetsVisible</key>
+	<string>NO</string>
+	<key>MasterSheet</key>
+	<string>Master 1</string>
+	<key>MasterSheets</key>
+	<array>
+		<dict>
+			<key>ActiveLayerIndex</key>
+			<integer>0</integer>
+			<key>AutoAdjust</key>
+			<true/>
+			<key>CanvasColor</key>
+			<dict>
+				<key>w</key>
+				<string>1</string>
+			</dict>
+			<key>CanvasOrigin</key>
+			<string>{0, 0}</string>
+			<key>CanvasScale</key>
+			<real>1</real>
+			<key>ColumnAlign</key>
+			<integer>1</integer>
+			<key>ColumnSpacing</key>
+			<real>36</real>
+			<key>DisplayScale</key>
+			<string>1 in = 1 in</string>
+			<key>GraphicsList</key>
+			<array/>
+			<key>GridInfo</key>
+			<dict/>
+			<key>HPages</key>
+			<integer>1</integer>
+			<key>IsPalette</key>
+			<string>NO</string>
+			<key>KeepToScale</key>
+			<false/>
+			<key>Layers</key>
+			<array>
+				<dict>
+					<key>Lock</key>
+					<string>NO</string>
+					<key>Name</key>
+					<string>Layer 1</string>
+					<key>Print</key>
+					<string>YES</string>
+					<key>View</key>
+					<string>YES</string>
+				</dict>
+			</array>
+			<key>LayoutInfo</key>
+			<dict>
+				<key>LayoutTarget</key>
+				<integer>3</integer>
+			</dict>
+			<key>Orientation</key>
+			<integer>2</integer>
+			<key>OutlineStyle</key>
+			<string>Basic</string>
+			<key>RowAlign</key>
+			<integer>1</integer>
+			<key>RowSpacing</key>
+			<real>36</real>
+			<key>SheetTitle</key>
+			<string>Master 1</string>
+			<key>UniqueID</key>
+			<integer>1</integer>
+			<key>VPages</key>
+			<integer>1</integer>
+		</dict>
+	</array>
+	<key>ModificationDate</key>
+	<string>2006-10-24 15:25:32 -0700</string>
+	<key>Modifier</key>
+	<string>Jesse Vincent</string>
+	<key>NotesVisible</key>
+	<string>NO</string>
+	<key>Orientation</key>
+	<integer>2</integer>
+	<key>OriginVisible</key>
+	<string>NO</string>
+	<key>OutlineStyle</key>
+	<string>Basic</string>
+	<key>PageBreaks</key>
+	<string>YES</string>
+	<key>PrintInfo</key>
+	<dict>
+		<key>NSBottomMargin</key>
+		<array>
+			<string>float</string>
+			<string>0</string>
+		</array>
+		<key>NSLeftMargin</key>
+		<array>
+			<string>float</string>
+			<string>0</string>
+		</array>
+		<key>NSRightMargin</key>
+		<array>
+			<string>float</string>
+			<string>0</string>
+		</array>
+		<key>NSTopMargin</key>
+		<array>
+			<string>float</string>
+			<string>0</string>
+		</array>
+	</dict>
+	<key>ReadOnly</key>
+	<string>NO</string>
+	<key>RowAlign</key>
+	<integer>1</integer>
+	<key>RowSpacing</key>
+	<real>36</real>
+	<key>SheetTitle</key>
+	<string>Canvas 1</string>
+	<key>SmartAlignmentGuidesActive</key>
+	<string>YES</string>
+	<key>SmartDistanceGuidesActive</key>
+	<string>YES</string>
+	<key>UniqueID</key>
+	<integer>1</integer>
+	<key>UseEntirePage</key>
+	<true/>
+	<key>VPages</key>
+	<integer>1</integer>
+	<key>WindowInfo</key>
+	<dict>
+		<key>CurrentSheet</key>
+		<string>0</string>
+		<key>DrawerOpen</key>
+		<true/>
+		<key>DrawerTab</key>
+		<string>Outline</string>
+		<key>DrawerWidth</key>
+		<real>209</real>
+		<key>FitInWindow</key>
+		<false/>
+		<key>Frame</key>
+		<string>{{0, 0}, {1680, 1072}}</string>
+		<key>ShowRuler</key>
+		<false/>
+		<key>ShowStatusBar</key>
+		<true/>
+		<key>VisibleRegion</key>
+		<string>{{-250, -92}, {1665, 958}}</string>
+		<key>Zoom</key>
+		<string>1</string>
+	</dict>
+</dict>
+</plist>

Added: jifty/branches/schema-plugins/doc/pubsub/system_architecture.png
==============================================================================
Binary file. No diff available.

Added: jifty/branches/schema-plugins/doc/talks/amazon-jifty.pdf
==============================================================================
Binary file. No diff available.

Added: jifty/branches/schema-plugins/doc/talks/blogdemo.png
==============================================================================
Binary file. No diff available.

Added: jifty/branches/schema-plugins/doc/talks/component-tree.png
==============================================================================
Binary file. No diff available.

Added: jifty/branches/schema-plugins/doc/talks/edit.png
==============================================================================
Binary file. No diff available.

Added: jifty/branches/schema-plugins/doc/talks/error.png
==============================================================================
Binary file. No diff available.

Added: jifty/branches/schema-plugins/doc/talks/euroscon.css
==============================================================================
--- (empty file)
+++ jifty/branches/schema-plugins/doc/talks/euroscon.css	Mon Jan 29 21:05:02 2007
@@ -0,0 +1,219 @@
+ at charset "UTF-8";
+
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Takahashi-Method-based Presentation Tool in XUL.
+ *
+ * The Initial Developer of the Original Code is SHIMODA Hiroshi.
+ * Portions created by the Initial Developer are Copyright (C) 2005
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s): SHIMODA Hiroshi <piro at p.club.ne.jp>
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#canvas {
+	/*
+        color: black !important;
+	background: white !important;
+        */
+	color: #000 !important;
+	background: white !important;
+        /* font-weight: bold; */
+	font-family:
+                "Candara"
+                "Georgia"
+                "DejaVu Serif Condensed"
+                "Arial"
+		"Bitstream Vera Sans"
+		"Verdana"
+		"Apple LiGothic"
+		"Arial Black"
+                "Bitstream Vera Sans"
+		sans-serif !important;
+}
+#canvas * {
+	cursor: pointer !important;
+}
+#canvas image {
+	width: auto;
+	height: auto;
+}
+.link-text {
+	color: #000066 !important;
+	text-decoration: none !important;
+}
+.link-text:hover {
+	color: #3333FF !important;
+/*        border-bottom: dotted 1px; */
+}
+.link-text:active {
+	color: #9999FF !important;
+}
+.s {
+        text-decoration: line-through;
+}
+.iu {
+        text-decoration: underline;
+        font-style: italic;
+}
+.ui {
+/*      text-decoration: underline; */
+        font-style: italic;
+}
+.u {
+        text-decoration: underline;
+}
+.date {
+        font-style: italic;
+        text-decoration: underline;
+        font-size: 66%;
+}
+.i {
+        font-style: italic;
+        font-family: "Cambria"
+                     "Times New Roman"
+                     "Bitstream Vera Serif"
+                     serif;
+}
+.t {
+        font-style: italic;
+}
+.tag {
+        color: #339933;
+}
+.att {
+        color: #333399;
+}
+.key {
+        color: #009999;
+}
+.h {
+        color: #000;
+        margin: 0px;
+}
+.c {
+        color: #C39;
+        margin: 0px;
+}
+.m {
+        color: #963;
+        margin: 0px;
+	font-family: "Comic Sans MS";
+}
+.cz {
+        color: #C39;
+        margin: 0px;
+	font-family: "Candara";
+        margin-right: -10px;
+}
+.z {
+        margin: 0px;
+        margin-left: -10px;
+	font-family: "Candara"
+}
+.x {
+        color: #C00;
+        margin: 0px;
+}
+.xs {
+        color: #633;
+        margin: 0px;
+        text-decoration: line-through;
+}
+.ci {
+        color: #C39;
+        margin: 0px;
+        font-style: italic;
+        font-family: "Constantia"
+                     "Times New Roman"
+                     "Bitstream Vera Serif"
+                     serif;
+}
+.cu {
+        color: #C39;
+        margin: 0px;
+        text-decoration: underline;
+}
+.ct {
+        color: #C39;
+        margin: 0px;
+        font-style: italic;
+}
+.hs {
+        color: #f33;
+        margin: 0px;
+        text-decoration: line-through;
+}
+.ht {
+        color: #aaa;
+        font-style: italic;
+}
+.pre {
+        font-family: "Consolas"
+                     "Anonymous"
+		     "Andale Mono"
+                     "Bitstream Vera Sans Mono"
+                     monospace;
+        padding-bottom: 8px;
+}
+#canvas[rendering="true"] image {
+	display: none;
+}
+#canvas[rendering="true"] *,
+#canvas[rendering="true"] .text-link {
+	color: white !important;
+}
+
+
+tabbox, tabpanels, tabpanel {
+	margin: 0;
+	padding: 0;
+}
+
+
+
+
+#canvas[eva="true"] {
+	background: white !important;
+	color: black !important;
+	font-family:
+                "Georgia"
+                "DejaVu Serif Condensed"
+		"Apple LiGothic"
+		"Arial Black"
+		serif !important;
+}
+#canvas[eva="true"] .link-text {
+	color: red !important;
+	text-decoration: none !important;
+}
+#canvas[eva="true"] .link-text:hover {
+	color: pink !important;
+}
+#canvas[eva="true"] .link-text:active {
+	color: orange !important;
+}
+#canvas[rendering="true"] *,
+#canvas[rendering="true"] .text-link {
+	color: black !important;
+}
+
+
+
+
+#canvasToolbar {
+	position: relative;
+}
+

Added: jifty/branches/schema-plugins/doc/talks/halo-overview.png
==============================================================================
Binary file. No diff available.

Added: jifty/branches/schema-plugins/doc/talks/halo.png
==============================================================================
Binary file. No diff available.

Added: jifty/branches/schema-plugins/doc/talks/lpw_intro_jifty_2006.key.tgz
==============================================================================
Binary file. No diff available.

Added: jifty/branches/schema-plugins/doc/talks/lpw_intro_jifty_2006.pdf
==============================================================================
Binary file. No diff available.

Added: jifty/branches/schema-plugins/doc/talks/lpw_scary_jifty.key.tgz
==============================================================================
Binary file. No diff available.

Added: jifty/branches/schema-plugins/doc/talks/lpw_scary_jifty.pdf
==============================================================================
Binary file. No diff available.

Added: jifty/branches/schema-plugins/doc/talks/new-entry.png
==============================================================================
Binary file. No diff available.

Added: jifty/branches/schema-plugins/doc/talks/npw.2006.xul
==============================================================================
Binary file. No diff available.

Added: jifty/branches/schema-plugins/doc/talks/npw.2006/Blog/Makefile.PL
==============================================================================
--- (empty file)
+++ jifty/branches/schema-plugins/doc/talks/npw.2006/Blog/Makefile.PL	Mon Jan 29 21:05:02 2007
@@ -0,0 +1,6 @@
+use inc::Module::Install;
+name('Blog');
+version('0.01');
+requires('Jifty' => '0.60507');
+requires('Regexp::Common::profanity_us' => '0'); 
+WriteAll;

Added: jifty/branches/schema-plugins/doc/talks/npw.2006/Blog/bin/jifty
==============================================================================
--- (empty file)
+++ jifty/branches/schema-plugins/doc/talks/npw.2006/Blog/bin/jifty	Mon Jan 29 21:05:02 2007
@@ -0,0 +1,18 @@
+#!/opt/local/bin/perl
+
+eval 'exec /opt/local/bin/perl  -S $0 ${1+"$@"}'
+    if 0; # not running under some shell
+use warnings;
+use strict;
+use File::Basename qw(dirname); 
+use UNIVERSAL::require;
+
+BEGIN {
+    Jifty::Util->require or die $UNIVERSAL::require::ERROR;
+    my $root = Jifty::Util->app_root;
+    unshift @INC, "$root/lib" if ($root);
+}
+
+use Jifty::Script;
+$SIG{INT} = $SIG{TERM} = sub { warn "Stopped\n"; exit; };
+Jifty::Script->dispatch();

Added: jifty/branches/schema-plugins/doc/talks/npw.2006/Blog/etc/config.yml
==============================================================================
--- (empty file)
+++ jifty/branches/schema-plugins/doc/talks/npw.2006/Blog/etc/config.yml	Mon Jan 29 21:05:02 2007
@@ -0,0 +1,36 @@
+--- 
+framework: 
+  AdminMode: 1
+  ApplicationClass: Blog
+  ApplicationName: Blog
+  Database: 
+    Database: blog
+    Driver: SQLite
+    Host: localhost
+    Password: ''
+    RecordBaseClass: Jifty::DBI::Record::Cachable
+    User: ''
+    Version: 0.0.2
+  DevelMode: 1
+  L10N: 
+    PoDir: share/po
+  LogLevel: INFO
+  Mailer: Sendmail
+  MailerArgs: []
+
+  Plugins: []
+
+  Web: 
+    BaseURL: http://localhost
+    DataDir: var/mason
+    Globals: []
+
+    MasonConfig: 
+      autoflush: 0
+      default_escape_flags: h
+      error_format: text
+      error_mode: fatal
+    Port: 8888
+    ServeStaticFiles: 1
+    StaticRoot: share/web/static
+    TemplateRoot: share/web/templates

Added: jifty/branches/schema-plugins/doc/talks/npw.2006/Blog/lib/Blog/Dispatcher.pm
==============================================================================
--- (empty file)
+++ jifty/branches/schema-plugins/doc/talks/npw.2006/Blog/lib/Blog/Dispatcher.pm	Mon Jan 29 21:05:02 2007
@@ -0,0 +1,23 @@
+ package Blog::Dispatcher;
+ use Jifty::Dispatcher -base;
+
+ before '*' => run {
+    my $top = Jifty->web->navigation;
+    $top->child('List Entries' => url => '/');
+    $top->child('New Entry'    => url => '/new_entry');
+ }
+ on '/' => run {
+     my $entries =
+        Blog::Model::EntryCollection->new();
+     $entries->unlimit();
+
+     set entries => $entries;
+ };
+ on '/new_entry' => run {
+     set create => Jifty->web->new_action(
+         class => 'CreateEntry',
+         moniker => 'new_entry',
+     );
+ };
+
+1;

Added: jifty/branches/schema-plugins/doc/talks/npw.2006/Blog/lib/Blog/Model/Entry.pm
==============================================================================
--- (empty file)
+++ jifty/branches/schema-plugins/doc/talks/npw.2006/Blog/lib/Blog/Model/Entry.pm	Mon Jan 29 21:05:02 2007
@@ -0,0 +1,42 @@
+use strict;
+use warnings;
+
+package Blog::Model::Entry::Schema;
+use Jifty::DBI::Schema;
+
+# Your column definitions go here.  See L<Jifty::DBI::Schema> for
+# documentation about how to write column definitions.
+
+column
+    title => type is 'text',
+    default is 'Untitled';
+
+column
+    body => type is 'text',
+    render_as 'Textarea';
+
+package Blog::Model::Entry;
+use base qw/Blog::Record/;
+
+# Your model-specific methods go here.
+
+use Regexp::Common 'profanity_us';
+
+sub canonicalize_body {
+    my $self = shift;
+    my $body = shift;
+    $body =~ s/$RE{profanity}/**expletives**/gi;
+    return $body;
+}
+
+sub validate_body {
+    my $self = shift;
+    my $body = shift;
+    if ( $body =~ /$RE{profanity}/i ) {
+        return ( 0,
+            'Would you speak like that in front of your mother? *cough*' );
+    }
+    return ( 1, "OK" );
+}
+
+1;

Added: jifty/branches/schema-plugins/doc/talks/npw.2006/Blog/share/web/templates/index.html
==============================================================================
--- (empty file)
+++ jifty/branches/schema-plugins/doc/talks/npw.2006/Blog/share/web/templates/index.html	Mon Jan 29 21:05:02 2007
@@ -0,0 +1,12 @@
+<%ARGS>
+$entries # From the dispatcher
+</%ARGS>
+<&|/_elements/wrapper&>
+% while (my $entry = $entries->next) {
+  <h2><% $entry->title %></h2>
+  <div class="body">
+    <% $entry->body %>
+  </div>
+% }
+</&>
+

Added: jifty/branches/schema-plugins/doc/talks/npw.2006/Blog/share/web/templates/new_entry
==============================================================================
--- (empty file)
+++ jifty/branches/schema-plugins/doc/talks/npw.2006/Blog/share/web/templates/new_entry	Mon Jan 29 21:05:02 2007
@@ -0,0 +1,13 @@
+<%ARGS>
+$create # From the dispatcher
+</%ARGS>
+<&|/_elements/wrapper,
+   title => 'Create an article' &>
+<% Jifty->web->form->start %> 
+% foreach my $arg ($create->argument_names) {
+<% $create->form_field($arg) %>
+% }
+<% Jifty->web->form->submit( label => 'Save' ) %>
+<% Jifty->web->form->end %>
+</&>
+

Added: jifty/branches/schema-plugins/doc/talks/npw.2006/Blog/t/00-model-Entry.t
==============================================================================
--- (empty file)
+++ jifty/branches/schema-plugins/doc/talks/npw.2006/Blog/t/00-model-Entry.t	Mon Jan 29 21:05:02 2007
@@ -0,0 +1,49 @@
+#!/usr/bin/env perl
+use warnings;
+use strict;
+
+=head1 DESCRIPTION
+
+A basic test harness for the Entry model.
+
+=cut
+
+use Jifty::Test tests => 11;
+
+# Make sure we can load the model
+use_ok('Blog::Model::Entry');
+
+# Grab a system use
+my $system_user = Blog::CurrentUser->superuser;
+ok($system_user, "Found a system user");
+
+# Try testing a create
+my $o = Blog::Model::Entry->new(current_user => $system_user);
+my ($id) = $o->create();
+ok($id, "Entry create returned success");
+ok($o->id, "New Entry has valid id set");
+is($o->id, $id, "Create returned the right id");
+
+# And another
+$o->create();
+ok($o->id, "Entry create returned another value");
+isnt($o->id, $id, "And it is different from the previous one");
+
+# Searches in general
+my $collection =  Blog::Model::EntryCollection->new(current_user => $system_user);
+$collection->unlimit;
+is($collection->count, 2, "Finds two records");
+
+# Searches in specific
+$collection->limit(column => 'id', value => $o->id);
+is($collection->count, 1, "Finds one record with specific id");
+
+# Delete one of them
+$o->delete;
+$collection->redo_search;
+is($collection->count, 0, "Deleted row is gone");
+
+# And the other one is still there
+$collection->unlimit;
+is($collection->count, 1, "Still one left");
+

Added: jifty/branches/schema-plugins/doc/talks/npw.2006/blog.png
==============================================================================
Binary file. No diff available.

Added: jifty/branches/schema-plugins/doc/talks/npw.2006/canonicalize_entry.png
==============================================================================
Binary file. No diff available.

Added: jifty/branches/schema-plugins/doc/talks/npw.2006/halo.png
==============================================================================
Binary file. No diff available.

Added: jifty/branches/schema-plugins/doc/talks/npw.2006/halo2.png
==============================================================================
Binary file. No diff available.

Added: jifty/branches/schema-plugins/doc/talks/npw.2006/hello.png
==============================================================================
Binary file. No diff available.

Added: jifty/branches/schema-plugins/doc/talks/npw.2006/hello_jesse.png
==============================================================================
Binary file. No diff available.

Added: jifty/branches/schema-plugins/doc/talks/npw.2006/jifty_3_files.png
==============================================================================
Binary file. No diff available.

Added: jifty/branches/schema-plugins/doc/talks/npw.2006/jifty_app.png
==============================================================================
Binary file. No diff available.

Added: jifty/branches/schema-plugins/doc/talks/npw.2006/jifty_edit_model.png
==============================================================================
Binary file. No diff available.

Added: jifty/branches/schema-plugins/doc/talks/npw.2006/jifty_model.png
==============================================================================
Binary file. No diff available.

Added: jifty/branches/schema-plugins/doc/talks/npw.2006/jifty_schema_setup.png
==============================================================================
Binary file. No diff available.

Added: jifty/branches/schema-plugins/doc/talks/npw.2006/jifty_server.png
==============================================================================
Binary file. No diff available.

Added: jifty/branches/schema-plugins/doc/talks/npw.2006/jifty_web_1.png
==============================================================================
Binary file. No diff available.

Added: jifty/branches/schema-plugins/doc/talks/npw.2006/jifty_web_crud.png
==============================================================================
Binary file. No diff available.

Added: jifty/branches/schema-plugins/doc/talks/npw.2006/jifty_web_crud_create_2.png
==============================================================================
Binary file. No diff available.

Added: jifty/branches/schema-plugins/doc/talks/npw.2006/jifty_web_crud_edit.png
==============================================================================
Binary file. No diff available.

Added: jifty/branches/schema-plugins/doc/talks/npw.2006/jifty_web_crud_edited.png
==============================================================================
Binary file. No diff available.

Added: jifty/branches/schema-plugins/doc/talks/npw.2006/jifty_web_crud_new.png
==============================================================================
Binary file. No diff available.

Added: jifty/branches/schema-plugins/doc/talks/npw.2006/jifty_web_dbadmin.png
==============================================================================
Binary file. No diff available.

Added: jifty/branches/schema-plugins/doc/talks/npw.2006/makefile_pl.png
==============================================================================
Binary file. No diff available.

Added: jifty/branches/schema-plugins/doc/talks/npw.2006/new_entry.png
==============================================================================
Binary file. No diff available.

Added: jifty/branches/schema-plugins/doc/talks/npw.2006/online_docs.png
==============================================================================
Binary file. No diff available.

Added: jifty/branches/schema-plugins/doc/talks/npw.2006/tests.png
==============================================================================
Binary file. No diff available.

Added: jifty/branches/schema-plugins/doc/talks/npw.2006/validate_entry.png
==============================================================================
Binary file. No diff available.

Added: jifty/branches/schema-plugins/doc/talks/npw2005.xul
==============================================================================
Binary file. No diff available.

Added: jifty/branches/schema-plugins/doc/talks/oscon-europe.2006.xul
==============================================================================
Binary file. No diff available.

Added: jifty/branches/schema-plugins/doc/talks/oscon.2006.xul
==============================================================================
Binary file. No diff available.

Added: jifty/branches/schema-plugins/doc/talks/pony.jpg
==============================================================================
Binary file. No diff available.

Added: jifty/branches/schema-plugins/doc/talks/pony.png
==============================================================================
Binary file. No diff available.

Added: jifty/branches/schema-plugins/doc/talks/takahashi.css
==============================================================================
--- (empty file)
+++ jifty/branches/schema-plugins/doc/talks/takahashi.css	Mon Jan 29 21:05:02 2007
@@ -0,0 +1,184 @@
+ at charset "UTF-8";
+
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Takahashi-Method-based Presentation Tool in XUL.
+ *
+ * The Initial Developer of the Original Code is SHIMODA Hiroshi.
+ * Portions created by the Initial Developer are Copyright (C) 2005
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s): SHIMODA Hiroshi <piro at p.club.ne.jp>
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#canvas {
+    /*
+	background: black !important;
+	color: white !important;
+        */
+        font-weight: bold;
+	font-family:
+                "Candara"
+                "Georgia"
+                "DejaVu Serif Condensed"
+                "Arial"
+		"Bitstream Vera Sans"
+		"Verdana"
+		"Apple LiGothic"
+		"Arial Black"
+                "Bitstream Vera Sans"
+		sans-serif !important;
+}
+#canvas * {
+	cursor: pointer !important;
+}
+#canvas image {
+	width: auto;
+	height: auto;
+}
+.link-text {
+	color: #99CCFF !important;
+	text-decoration: none !important;
+}
+.link-text:hover {
+	color: #CCEEFF !important;
+/*        border-bottom: dotted 1px; */
+}
+.link-text:active {
+	color: white !important;
+}
+.s {
+        text-decoration: line-through;
+}
+.iu {
+        text-decoration: underline;
+        font-style: italic;
+}
+.ui {
+/*      text-decoration: underline; */
+        font-style: italic;
+}
+.u {
+        text-decoration: underline;
+}
+.i {
+        font-style: italic;
+        font-family: "Times New Roman"
+                     "Bitstream Vera Serif"
+                     serif;
+}
+.c {
+        font-family: "Anonymous"
+		     "Lucida Console"
+		     "Andale Mono"
+                     "Bitstream Vera Sans Mono"
+                     monospace;
+}
+.t {
+        font-style: italic;
+}
+
+.h {
+        color: #ff0000;
+}
+
+.tag {
+        color: #33f;
+}
+.warn {
+        color: #f00;
+}
+.att {
+        color: #9999cc;
+}
+.key {
+        color: #00ffff;
+}
+.hid {
+        color: #999999;
+}
+.hidt {
+        color: #999999;
+        font-style: italic;
+}
+.pre {
+        font-family: "Anonymous"
+		     "Lucida Console"
+		     "Andale Mono"
+                     "Bitstream Vera Sans Mono"
+                     monospace;
+        padding-bottom: 8px;
+}
+#canvas[rendering="true"] image {
+	display: none;
+}
+#canvas[rendering="true"] *,
+#canvas[rendering="true"] .text-link {
+	color: white !important;
+}
+
+
+tabbox, tabpanels, tabpanel {
+	margin: 0;
+	padding: 0;
+}
+
+
+
+
+#canvas[eva="true"] {
+	background: white !important;
+	color: black !important;
+	font-family:
+                "Georgia"
+                "DejaVu Serif Condensed"
+		"Apple LiGothic"
+		"Arial Black"
+		serif !important;
+}
+#canvas[eva="true"] .link-text {
+	color: red !important;
+	text-decoration: none !important;
+}
+#canvas[eva="true"] .link-text:hover {
+	color: pink !important;
+}
+#canvas[eva="true"] .link-text:active {
+	color: orange !important;
+}
+#canvas[rendering="true"] *,
+#canvas[rendering="true"] .text-link {
+	color: black !important;
+}
+
+
+
+
+#canvasToolbar {
+	position: relative;
+}
+
+.subtitle {
+	display: none;
+    font-family: "Kochi Gothic";
+    color: yellow;
+    text-align: center;
+    font-size: 40px;
+    background: black;
+    bottom: 10;
+    padding-bottom: 10px;
+    padding-top: 10px;
+    spacing: 10px;
+}

Added: jifty/branches/schema-plugins/doc/talks/takahashi.js
==============================================================================
--- (empty file)
+++ jifty/branches/schema-plugins/doc/talks/takahashi.js	Mon Jan 29 21:05:02 2007
@@ -0,0 +1,525 @@
+var Presentation = {
+    init : function(option){
+        this.size = 9;
+
+        this._offset  = 0;
+        this.canvas   = document.getElementById('canvas');
+        this.content  = document.getElementById('content');
+        this.textbox  = document.getElementById('textField');
+        this.deck     = document.getElementById('deck');
+        this.scroller = document.getElementById('scroller');
+
+               this.canvas.appendChild(document.createElement('description'));
+               this.canvas.lastChild.setAttribute('id', "caption");
+               this.canvas.lastChild.setAttribute('class', 'subtitle');
+        this.toolbar         = document.getElementById('canvasToolbar');
+        this.toolbarHeight   = this.toolbar.boxObject.height;
+        this.isToolbarHidden = true;
+        this.toolbar.setAttribute('style', 'margin-top:'+(0-this.toolbarHeight)+'px;margin-bottom:0px;');
+
+        if(option){
+            for(var i in option){this[i] = option[i]}
+        }
+
+        if (this.readParameter()) {
+            this.takahashi();
+        }
+
+        document.documentElement.focus();
+    },
+
+    takahashi : function(){
+        if (!document.title)
+            document.title = this.data[0].replace(/[\r\n]/g, ' ');
+
+        if(!this.data[this.offset]){
+            this.offset = this.data.length-1;
+        }
+        document.getElementById("current_page").value = this.offset+1;
+        document.getElementById("max_page").value     = this.data.length;
+
+        this.scroller.setAttribute('maxpos', this.data.length-1);
+        this.scroller.setAttribute('curpos', this.offset);
+
+        var broadcaster = document.getElementById('canBack');
+        if (!this.offset)
+            broadcaster.setAttribute('disabled', true);
+        else
+            broadcaster.removeAttribute('disabled');
+
+        var broadcaster = document.getElementById('canForward');
+        if (this.offset == this.data.length-1)
+            broadcaster.setAttribute('disabled', true);
+        else
+            broadcaster.removeAttribute('disabled');
+
+        this.canvas.setAttribute('rendering', true);
+
+        var text = this.data[this.offset].
+                replace(/^[\r\n]+/g,"").replace(/[\r\n]+$/g,"").replace(/(\r\n|[\r\n])/g,"\n")
+                .split('\n');
+        var range = document.createRange();
+        range.selectNodeContents(this.content);
+        range.deleteContents();
+        range.detach();
+
+        var line;
+        var newLine;
+        var uri;
+        var image_width;
+        var image_total_width  = 0;
+        var image_height;
+        var image_total_height = 0;
+        var image_src;
+        var code_listing = 0;
+
+
+        var labelId = 0;
+
+        for (var i = 0; i < text.length; i++)
+        {
+            this.content.appendChild(document.createElement('hbox'));
+            this.content.lastChild.setAttribute('align', 'center');
+            this.content.lastChild.setAttribute('pack', 'center');
+
+            line = text[i];
+            image_width  = 0;
+            image_height = 0;
+            var subtitle = '';
+
+            if (line.match(/^~/)) {
+              subtitle = line.substring(1);
+              line = '';
+            }
+
+            if (line.match(/^#/)) {
+                continue;
+            }
+
+            if (line.match(/^\\#/)) {
+                line = line.substring(1);
+            }
+
+            if (line.match(/^ /)) {
+              code_listing = 1; 
+              this.content.lastChild.setAttribute('align', 'left');
+              this.content.lastChild.setAttribute('class', 'pre');
+              line = line.substring(1)
+            } 
+            while (line.match(/^([^\{]+)?(\{\{ima?ge? +src="([^"]+)" +width="([0-9]+)" +height="([0-9]+)"[^\}]*\}\}|\{\{(([^\|]+)?\||)([^\}]+)\}\})(.+)?/))
+            {
+                if (RegExp.$1) {
+                    this.content.lastChild.appendChild(document.createElement('description'));
+                    this.content.lastChild.lastChild.setAttribute('value', RegExp.$1);
+                }
+                newLine = line.substring((RegExp.$1+RegExp.$2).length);
+
+                // Images
+                if (/^([^\{]+)?\{\{ima?ge? +src="([^"]+)" +width="([0-9]+)" +height="([0-9]+)"[^\}]*\}\}/.test(line)) {
+                    this.content.lastChild.appendChild(document.createElement('image'));
+                    image_src = RegExp.$2;
+                    if (image_src.indexOf('http://') < 0 &&
+                        image_src.indexOf('https://') < 0)
+                        image_src = this.dataFolder+image_src;
+                    this.content.lastChild.lastChild.setAttribute('src', image_src);
+                    this.content.lastChild.lastChild.setAttribute('width', parseInt(RegExp.$3 || '0'));
+                    this.content.lastChild.lastChild.setAttribute('height', parseInt(RegExp.$4 || '0'));
+                    image_width  += parseInt(RegExp.$3 || '0');
+                    image_height = Math.max(image_height, parseInt(RegExp.$4 || '0'));
+                }
+
+                // Styles
+                // else if (/^([^\{]+)?\{\{#([^\|]+)\|([^\}]+)\}\}/.test(line)) {
+                else if (/^([^\{]+)?\{\{(#([^\|]+)?\|)([^\}]+)\}\}/.test(line)) {
+                    uri = RegExp.$4;
+                    this.content.lastChild.appendChild(document.createElement('description'));
+                    this.content.lastChild.lastChild.setAttribute('value', uri);
+                    this.content.lastChild.lastChild.setAttribute('class', RegExp.$3);
+                }
+
+                // Links
+                else if (/^([^\{]+)?\{\{(([^\|]+)?\||)([^\}]+)\}\}/.test(line)) {
+                    uri = RegExp.$4;
+                    if (uri.indexOf('://') < 0)
+                        uri = this.dataFolder+uri;
+                    this.content.lastChild.appendChild(document.createElement('description'));
+                    this.content.lastChild.lastChild.setAttribute('value', RegExp.$3 || RegExp.$4);
+                    this.content.lastChild.lastChild.setAttribute('href', uri);
+                    this.content.lastChild.lastChild.setAttribute('tooltiptext', uri);
+                    this.content.lastChild.lastChild.setAttribute('statustext', uri);
+                    this.content.lastChild.lastChild.setAttribute('class', 'link-text');
+                }
+
+                line = newLine;
+            }
+
+            if (line) {
+                this.content.lastChild.appendChild(document.createElement('description'));
+                this.content.lastChild.lastChild.setAttribute('value', line);
+            }
+
+            image_total_width = Math.max(image_total_width, image_width);
+            image_total_height += image_height;
+        }
+
+        this.content.setAttribute('style', 'font-size:10px;');
+          caption =  document.getElementById('caption');
+        if (subtitle) {
+               caption.setAttribute('value', subtitle);
+        } else {
+               caption.setAttribute('value', '');
+
+        }
+
+        if (this.content.boxObject.width) {
+            var canvas_w  = this.canvas.boxObject.width;
+            var canvas_h  = this.canvas.boxObject.height-image_total_height;
+
+            var content_w = this.content.boxObject.width;
+            var new_fs = Math.round((canvas_w/content_w) * this.size);
+
+            if (new_fs > 32) {
+                new_fs = new_fs - (new_fs % 32) 
+            }
+            //if (code_listing) { new_fs = 48;}
+
+            this.content.setAttribute('style', 'top: 0');
+            this.content.setAttribute('style', 'font-size:'+ new_fs + "px");
+
+            if (this.content.boxObject.width < image_total_width) {
+                content_w = image_total_width;
+                new_fs = Math.round((canvas_w/content_w) * this.size);
+                this.content.setAttribute('style', 'font-size:'+ new_fs + "px");
+            }
+
+            var content_h = this.content.boxObject.height;
+            if(content_h >= (canvas_h - 70)){ // That 50 is space for subtitles
+                new_fs = Math.round(((canvas_h-70)/content_h) * new_fs);
+                this.content.setAttribute('style', 'font-size:'+ new_fs + "px");
+                content_h = this.content.boxObject.height;
+            }
+        }
+        this.canvas.removeAttribute('rendering');
+    },
+
+    reload : function() {
+        if (this.dataPath != location.href) {
+            var path = this.dataPath;
+            if (location.href.match(/^https?:/)) {
+                var request = new XMLHttpRequest();
+                request.open('GET', path);
+                request.onload = function() {
+                    Presentation.textbox.value = request.responseText;
+                    Presentation.data = Presentation.textbox.value.split('----');
+
+                    Presentation.takahashi();
+
+                    path = null;
+                    request = null;
+                };
+                request.send(null);
+            }
+            else {
+                document.getElementById('dataLoader').setAttribute('src', 'about:blank');
+                window.setTimeout(function() {
+                    document.getElementById('dataLoader').setAttribute('src', path);
+                    path = null;
+                }, 10);
+            }
+        }
+        else
+            window.location.reload();
+    },
+
+    forward : function(){
+        this.offset++;
+        this.takahashi();
+    },
+    back : function(){
+        this.offset--;
+        if(this.offset < 0){this.offset = 0}
+        this.takahashi();
+    },
+    home : function(){
+        this.offset = 0;
+        this.takahashi();
+    },
+    end : function(){
+        this.offset = this.data.length-1;
+        this.takahashi();
+    },
+    showPage : function(aPageOffset){
+        this.offset = aPageOffset ? aPageOffset : 0 ;
+        this.takahashi();
+    },
+
+    addPage : function() {
+        if (this.textbox.value &&
+            !this.textbox.value.match(/(\r\n|[\r\n])$/))
+            this.textbox.value += '\n';
+        this.textbox.value += '----\n';
+        this.onEdit();
+    },
+
+    toggleEditMode : function(){
+        this.deck.selectedIndex = (this.deck.selectedIndex == 0) ? 1 : 0 ;
+    },
+    toggleEvaMode : function(){
+        var check = document.getElementById('toggleEva');
+        if (this.canvas.getAttribute('eva') == 'true') {
+            this.canvas.removeAttribute('eva');
+            check.checked = false;
+        }
+        else {
+            this.canvas.setAttribute('eva', true);
+            check.checked = true;
+        }
+    },
+
+    onPresentationClick : function(aEvent){
+        if (!this.isToolbarHidden)
+            this.showHideToolbar();
+
+        switch(aEvent.button)
+        {
+            case 0:
+                var uri = aEvent.target.getAttribute('href');
+                if (uri)
+                    window.open(uri);
+                else {
+                    this.forward();
+                    document.documentElement.focus();
+                }
+                break;
+            case 2:
+                this.back();
+                document.documentElement.focus();
+                break;
+            default:
+                break;
+        }
+    },
+    onScrollerDragStart : function(){
+        this.scroller.dragging = true;
+    },
+    onScrollerDragMove : function(){
+        if (this.scroller.dragging)
+            this.showPage(parseInt(this.scroller.getAttribute('curpos')));
+    },
+    onScrollerDragDrop : function(){
+        if (this.scroller.dragging) {
+            this.showPage(parseInt(this.scroller.getAttribute('curpos')));
+        }
+         this.scroller.dragging = false;
+    },
+    onEdit : function() {
+        this.data = this.textbox.value.split('----');
+        this.takahashi();
+    },
+
+    onKeyPress : function(aEvent) {
+        switch(aEvent.keyCode)
+        {
+            case aEvent.DOM_VK_BACK_SPACE:
+                if (this.isPresentationMode) {
+                    aEvent.preventBubble();
+                    aEvent.preventDefault();
+                    Presentation.back();
+                }
+                break;
+            default:
+                break;
+        }
+    },
+
+
+    onToolbarArea   : false,
+    toolbarHeight   : 0,
+    toolbarDelay    : 300,
+    toolbarTimer    : null,
+    isToolbarHidden : false,
+    onMouseMoveOnCanvas : function(aEvent) {
+        if (this.scroller.dragging) return;
+
+        this.onToolbarArea = (aEvent.clientY < this.toolbarHeight);
+
+        if (this.isToolbarHidden == this.onToolbarArea) {
+            if (this.toolbarTimer) window.clearTimeout(this.toolbarTimer);
+            this.toolbarTimer = window.setTimeout('Presentation.onMouseMoveOnCanvasCallback()', this.toolbarDelay);
+        }
+    },
+    onMouseMoveOnCanvasCallback : function() {
+        if (this.isToolbarHidden == this.onToolbarArea)
+            this.showHideToolbar();
+    },
+
+    toolbarAnimationDelay : 100,
+    toolbarAnimationSteps : 5,
+    toolbarAnimationInfo  : null,
+    toolbarAnimationTimer : null,
+    showHideToolbar : function()
+    {
+        if (this.toolbarAnimationTimer) window.clearTimeout(this.toolbarAnimationTimer);
+
+        this.toolbarAnimationInfo = { count : 0 };
+        if (this.isToolbarHidden) {
+            this.toolbarAnimationInfo.start = 0;
+            this.toolbarAnimationInfo.end   = this.toolbarHeight;
+        }
+        else {
+            this.toolbarAnimationInfo.start = this.toolbarHeight;
+            this.toolbarAnimationInfo.end   = 0;
+        }
+        this.toolbarAnimationInfo.current = 0;
+
+        this.toolbar.setAttribute('style', 'margin-top:'+(0-(this.toolbarHeight-this.toolbarAnimationInfo.start))+'px; margin-bottom:'+(0-this.toolbarAnimationInfo.start)+'px;');
+
+        this.toolbarAnimationTimer = window.setTimeout('Presentation.animateToolbar()', this.toolbarAnimationDelay/this.toolbarAnimationSteps);
+    },
+    animateToolbar : function()
+    {
+        this.toolbarAnimationInfo.current += parseInt(this.toolbarHeight/this.toolbarAnimationSteps);
+
+        var top, bottom;
+        if (this.toolbarAnimationInfo.start < this.toolbarAnimationInfo.end) {
+            top    = this.toolbarHeight-this.toolbarAnimationInfo.current;
+            bottom = this.toolbarAnimationInfo.current;
+        }
+        else {
+            top    = this.toolbarAnimationInfo.current;
+            bottom = this.toolbarHeight-this.toolbarAnimationInfo.current;
+        }
+
+        top    = Math.min(Math.max(top, 0), this.toolbarHeight);
+        bottom = Math.min(Math.max(bottom, 0), this.toolbarHeight);
+
+        this.toolbar.setAttribute('style', 'margin-top:'+(0-top)+'px; margin-bottom:'+(0-bottom)+'px');
+
+        if (this.toolbarAnimationInfo.count < this.toolbarAnimationSteps) {
+            this.toolbarAnimationInfo.count++;
+            this.toolbarAnimationTimer = window.setTimeout('Presentation.animateToolbar()', this.toolbarAnimationDelay/this.toolbarAnimationSteps);
+        }
+        else
+            this.isToolbarHidden = !this.isToolbarHidden;
+    },
+
+
+
+    get offset(){
+        return this._offset;
+    },
+    set offset(aValue){
+        this._offset = parseInt(aValue || 0);
+        document.documentElement.setAttribute('lastoffset', this.offset);
+        return this.offset;
+    },
+
+    get data(){
+        if (!this._data) {
+             // Make sure you break the text into parts smaller than 4096
+             // characters, and name them as indicated. Tweak as required.
+             // (What a hack. A JS programmer should find a better way.)
+             // Luc St-Louis, and email is lucs at pobox.com.
+
+                 nodes = document.getElementById('builtinCode').childNodes;
+                 content = '';
+                for (i in nodes) {
+                    if (nodes[i].nodeValue) {
+                    content = content + nodes[i].nodeValue;
+                    }
+                }
+    
+               this._data = content.split(/^----/m);
+        }
+
+        return this._data;
+    },
+    set data(aValue){
+        this._data = aValue;
+        return aValue;
+    },
+
+
+    get isPresentationMode(){
+        return (this.deck.selectedIndex == 0);
+    },
+
+
+    get dataPath(){
+        if (!this._dataPath)
+            this.dataPath = location.href;
+        return this._dataPath;
+    },
+    set dataPath(aValue){
+        var oldDataPath = this._dataPath;
+        this._dataPath = aValue;
+        if (oldDataPath != aValue) {
+            this._dataFolder = this._dataPath.split('?')[0].replace(/[^\/]+$/, '');
+        }
+        return this._dataPath;
+    },
+
+    get dataFolder(){
+        if (!this._dataFolder)
+            this.dataPath = this.dataPath;
+        return this._dataFolder;
+    },
+    set dataFolder(aValue){
+        this._dataFolder = aValue;
+        return this._dataFolder;
+    },
+
+    readParameter : function() {
+        if (location.search) {
+            var param = location.search.replace(/^\?/, '');
+
+            if (param.match(/page=([0-9]+)/i))
+                this.offset = parseInt(RegExp.$1)-1;
+
+            if (param.match(/edit=(1|true|yes)/i))
+                this.toggleEditMode();
+
+            if (param.match(/eva=(1|true|yes)/i))
+                this.toggleEvaMode();
+
+            if (param.match(/data=([^&;]+)/i)) {
+                var path = unescape(RegExp.$1);
+                this.dataPath = path;
+                if (location.href.match(/^https?:/)) {
+                    var request = new XMLHttpRequest();
+                    request.open('GET', path);
+                    request.onload = function() {
+                        Presentation.textbox.value = request.responseText;
+                        Presentation.data = Presentation.textbox.value.split('----');
+
+                        Presentation.takahashi();
+                    };
+                    request.send(null);
+                }
+                else {
+                    document.getElementById('dataLoader').setAttribute('src', path);
+                }
+                return false;
+            }
+        }
+        return true;
+    },
+    onDataLoad : function() {
+        if (!window.frames[0].document.body.hasChildNodes()) return;
+        var data = window.frames[0].document.body.firstChild.innerHTML;
+        if (!data) return;
+
+        this.textbox.value = data;
+        this.data = this.textbox.value.split('----');
+
+        this.takahashi();
+    }
+};
+
+function init()
+{
+    window.removeEventListener('load', init, false);
+
+    Presentation.init();
+}
+window.addEventListener('load', init, false);

Added: jifty/branches/schema-plugins/doc/talks/yapc.asia.2006.xul
==============================================================================
Binary file. No diff available.

Added: jifty/branches/schema-plugins/doc/talks/yapc.na.2006.xul
==============================================================================
Binary file. No diff available.

Added: jifty/branches/schema-plugins/etc/config.yml
==============================================================================
--- (empty file)
+++ jifty/branches/schema-plugins/etc/config.yml	Mon Jan 29 21:05:02 2007
@@ -0,0 +1,6 @@
+# This exists for the test files; they get all kinds of unhappy if the
+# application's name is 'Jifty', because of namespace issues.
+
+framework:
+  ApplicationName: JiftyApp
+  WhichConfigFile: main

Added: jifty/branches/schema-plugins/etc/site_config.yml
==============================================================================
--- (empty file)
+++ jifty/branches/schema-plugins/etc/site_config.yml	Mon Jan 29 21:05:02 2007
@@ -0,0 +1,2 @@
+framework:
+  WhichConfigFile: site

Added: jifty/branches/schema-plugins/examples/Chat/Makefile.PL
==============================================================================
--- (empty file)
+++ jifty/branches/schema-plugins/examples/Chat/Makefile.PL	Mon Jan 29 21:05:02 2007
@@ -0,0 +1,6 @@
+use inc::Module::Install;
+name('Clock');
+version('0.01');
+requires('Jifty' => '0.60912');
+
+WriteAll;

Added: jifty/branches/schema-plugins/examples/Chat/bin/jifty
==============================================================================
--- (empty file)
+++ jifty/branches/schema-plugins/examples/Chat/bin/jifty	Mon Jan 29 21:05:02 2007
@@ -0,0 +1,15 @@
+#!/usr/bin/env perl
+use warnings;
+use strict;
+use File::Basename qw(dirname); 
+use UNIVERSAL::require;
+
+BEGIN {
+    Jifty::Util->require or die $UNIVERSAL::require::ERROR;
+    my $root = Jifty::Util->app_root;
+    unshift @INC, "$root/lib" if ($root);
+}
+
+use Jifty::Script;
+$SIG{INT} = $SIG{TERM} = sub { warn "Stopped\n"; exit; };
+Jifty::Script->dispatch();

Added: jifty/branches/schema-plugins/examples/Chat/etc/config.yml
==============================================================================
--- (empty file)
+++ jifty/branches/schema-plugins/examples/Chat/etc/config.yml	Mon Jan 29 21:05:02 2007
@@ -0,0 +1,37 @@
+---
+framework:
+  AdminMode: 0
+  ApplicationClass: Chat
+  ApplicationName: Chat
+  PubSub:
+    Enable: 1
+  Database:
+    CheckSchema: 1
+    Database: chat
+    Driver: SQLite
+    Host: localhost
+    Password: ''
+    RecordBaseClass: Jifty::DBI::Record::Cachable
+    User: ''
+    Version: 0.0.1
+  DevelMode: 0
+  L10N:
+    PoDir: share/po
+  LogLevel: INFO
+  Mailer: Sendmail
+  MailerArgs: []
+  Plugins: []
+  Web:
+    BaseURL: http://localhost
+    DataDir: var/mason
+    Globals: []
+    MasonConfig:
+      autoflush: 0
+      default_escape_flags: h
+      error_format: text
+      error_mode: fatal
+    Port: 8888
+    ServeStaticFiles: 1
+    StaticRoot: share/web/static
+    TemplateRoot: share/web/templates
+    ServerClass: Chat::Server

Added: jifty/branches/schema-plugins/examples/Chat/lib/Chat/Action/Send.pm
==============================================================================
--- (empty file)
+++ jifty/branches/schema-plugins/examples/Chat/lib/Chat/Action/Send.pm	Mon Jan 29 21:05:02 2007
@@ -0,0 +1,18 @@
+package Chat::Action::Send;
+use warnings;
+use strict;
+
+use Jifty::Param::Schema;
+use Jifty::Action schema {
+    param message =>
+        label is 'Say something witty:';
+};
+
+sub take_action {
+    my $self = shift;
+    my $msg  = $self->argument_value('message');
+    $msg = "<$1\@${ENV{'REMOTE_ADDR'}}> $msg" if $ENV{HTTP_USER_AGENT} =~ /([^\W\d]+)[\W\d]*$/;
+    Chat::Event::Message->new( { message => $msg } )->publish;
+}
+
+1;

Added: jifty/branches/schema-plugins/examples/Chat/lib/Chat/Event/Message.pm
==============================================================================
--- (empty file)
+++ jifty/branches/schema-plugins/examples/Chat/lib/Chat/Event/Message.pm	Mon Jan 29 21:05:02 2007
@@ -0,0 +1,6 @@
+package Chat::Event::Message;
+use strict;
+use warnings;
+use base 'Chat::Event';
+
+1;

Added: jifty/branches/schema-plugins/examples/Chat/lib/Chat/Server.pm
==============================================================================
--- (empty file)
+++ jifty/branches/schema-plugins/examples/Chat/lib/Chat/Server.pm	Mon Jan 29 21:05:02 2007
@@ -0,0 +1,6 @@
+package Chat::Server;
+use base 'Jifty::Server';
+
+sub net_server { 'Net::Server::Fork' }
+
+1;

Added: jifty/branches/schema-plugins/examples/Chat/share/web/templates/fragments/message
==============================================================================
--- (empty file)
+++ jifty/branches/schema-plugins/examples/Chat/share/web/templates/fragments/message	Mon Jan 29 21:05:02 2007
@@ -0,0 +1 @@
+<div><% ${$ARGS{event}}->{message} %></div>

Added: jifty/branches/schema-plugins/examples/Chat/share/web/templates/fragments/sender
==============================================================================
--- (empty file)
+++ jifty/branches/schema-plugins/examples/Chat/share/web/templates/fragments/sender	Mon Jan 29 21:05:02 2007
@@ -0,0 +1,7 @@
+<%init>
+my $action = Jifty->web->new_action( class => 'Send' );
+</%init>
+<% Jifty->web->form->start %>
+<% $action->form_field('message', focus => 1) %>
+<% Jifty->web->form->submit(onclick => [ { submit => $action }, { refresh_self => 1 } ]) %>
+<% Jifty->web->form->end %>

Added: jifty/branches/schema-plugins/examples/Chat/share/web/templates/index.html
==============================================================================
--- (empty file)
+++ jifty/branches/schema-plugins/examples/Chat/share/web/templates/index.html	Mon Jan 29 21:05:02 2007
@@ -0,0 +1,12 @@
+<&| /_elements/wrapper, title => "Jifty chat server", subtitle => "" &>
+<% Jifty::Web::PageRegion->new( name => "message", path => '/__jifty/empty' )->render %>
+<% Jifty::Web::PageRegion->new( name => "sender", path => '/fragments/sender' )->render %>
+</&>
+<%init>
+Jifty->subs->add(
+    class       => 'Message',
+    mode        => 'Bottom',
+    region      => "message",
+    render_with => '/fragments/message',
+);
+</%init>

Added: jifty/branches/schema-plugins/examples/Chat/t/00compile.t
==============================================================================
--- (empty file)
+++ jifty/branches/schema-plugins/examples/Chat/t/00compile.t	Mon Jan 29 21:05:02 2007
@@ -0,0 +1,19 @@
+#!/usr/bin/perl -w
+
+use Test::More;
+
+use File::Find;
+
+my @modules;
+find sub {
+    return unless /\.pm$/;
+    push @modules, $File::Find::name;
+}, "lib";
+
+ at modules = map { s[^lib/][];  $_ =~ s[.pm$][];  $_ =~ s[/][::]g; $_ } @modules;
+
+plan tests => scalar @modules;
+
+for my $module (@modules) {
+    require_ok $module;
+}

Added: jifty/branches/schema-plugins/examples/Chat/t/01startup.t
==============================================================================
--- (empty file)
+++ jifty/branches/schema-plugins/examples/Chat/t/01startup.t	Mon Jan 29 21:05:02 2007
@@ -0,0 +1,13 @@
+#!/usr/bin/perl -w
+
+use Jifty::Test 'no_plan';
+use Jifty::Test::WWW::Mechanize;
+
+# Startup the server.
+my $server = Jifty::Test->make_server;
+isa_ok($server, 'Jifty::Server');
+
+my $URL = $server->started_ok;
+my $mech = Jifty::Test::WWW::Mechanize->new;
+
+$mech->get_ok("$URL", "got the front page");

Added: jifty/branches/schema-plugins/examples/Clock/Makefile.PL
==============================================================================
--- (empty file)
+++ jifty/branches/schema-plugins/examples/Clock/Makefile.PL	Mon Jan 29 21:05:02 2007
@@ -0,0 +1,6 @@
+use inc::Module::Install;
+name('Clock');
+version('0.01');
+requires('Jifty' => '0.60912');
+
+WriteAll;

Added: jifty/branches/schema-plugins/examples/Clock/bin/jifty
==============================================================================
--- (empty file)
+++ jifty/branches/schema-plugins/examples/Clock/bin/jifty	Mon Jan 29 21:05:02 2007
@@ -0,0 +1,15 @@
+#!/usr/bin/env perl
+use warnings;
+use strict;
+use File::Basename qw(dirname); 
+use UNIVERSAL::require;
+
+BEGIN {
+    Jifty::Util->require or die $UNIVERSAL::require::ERROR;
+    my $root = Jifty::Util->app_root;
+    unshift @INC, "$root/lib" if ($root);
+}
+
+use Jifty::Script;
+$SIG{INT} = $SIG{TERM} = sub { warn "Stopped\n"; exit; };
+Jifty::Script->dispatch();

Added: jifty/branches/schema-plugins/examples/Clock/clockserv.pl
==============================================================================
--- (empty file)
+++ jifty/branches/schema-plugins/examples/Clock/clockserv.pl	Mon Jan 29 21:05:02 2007
@@ -0,0 +1,21 @@
+use strict;
+use lib 'lib';
+use Time::HiRes qw( time sleep );
+use Jifty;
+
+BEGIN { Jifty->new };
+
+sub ping {
+    my ($class, $sub) = @_;
+    while (1) {
+        my $new_time = time;
+        warn "Time: $new_time\n";
+        Clock::Event::Tick->new($new_time)->publish;
+        sleep 0.5;
+    }
+    exit;
+}
+
+ping();
+
+1;

Added: jifty/branches/schema-plugins/examples/Clock/etc/config.yml
==============================================================================
--- (empty file)
+++ jifty/branches/schema-plugins/examples/Clock/etc/config.yml	Mon Jan 29 21:05:02 2007
@@ -0,0 +1,37 @@
+---
+framework:
+  AdminMode: 1
+  ApplicationClass: Clock
+  ApplicationName: Clock
+  PubSub:
+    Enable: TRUE
+  Database:
+    CheckSchema: 1
+    Database: clock
+    Driver: SQLite
+    Host: localhost
+    Password: ''
+    RecordBaseClass: Jifty::DBI::Record::Cachable
+    User: ''
+    Version: 0.0.1
+  DevelMode: 1
+  L10N:
+    PoDir: share/po
+  LogLevel: INFO
+  Mailer: Sendmail
+  MailerArgs: []
+  Plugins: []
+  Web:
+    BaseURL: http://localhost
+    DataDir: var/mason
+    Globals: []
+    MasonConfig:
+      autoflush: 0
+      default_escape_flags: h
+      error_format: text
+      error_mode: fatal
+    Port: 8888
+    ServeStaticFiles: 1
+    StaticRoot: share/web/static
+    TemplateRoot: share/web/templates
+    ServerClass: Clock::Server

Added: jifty/branches/schema-plugins/examples/Clock/lib/Clock/Event/Tick.pm
==============================================================================
--- (empty file)
+++ jifty/branches/schema-plugins/examples/Clock/lib/Clock/Event/Tick.pm	Mon Jan 29 21:05:02 2007
@@ -0,0 +1,15 @@
+package Clock::Event::Tick;
+use strict;
+use warnings;
+use base 'Clock::Event';
+
+sub match {
+    my $self    = shift;
+    my $query   = shift;
+    if (my $like = $query->{like}) {
+        return(index($$self, $like) >= 0);
+    }
+    return 1;
+}
+
+1;

Added: jifty/branches/schema-plugins/examples/Clock/lib/Clock/Server.pm
==============================================================================
--- (empty file)
+++ jifty/branches/schema-plugins/examples/Clock/lib/Clock/Server.pm	Mon Jan 29 21:05:02 2007
@@ -0,0 +1,6 @@
+package Clock::Server;
+use base 'Jifty::Server';
+
+sub net_server { 'Net::Server::Fork' }
+
+1;

Added: jifty/branches/schema-plugins/examples/Clock/share/web/templates/fragments/time
==============================================================================
--- (empty file)
+++ jifty/branches/schema-plugins/examples/Clock/share/web/templates/fragments/time	Mon Jan 29 21:05:02 2007
@@ -0,0 +1,4 @@
+<span><% $$event %></span>
+<%ARGS>
+$event
+</%ARGS>

Added: jifty/branches/schema-plugins/examples/Clock/share/web/templates/index.html
==============================================================================
--- (empty file)
+++ jifty/branches/schema-plugins/examples/Clock/share/web/templates/index.html	Mon Jan 29 21:05:02 2007
@@ -0,0 +1,36 @@
+<&| /_elements/wrapper, title => "Hi", subtitle => "Welcome" &>
+<table>
+<tr><td>
+Full: <% $region->render %>
+</td><td>
+Filtered: <% $region_filtered->render %>
+</td></tr>
+</table>
+</&>
+<%init>
+my $region = Jifty::Web::PageRegion->new(
+    name => "clock-time",
+    path => '/__jifty/empty',
+);
+my $region_filtered = Jifty::Web::PageRegion->new(
+    name => "clock-filtered",
+    path => '/__jifty/empty',
+);
+
+Jifty->subs->add(
+  # window_id   => 'random scope',
+    class       => 'Tick',
+    mode        => 'Replace',
+    region      => "clock-time",
+    render_with => '/fragments/time',
+);
+
+Jifty->subs->add(
+  # window_id   => 'random scope',
+    class       => 'Tick',
+    queries     => [{ like => '9' }],
+    mode        => 'Replace',
+    region      => "clock-filtered",
+    render_with => '/fragments/time',
+);
+</%init>

Added: jifty/branches/schema-plugins/examples/MyWeblog/Makefile.PL
==============================================================================
--- (empty file)
+++ jifty/branches/schema-plugins/examples/MyWeblog/Makefile.PL	Mon Jan 29 21:05:02 2007
@@ -0,0 +1,6 @@
+use inc::Module::Install;
+name('MyWeblog');
+version('0.01');
+requires('Jifty' => '0.61123_01');
+
+WriteAll;

Added: jifty/branches/schema-plugins/examples/MyWeblog/bin/jifty
==============================================================================
--- (empty file)
+++ jifty/branches/schema-plugins/examples/MyWeblog/bin/jifty	Mon Jan 29 21:05:02 2007
@@ -0,0 +1,15 @@
+#!/usr/bin/env perl
+use warnings;
+use strict;
+use File::Basename qw(dirname); 
+use UNIVERSAL::require;
+
+BEGIN {
+    Jifty::Util->require or die $UNIVERSAL::require::ERROR;
+    my $root = Jifty::Util->app_root;
+    unshift @INC, "$root/lib" if ($root);
+}
+
+use Jifty::Script;
+$SIG{INT} = $SIG{TERM} = sub { warn "Stopped\n"; exit; };
+Jifty::Script->dispatch();

Added: jifty/branches/schema-plugins/examples/MyWeblog/etc/config.yml
==============================================================================
--- (empty file)
+++ jifty/branches/schema-plugins/examples/MyWeblog/etc/config.yml	Mon Jan 29 21:05:02 2007
@@ -0,0 +1,41 @@
+--- 
+framework: 
+  AdminMode: 1
+  ApplicationClass: MyWeblog
+  ApplicationName: MyWeblog
+  Database: 
+    CheckSchema: 1
+    Database: myweblog
+    Driver: SQLite
+    Host: localhost
+    Password: ''
+    RecordBaseClass: Jifty::DBI::Record::Cachable
+    User: ''
+    Version: 0.0.3
+  DevelMode: 1
+  L10N: 
+    PoDir: share/po
+  LogLevel: INFO
+  Mailer: Sendmail
+  MailerArgs: []
+
+  Plugins:
+   - Login: {}
+
+  PubSub: 
+    Backend: Memcached
+    Enable: ~
+  Web: 
+    BaseURL: http://localhost
+    DataDir: var/mason
+    Globals: []
+
+    MasonConfig: 
+      autoflush: 0
+      default_escape_flags: h
+      error_format: text
+      error_mode: fatal
+    Port: 8888
+    ServeStaticFiles: 1
+    StaticRoot: share/web/static
+    TemplateRoot: share/web/templates

Added: jifty/branches/schema-plugins/examples/MyWeblog/lib/MyWeblog/Model/Post.pm
==============================================================================
--- (empty file)
+++ jifty/branches/schema-plugins/examples/MyWeblog/lib/MyWeblog/Model/Post.pm	Mon Jan 29 21:05:02 2007
@@ -0,0 +1,24 @@
+use strict;
+use warnings;
+
+package MyWeblog::Model::Post;
+use Jifty::DBI::Schema;
+
+use MyWeblog::Record schema {
+
+         column title =>
+               type is 'text',
+               label is 'Title',
+               default is 'Untitled post';
+
+         column body =>
+               type is 'text',
+               label is 'Content',
+               render_as 'Textarea';
+
+};
+
+# Your model-specific methods go here.
+
+1;
+

Added: jifty/branches/schema-plugins/examples/MyWeblog/share/web/templates/_elements/nav
==============================================================================
--- (empty file)
+++ jifty/branches/schema-plugins/examples/MyWeblog/share/web/templates/_elements/nav	Mon Jan 29 21:05:02 2007
@@ -0,0 +1,11 @@
+<%init>
+my $top = Jifty->web->navigation;
+$top->child( Home => url => "/", sort_order => 1);
+$top->child( Post => url => "/post", label => "Post Article");
+
+if (Jifty->config->framework('AdminMode') ) {
+    $top->child(Administration       => url => "/__jifty/admin/", sort_order => 998);
+    $top->child(OnlineDocs       => url => "/__jifty/online_docs/", label => 'Online docs',  sort_order => 999);
+ }
+return();
+</%init>

Added: jifty/branches/schema-plugins/examples/MyWeblog/share/web/templates/fragments/page_of_posts
==============================================================================
--- (empty file)
+++ jifty/branches/schema-plugins/examples/MyWeblog/share/web/templates/fragments/page_of_posts	Mon Jan 29 21:05:02 2007
@@ -0,0 +1,30 @@
+<%args>
+$page => 1
+</%args>
+<%init>
+my $posts = MyWeblog::Model::PostCollection->new();
+$posts->unlimit();
+$posts->set_page_info( current_page => $page,
+                       per_page     => 15
+                     );
+$m->out("No items found.") if ($posts->pager->total_entries == 0);
+
+</%init>
+% if ($posts->pager->last_page > 1) {
+   Page <% $page %> of <% $posts->pager->last_page %>
+% }
+<dl class="list">
+% while (my $post = $posts->next) {
+ <dt><% $post->title %></dt>
+ <dd><% $post->body %></dd>
+% }
+</dl>
+
+% if ($posts->pager->previous_page) {
+  <% Jifty->web->link( label => "Previous Page", onclick => { args => { page => $posts->pager->previous_page } 
+} ) %>
+% }
+% if ($posts->pager->next_page) {
+  <% Jifty->web->link( label => "Next Page", onclick => { args => { page => $posts->pager->next_page } } ) %>
+% }
+

Added: jifty/branches/schema-plugins/examples/MyWeblog/share/web/templates/index.html
==============================================================================
--- (empty file)
+++ jifty/branches/schema-plugins/examples/MyWeblog/share/web/templates/index.html	Mon Jan 29 21:05:02 2007
@@ -0,0 +1,10 @@
+<&| /_elements/wrapper, title => Jifty->config->framework('ApplicationName') &>
+  
+<% Jifty->web->region(name => "myweblog-posts",
+                      path => "/fragments/page_of_posts") %>
+</&>
+<%init>
+my $posts = MyWeblog::Model::PostCollection->new();
+$posts->unlimit();
+</%init>
+

Added: jifty/branches/schema-plugins/examples/MyWeblog/share/web/templates/post
==============================================================================
--- (empty file)
+++ jifty/branches/schema-plugins/examples/MyWeblog/share/web/templates/post	Mon Jan 29 21:05:02 2007
@@ -0,0 +1,13 @@
+<%init>
+my $action = Jifty->web->new_action(class => 'CreatePost');
+</%init>
+
+<&| /_elements/wrapper, title => "Post to your weblog" &>
+<% Jifty->web->form->start() %>
+<% Jifty->web->form->next_page( url => '/') %>
+<% $action->form_field('title') %>
+<% $action->form_field('body') %>
+<% Jifty->web->form->submit( label => 'Post' ) %>
+<% Jifty->web->form->end() %>
+</&>
+

Added: jifty/branches/schema-plugins/examples/MyWeblog/t/00-model-Post.t
==============================================================================
--- (empty file)
+++ jifty/branches/schema-plugins/examples/MyWeblog/t/00-model-Post.t	Mon Jan 29 21:05:02 2007
@@ -0,0 +1,49 @@
+#!/usr/bin/env perl
+use warnings;
+use strict;
+
+=head1 DESCRIPTION
+
+A basic test harness for the Post model.
+
+=cut
+
+use Jifty::Test tests => 11;
+
+# Make sure we can load the model
+use_ok('MyWeblog::Model::Post');
+
+# Grab a system user
+my $system_user = MyWeblog::CurrentUser->superuser;
+ok($system_user, "Found a system user");
+
+# Try testing a create
+my $o = MyWeblog::Model::Post->new(current_user => $system_user);
+my ($id) = $o->create();
+ok($id, "Post create returned success");
+ok($o->id, "New Post has valid id set");
+is($o->id, $id, "Create returned the right id");
+
+# And another
+$o->create();
+ok($o->id, "Post create returned another value");
+isnt($o->id, $id, "And it is different from the previous one");
+
+# Searches in general
+my $collection =  MyWeblog::Model::PostCollection->new(current_user => $system_user);
+$collection->unlimit;
+is($collection->count, 2, "Finds two records");
+
+# Searches in specific
+$collection->limit(column => 'id', value => $o->id);
+is($collection->count, 1, "Finds one record with specific id");
+
+# Delete one of them
+$o->delete;
+$collection->redo_search;
+is($collection->count, 0, "Deleted row is gone");
+
+# And the other one is still there
+$collection->unlimit;
+is($collection->count, 1, "Still one left");
+

Added: jifty/branches/schema-plugins/examples/Ping/Makefile.PL
==============================================================================
--- (empty file)
+++ jifty/branches/schema-plugins/examples/Ping/Makefile.PL	Mon Jan 29 21:05:02 2007
@@ -0,0 +1,7 @@
+use inc::Module::Install;
+name('Ping');
+version('0.01');
+requires('Jifty' => '0.61025');
+requires('Net::Server' => 0);
+
+WriteAll;

Added: jifty/branches/schema-plugins/examples/Ping/bin/jifty
==============================================================================
--- (empty file)
+++ jifty/branches/schema-plugins/examples/Ping/bin/jifty	Mon Jan 29 21:05:02 2007
@@ -0,0 +1,15 @@
+#!/usr/bin/env perl
+use warnings;
+use strict;
+use File::Basename qw(dirname); 
+use UNIVERSAL::require;
+
+BEGIN {
+    Jifty::Util->require or die $UNIVERSAL::require::ERROR;
+    my $root = Jifty::Util->app_root;
+    unshift @INC, "$root/lib" if ($root);
+}
+
+use Jifty::Script;
+$SIG{INT} = $SIG{TERM} = sub { warn "Stopped\n"; exit; };
+Jifty::Script->dispatch();

Added: jifty/branches/schema-plugins/examples/Ping/etc/config.yml
==============================================================================
--- (empty file)
+++ jifty/branches/schema-plugins/examples/Ping/etc/config.yml	Mon Jan 29 21:05:02 2007
@@ -0,0 +1,40 @@
+--- 
+framework: 
+  AdminMode: 1
+  ApplicationClass: Ping
+  ApplicationName: Ping
+  PubSub:
+    Enable: 1
+  Database: 
+    CheckSchema: 1
+    Database: ping
+    Driver: SQLite
+    Host: localhost
+    Password: ''
+    RecordBaseClass: Jifty::DBI::Record::Cachable
+    User: ''
+    Version: 0.0.1
+  DevelMode: 0
+  L10N: 
+    PoDir: share/po
+  LogLevel: WARN
+  Mailer: Sendmail
+  MailerArgs: []
+
+  Plugins: []
+
+  Web: 
+    BaseURL: http://localhost
+    DataDir: var/mason
+    Globals: []
+
+    MasonConfig: 
+      autoflush: 0
+      default_escape_flags: h
+      error_format: text
+      error_mode: fatal
+    Port: 8888
+    ServeStaticFiles: 1
+    StaticRoot: share/web/static
+    TemplateRoot: share/web/templates
+    ServerClass: Ping::Server

Added: jifty/branches/schema-plugins/examples/Ping/lib/Ping/Action/AddPing.pm
==============================================================================
--- (empty file)
+++ jifty/branches/schema-plugins/examples/Ping/lib/Ping/Action/AddPing.pm	Mon Jan 29 21:05:02 2007
@@ -0,0 +1,51 @@
+package Ping::Action::AddPing;
+use strict;
+use Jifty::Param::Schema;
+use Jifty::Action schema {
+
+param host =>
+    label is 'Hostname',
+    is mandatory;
+
+param only_failure =>
+    type is 'checkbox',
+    label is 'Failure only?',
+    hints is 'Show only failed pings to me.',
+    default is 0;
+
+};
+
+sub take_action {
+    my $self = shift;
+    my $host = $self->argument_value('host');
+    my $only_failure = $self->argument_value('only_failure');
+
+    Jifty->bus->modify(hosts => sub {
+        $_->{$host} ||= do {
+            if (my $pid = fork) {
+                $pid;
+            }
+            else {
+                exec($^X => "-Ilib", "-MPing::PingServer", "-e", "Ping::PingServer->ping('$host')");
+            }
+        }
+    });
+
+    my $id = Jifty->web->session->id;
+
+    Jifty->bus->modify("$id-ping" => sub {
+        my $sid = $_->{$host}; 
+        Jifty->subs->cancel($sid) if $sid;
+        $_->{$host} = Jifty->subs->add(
+            class       => 'Pong',
+            queries     => [{ host => $host }, $only_failure ? { fail => 1 } : ()],
+            mode        => 'Bottom',
+            region      => 'pong',
+            render_with => '/fragments/pong',
+        );
+    });
+
+    $self->result->message( "Added host: $host" );
+}
+
+1;

Added: jifty/branches/schema-plugins/examples/Ping/lib/Ping/Action/CancelPing.pm
==============================================================================
--- (empty file)
+++ jifty/branches/schema-plugins/examples/Ping/lib/Ping/Action/CancelPing.pm	Mon Jan 29 21:05:02 2007
@@ -0,0 +1,25 @@
+package Ping::Action::CancelPing;
+use strict;
+use Jifty::Param::Schema;
+use Jifty::Action schema {
+
+param host =>
+    label is 'Hostname',
+    is mandatory;
+
+};
+
+sub take_action {
+    my $self = shift;
+    my $host = $self->argument_value('host');
+
+    my $id  = Jifty->web->session->id;
+    my $sid = Jifty->bus->modify("$id-ping" => sub {
+        delete($_->{$host})
+    });
+    Jifty->subs->cancel($sid);
+
+    $self->result->message( "Cancelled host: $host" );
+}
+
+1;

Added: jifty/branches/schema-plugins/examples/Ping/lib/Ping/Event/Pong.pm
==============================================================================
--- (empty file)
+++ jifty/branches/schema-plugins/examples/Ping/lib/Ping/Event/Pong.pm	Mon Jan 29 21:05:02 2007
@@ -0,0 +1,25 @@
+package Ping::Event::Pong;
+use strict;
+use warnings;
+use base 'Ping::Event';
+
+sub match {
+    my $self    = shift;
+    my $query   = shift;
+
+    if ($query->{fail}) {
+        not $$self->{alive};
+    }
+    elsif (my $host = $query->{host}) {
+        $$self->{host} eq $host;
+    }
+    else {
+        1;
+    }
+}
+
+sub render_arguments {
+    %{$_[0]->data};
+}
+
+1;

Added: jifty/branches/schema-plugins/examples/Ping/lib/Ping/PingServer.pm
==============================================================================
--- (empty file)
+++ jifty/branches/schema-plugins/examples/Ping/lib/Ping/PingServer.pm	Mon Jan 29 21:05:02 2007
@@ -0,0 +1,25 @@
+package Ping::PingServer;
+
+use Net::Ping;
+use Time::HiRes qw( time sleep );
+use Jifty;
+
+BEGIN { Jifty->new };
+
+sub ping {
+    my ($class, $host) = @_;
+    my $ping = Net::Ping->new(tcp => 1);
+    while (1) {
+        my $old_time = time;
+        my $alive = $ping->ping($host);
+        my $new_time = time;
+
+        Ping::Event::Pong->new(
+            { host => $host, alive => ($alive ? ($new_time - $old_time + 0.001) : 0), time => $new_time }
+        )->publish;
+        sleep 1;
+    }
+    exit;
+}
+
+1;

Added: jifty/branches/schema-plugins/examples/Ping/lib/Ping/Server.pm
==============================================================================
--- (empty file)
+++ jifty/branches/schema-plugins/examples/Ping/lib/Ping/Server.pm	Mon Jan 29 21:05:02 2007
@@ -0,0 +1,7 @@
+package Ping::Server;
+use base 'Jifty::Server';
+use IO::Socket::INET;
+
+sub net_server { 'Net::Server::Fork' }
+
+1;

Added: jifty/branches/schema-plugins/examples/Ping/share/web/templates/fragments/pong
==============================================================================
--- (empty file)
+++ jifty/branches/schema-plugins/examples/Ping/share/web/templates/fragments/pong	Mon Jan 29 21:05:02 2007
@@ -0,0 +1,23 @@
+<%init>
+my $res = Jifty::Result->new;
+my $tm  = scalar localtime($time);
+if ($alive) {
+    $res->message( "Pong: $host ($tm)" ); # - $alive ($tm)" );
+}
+else {
+    $res->error( "Fail: $host ($tm)" ); # ($tm)" );
+}
+Jifty->web->response->{results} = {};
+Jifty->web->response->result("~$tm~$host" => $res);
+print  Jifty->web->render_messages;
+Jifty->web->response->{results} = {};
+</%init>
+<script>
+var objDiv = document.getElementById('pushed');
+objDiv.scrollTop = objDiv.scrollHeight;
+</script>
+<%args>
+$time
+$host
+$alive
+</%args>

Added: jifty/branches/schema-plugins/examples/Ping/share/web/templates/index.html
==============================================================================
--- (empty file)
+++ jifty/branches/schema-plugins/examples/Ping/share/web/templates/index.html	Mon Jan 29 21:05:02 2007
@@ -0,0 +1,50 @@
+<&|/_elements/wrapper, title => 'Ping for ' . Jifty->web->session->id &>
+
+<div id="pushed" style="overflow: scroll; width: 100%; height: 250px" >
+        <% $region->render %>
+</div>
+
+<table width="80%"><tr valign="top"><td>
+<fieldset>
+<legend>New Pings</legend>
+% my $form = Jifty->web->form->new(name => 'new');
+<% $form->start %>
+<% $action->form_field('host') %>
+<% $action->form_field('only_failure')%>
+<% $form->submit( label => 'Start' )%>
+<% $form->end %>
+</fieldset>
+% my $id = Jifty->web->session->id;
+% my $pings = Jifty->bus->modify("$id-ping") || {};
+% if (my @subs = keys %$pings) {
+</td><td>
+<fieldset>
+<legend>Current Pings</legend>
+<table width="100%">
+% foreach my $sub (@subs) {
+% $form = Jifty->web->form->new(name => $sub);
+<% $form->start %>
+%    my $del = Jifty->web->new_action(class => 'CancelPing', arguments => { host => $sub });
+<tr><td>
+<% $del->form_field('host', render_as => 'Hidden', default_value => $sub) %>
+<% $sub %>
+</td><td>
+<% $form->submit( label => 'Stop' )%>
+<% $form->end %>
+</td></tr>
+% }
+</table>
+</fieldset>
+% }
+</td></tr></table>
+<script>new Jifty.Subs({}).start();</script>
+</&>
+
+<%init>
+my $action = Jifty->web->new_action(class => 'AddPing');
+my $region = Jifty::Web::PageRegion->new(
+    name => 'pong',
+    path => '/__jifty/empty',
+);
+
+</%init>

Added: jifty/branches/schema-plugins/examples/Ping/t/00compile.t
==============================================================================
--- (empty file)
+++ jifty/branches/schema-plugins/examples/Ping/t/00compile.t	Mon Jan 29 21:05:02 2007
@@ -0,0 +1,22 @@
+#!/usr/bin/perl -w
+
+use Test::More;
+
+use File::Find;
+
+my @modules;
+find sub {
+    return unless /\.pm$/;
+    push @modules, $File::Find::name;
+}, "lib";
+
+ at modules = map { s[^lib/][];  $_ =~ s[.pm$][];  $_ =~ s[/][::]g; $_ } @modules;
+
+plan tests => scalar @modules;
+
+# Ping::PingServer will not compile without a schema.
+system "bin/jifty schema --setup";
+
+for my $module (@modules) {
+    require_ok $module;
+}

Added: jifty/branches/schema-plugins/examples/Ping/t/01startup.t
==============================================================================
--- (empty file)
+++ jifty/branches/schema-plugins/examples/Ping/t/01startup.t	Mon Jan 29 21:05:02 2007
@@ -0,0 +1,13 @@
+#!/usr/bin/perl -w
+
+use Jifty::Test 'no_plan';
+use Jifty::Test::WWW::Mechanize;
+
+# Startup the ping server.
+my $server = Jifty::Test->make_server;
+isa_ok($server, 'Jifty::Server');
+
+my $URL = $server->started_ok;
+my $mech = Jifty::Test::WWW::Mechanize->new;
+
+$mech->get_ok("$URL", "got the front page");

Added: jifty/branches/schema-plugins/inc/Module/AutoInstall.pm
==============================================================================
--- (empty file)
+++ jifty/branches/schema-plugins/inc/Module/AutoInstall.pm	Mon Jan 29 21:05:02 2007
@@ -0,0 +1,768 @@
+#line 1
+package Module::AutoInstall;
+
+use strict;
+use Cwd                 ();
+use ExtUtils::MakeMaker ();
+
+use vars qw{$VERSION};
+BEGIN {
+	$VERSION = '1.03';
+}
+
+# special map on pre-defined feature sets
+my %FeatureMap = (
+    ''      => 'Core Features',    # XXX: deprecated
+    '-core' => 'Core Features',
+);
+
+# various lexical flags
+my ( @Missing, @Existing,  %DisabledTests, $UnderCPAN,     $HasCPANPLUS );
+my ( $Config,  $CheckOnly, $SkipInstall,   $AcceptDefault, $TestOnly );
+my ( $PostambleActions, $PostambleUsed );
+
+# See if it's a testing or non-interactive session
+_accept_default( $ENV{AUTOMATED_TESTING} or ! -t STDIN ); 
+_init();
+
+sub _accept_default {
+    $AcceptDefault = shift;
+}
+
+sub missing_modules {
+    return @Missing;
+}
+
+sub do_install {
+    __PACKAGE__->install(
+        [
+            $Config
+            ? ( UNIVERSAL::isa( $Config, 'HASH' ) ? %{$Config} : @{$Config} )
+            : ()
+        ],
+        @Missing,
+    );
+}
+
+# initialize various flags, and/or perform install
+sub _init {
+    foreach my $arg (
+        @ARGV,
+        split(
+            /[\s\t]+/,
+            $ENV{PERL_AUTOINSTALL} || $ENV{PERL_EXTUTILS_AUTOINSTALL} || ''
+        )
+      )
+    {
+        if ( $arg =~ /^--config=(.*)$/ ) {
+            $Config = [ split( ',', $1 ) ];
+        }
+        elsif ( $arg =~ /^--installdeps=(.*)$/ ) {
+            __PACKAGE__->install( $Config, @Missing = split( /,/, $1 ) );
+            exit 0;
+        }
+        elsif ( $arg =~ /^--default(?:deps)?$/ ) {
+            $AcceptDefault = 1;
+        }
+        elsif ( $arg =~ /^--check(?:deps)?$/ ) {
+            $CheckOnly = 1;
+        }
+        elsif ( $arg =~ /^--skip(?:deps)?$/ ) {
+            $SkipInstall = 1;
+        }
+        elsif ( $arg =~ /^--test(?:only)?$/ ) {
+            $TestOnly = 1;
+        }
+    }
+}
+
+# overrides MakeMaker's prompt() to automatically accept the default choice
+sub _prompt {
+    goto &ExtUtils::MakeMaker::prompt unless $AcceptDefault;
+
+    my ( $prompt, $default ) = @_;
+    my $y = ( $default =~ /^[Yy]/ );
+
+    print $prompt, ' [', ( $y ? 'Y' : 'y' ), '/', ( $y ? 'n' : 'N' ), '] ';
+    print "$default\n";
+    return $default;
+}
+
+# the workhorse
+sub import {
+    my $class = shift;
+    my @args  = @_ or return;
+    my $core_all;
+
+    print "*** $class version " . $class->VERSION . "\n";
+    print "*** Checking for Perl dependencies...\n";
+
+    my $cwd = Cwd::cwd();
+
+    $Config = [];
+
+    my $maxlen = length(
+        (
+            sort   { length($b) <=> length($a) }
+              grep { /^[^\-]/ }
+              map  {
+                ref($_)
+                  ? ( ( ref($_) eq 'HASH' ) ? keys(%$_) : @{$_} )
+                  : ''
+              }
+              map { +{@args}->{$_} }
+              grep { /^[^\-]/ or /^-core$/i } keys %{ +{@args} }
+        )[0]
+    );
+
+    while ( my ( $feature, $modules ) = splice( @args, 0, 2 ) ) {
+        my ( @required, @tests, @skiptests );
+        my $default  = 1;
+        my $conflict = 0;
+
+        if ( $feature =~ m/^-(\w+)$/ ) {
+            my $option = lc($1);
+
+            # check for a newer version of myself
+            _update_to( $modules, @_ ) and return if $option eq 'version';
+
+            # sets CPAN configuration options
+            $Config = $modules if $option eq 'config';
+
+            # promote every features to core status
+            $core_all = ( $modules =~ /^all$/i ) and next
+              if $option eq 'core';
+
+            next unless $option eq 'core';
+        }
+
+        print "[" . ( $FeatureMap{ lc($feature) } || $feature ) . "]\n";
+
+        $modules = [ %{$modules} ] if UNIVERSAL::isa( $modules, 'HASH' );
+
+        unshift @$modules, -default => &{ shift(@$modules) }
+          if ( ref( $modules->[0] ) eq 'CODE' );    # XXX: bugward combatability
+
+        while ( my ( $mod, $arg ) = splice( @$modules, 0, 2 ) ) {
+            if ( $mod =~ m/^-(\w+)$/ ) {
+                my $option = lc($1);
+
+                $default   = $arg    if ( $option eq 'default' );
+                $conflict  = $arg    if ( $option eq 'conflict' );
+                @tests     = @{$arg} if ( $option eq 'tests' );
+                @skiptests = @{$arg} if ( $option eq 'skiptests' );
+
+                next;
+            }
+
+            printf( "- %-${maxlen}s ...", $mod );
+
+            if ( $arg and $arg =~ /^\D/ ) {
+                unshift @$modules, $arg;
+                $arg = 0;
+            }
+
+            # XXX: check for conflicts and uninstalls(!) them.
+            if (
+                defined( my $cur = _version_check( _load($mod), $arg ||= 0 ) ) )
+            {
+                print "loaded. ($cur" . ( $arg ? " >= $arg" : '' ) . ")\n";
+                push @Existing, $mod => $arg;
+                $DisabledTests{$_} = 1 for map { glob($_) } @skiptests;
+            }
+            else {
+                print "missing." . ( $arg ? " (would need $arg)" : '' ) . "\n";
+                push @required, $mod => $arg;
+            }
+        }
+
+        next unless @required;
+
+        my $mandatory = ( $feature eq '-core' or $core_all );
+
+        if (
+            !$SkipInstall
+            and (
+                $CheckOnly
+                or _prompt(
+                    qq{==> Auto-install the }
+                      . ( @required / 2 )
+                      . ( $mandatory ? ' mandatory' : ' optional' )
+                      . qq{ module(s) from CPAN?},
+                    $default ? 'y' : 'n',
+                ) =~ /^[Yy]/
+            )
+          )
+        {
+            push( @Missing, @required );
+            $DisabledTests{$_} = 1 for map { glob($_) } @skiptests;
+        }
+
+        elsif ( !$SkipInstall
+            and $default
+            and $mandatory
+            and
+            _prompt( qq{==> The module(s) are mandatory! Really skip?}, 'n', )
+            =~ /^[Nn]/ )
+        {
+            push( @Missing, @required );
+            $DisabledTests{$_} = 1 for map { glob($_) } @skiptests;
+        }
+
+        else {
+            $DisabledTests{$_} = 1 for map { glob($_) } @tests;
+        }
+    }
+
+    $UnderCPAN = _check_lock();    # check for $UnderCPAN
+
+    if ( @Missing and not( $CheckOnly or $UnderCPAN ) ) {
+        require Config;
+        print
+"*** Dependencies will be installed the next time you type '$Config::Config{make}'.\n";
+
+        # make an educated guess of whether we'll need root permission.
+        print "    (You may need to do that as the 'root' user.)\n"
+          if eval '$>';
+    }
+    print "*** $class configuration finished.\n";
+
+    chdir $cwd;
+
+    # import to main::
+    no strict 'refs';
+    *{'main::WriteMakefile'} = \&Write if caller(0) eq 'main';
+}
+
+# Check to see if we are currently running under CPAN.pm and/or CPANPLUS;
+# if we are, then we simply let it taking care of our dependencies
+sub _check_lock {
+    return unless @Missing;
+
+    if ($ENV{PERL5_CPANPLUS_IS_RUNNING}) {
+        print <<'END_MESSAGE';
+
+*** Since we're running under CPANPLUS, I'll just let it take care
+    of the dependency's installation later.
+END_MESSAGE
+        return 1;
+    }
+
+    _load_cpan();
+
+    # Find the CPAN lock-file
+    my $lock = MM->catfile( $CPAN::Config->{cpan_home}, ".lock" );
+    return unless -f $lock;
+
+    # Check the lock
+    local *LOCK;
+    return unless open(LOCK, $lock);
+
+    if (
+            ( $^O eq 'MSWin32' ? _under_cpan() : <LOCK> == getppid() )
+        and ( $CPAN::Config->{prerequisites_policy} || '' ) ne 'ignore'
+    ) {
+        print <<'END_MESSAGE';
+
+*** Since we're running under CPAN, I'll just let it take care
+    of the dependency's installation later.
+END_MESSAGE
+        return 1;
+    }
+
+    close LOCK;
+    return;
+}
+
+sub install {
+    my $class = shift;
+
+    my $i;    # used below to strip leading '-' from config keys
+    my @config = ( map { s/^-// if ++$i; $_ } @{ +shift } );
+
+    my ( @modules, @installed );
+    while ( my ( $pkg, $ver ) = splice( @_, 0, 2 ) ) {
+
+        # grep out those already installed
+        if ( defined( _version_check( _load($pkg), $ver ) ) ) {
+            push @installed, $pkg;
+        }
+        else {
+            push @modules, $pkg, $ver;
+        }
+    }
+
+    return @installed unless @modules;  # nothing to do
+    return @installed if _check_lock(); # defer to the CPAN shell
+
+    print "*** Installing dependencies...\n";
+
+    return unless _connected_to('cpan.org');
+
+    my %args = @config;
+    my %failed;
+    local *FAILED;
+    if ( $args{do_once} and open( FAILED, '.#autoinstall.failed' ) ) {
+        while (<FAILED>) { chomp; $failed{$_}++ }
+        close FAILED;
+
+        my @newmod;
+        while ( my ( $k, $v ) = splice( @modules, 0, 2 ) ) {
+            push @newmod, ( $k => $v ) unless $failed{$k};
+        }
+        @modules = @newmod;
+    }
+
+    if ( _has_cpanplus() ) {
+        _install_cpanplus( \@modules, \@config );
+    } else {
+        _install_cpan( \@modules, \@config );
+    }
+
+    print "*** $class installation finished.\n";
+
+    # see if we have successfully installed them
+    while ( my ( $pkg, $ver ) = splice( @modules, 0, 2 ) ) {
+        if ( defined( _version_check( _load($pkg), $ver ) ) ) {
+            push @installed, $pkg;
+        }
+        elsif ( $args{do_once} and open( FAILED, '>> .#autoinstall.failed' ) ) {
+            print FAILED "$pkg\n";
+        }
+    }
+
+    close FAILED if $args{do_once};
+
+    return @installed;
+}
+
+sub _install_cpanplus {
+    my @modules   = @{ +shift };
+    my @config    = _cpanplus_config( @{ +shift } );
+    my $installed = 0;
+
+    require CPANPLUS::Backend;
+    my $cp   = CPANPLUS::Backend->new;
+    my $conf = $cp->configure_object;
+
+    return unless $conf->can('conf') # 0.05x+ with "sudo" support
+               or _can_write($conf->_get_build('base'));  # 0.04x
+
+    # if we're root, set UNINST=1 to avoid trouble unless user asked for it.
+    my $makeflags = $conf->get_conf('makeflags') || '';
+    if ( UNIVERSAL::isa( $makeflags, 'HASH' ) ) {
+        # 0.03+ uses a hashref here
+        $makeflags->{UNINST} = 1 unless exists $makeflags->{UNINST};
+
+    } else {
+        # 0.02 and below uses a scalar
+        $makeflags = join( ' ', split( ' ', $makeflags ), 'UNINST=1' )
+          if ( $makeflags !~ /\bUNINST\b/ and eval qq{ $> eq '0' } );
+
+    }
+    $conf->set_conf( makeflags => $makeflags );
+    $conf->set_conf( prereqs   => 1 );
+
+    
+
+    while ( my ( $key, $val ) = splice( @config, 0, 2 ) ) {
+        $conf->set_conf( $key, $val );
+    }
+
+    my $modtree = $cp->module_tree;
+    while ( my ( $pkg, $ver ) = splice( @modules, 0, 2 ) ) {
+        print "*** Installing $pkg...\n";
+
+        MY::preinstall( $pkg, $ver ) or next if defined &MY::preinstall;
+
+        my $success;
+        my $obj = $modtree->{$pkg};
+
+        if ( $obj and defined( _version_check( $obj->{version}, $ver ) ) ) {
+            my $pathname = $pkg;
+            $pathname =~ s/::/\\W/;
+
+            foreach my $inc ( grep { m/$pathname.pm/i } keys(%INC) ) {
+                delete $INC{$inc};
+            }
+
+            my $rv = $cp->install( modules => [ $obj->{module} ] );
+
+            if ( $rv and ( $rv->{ $obj->{module} } or $rv->{ok} ) ) {
+                print "*** $pkg successfully installed.\n";
+                $success = 1;
+            } else {
+                print "*** $pkg installation cancelled.\n";
+                $success = 0;
+            }
+
+            $installed += $success;
+        } else {
+            print << ".";
+*** Could not find a version $ver or above for $pkg; skipping.
+.
+        }
+
+        MY::postinstall( $pkg, $ver, $success ) if defined &MY::postinstall;
+    }
+
+    return $installed;
+}
+
+sub _cpanplus_config {
+	my @config = ();
+	while ( @_ ) {
+		my ($key, $value) = (shift(), shift());
+		if ( $key eq 'prerequisites_policy' ) {
+			if ( $value eq 'follow' ) {
+				$value = CPANPLUS::Internals::Constants::PREREQ_INSTALL();
+			} elsif ( $value eq 'ask' ) {
+				$value = CPANPLUS::Internals::Constants::PREREQ_ASK();
+			} elsif ( $value eq 'ignore' ) {
+				$value = CPANPLUS::Internals::Constants::PREREQ_IGNORE();
+			} else {
+				die "*** Cannot convert option $key = '$value' to CPANPLUS version.\n";
+			}
+		} else {
+			die "*** Cannot convert option $key to CPANPLUS version.\n";
+		}
+	}
+	return @config;
+}
+
+sub _install_cpan {
+    my @modules   = @{ +shift };
+    my @config    = @{ +shift };
+    my $installed = 0;
+    my %args;
+
+    _load_cpan();
+    require Config;
+
+    if (CPAN->VERSION < 1.80) {
+        # no "sudo" support, probe for writableness
+        return unless _can_write( MM->catfile( $CPAN::Config->{cpan_home}, 'sources' ) )
+                  and _can_write( $Config::Config{sitelib} );
+    }
+
+    # if we're root, set UNINST=1 to avoid trouble unless user asked for it.
+    my $makeflags = $CPAN::Config->{make_install_arg} || '';
+    $CPAN::Config->{make_install_arg} =
+      join( ' ', split( ' ', $makeflags ), 'UNINST=1' )
+      if ( $makeflags !~ /\bUNINST\b/ and eval qq{ $> eq '0' } );
+
+    # don't show start-up info
+    $CPAN::Config->{inhibit_startup_message} = 1;
+
+    # set additional options
+    while ( my ( $opt, $arg ) = splice( @config, 0, 2 ) ) {
+        ( $args{$opt} = $arg, next )
+          if $opt =~ /^force$/;    # pseudo-option
+        $CPAN::Config->{$opt} = $arg;
+    }
+
+    local $CPAN::Config->{prerequisites_policy} = 'follow';
+
+    while ( my ( $pkg, $ver ) = splice( @modules, 0, 2 ) ) {
+        MY::preinstall( $pkg, $ver ) or next if defined &MY::preinstall;
+
+        print "*** Installing $pkg...\n";
+
+        my $obj     = CPAN::Shell->expand( Module => $pkg );
+        my $success = 0;
+
+        if ( $obj and defined( _version_check( $obj->cpan_version, $ver ) ) ) {
+            my $pathname = $pkg;
+            $pathname =~ s/::/\\W/;
+
+            foreach my $inc ( grep { m/$pathname.pm/i } keys(%INC) ) {
+                delete $INC{$inc};
+            }
+
+            my $rv = $args{force} ? CPAN::Shell->force( install => $pkg )
+                                  : CPAN::Shell->install($pkg);
+            $rv ||= eval {
+                $CPAN::META->instance( 'CPAN::Distribution', $obj->cpan_file, )
+                  ->{install}
+                  if $CPAN::META;
+            };
+
+            if ( $rv eq 'YES' ) {
+                print "*** $pkg successfully installed.\n";
+                $success = 1;
+            }
+            else {
+                print "*** $pkg installation failed.\n";
+                $success = 0;
+            }
+
+            $installed += $success;
+        }
+        else {
+            print << ".";
+*** Could not find a version $ver or above for $pkg; skipping.
+.
+        }
+
+        MY::postinstall( $pkg, $ver, $success ) if defined &MY::postinstall;
+    }
+
+    return $installed;
+}
+
+sub _has_cpanplus {
+    return (
+        $HasCPANPLUS = (
+            $INC{'CPANPLUS/Config.pm'}
+              or _load('CPANPLUS::Shell::Default')
+        )
+    );
+}
+
+# make guesses on whether we're under the CPAN installation directory
+sub _under_cpan {
+    require Cwd;
+    require File::Spec;
+
+    my $cwd  = File::Spec->canonpath( Cwd::cwd() );
+    my $cpan = File::Spec->canonpath( $CPAN::Config->{cpan_home} );
+
+    return ( index( $cwd, $cpan ) > -1 );
+}
+
+sub _update_to {
+    my $class = __PACKAGE__;
+    my $ver   = shift;
+
+    return
+      if defined( _version_check( _load($class), $ver ) );  # no need to upgrade
+
+    if (
+        _prompt( "==> A newer version of $class ($ver) is required. Install?",
+            'y' ) =~ /^[Nn]/
+      )
+    {
+        die "*** Please install $class $ver manually.\n";
+    }
+
+    print << ".";
+*** Trying to fetch it from CPAN...
+.
+
+    # install ourselves
+    _load($class) and return $class->import(@_)
+      if $class->install( [], $class, $ver );
+
+    print << '.'; exit 1;
+
+*** Cannot bootstrap myself. :-( Installation terminated.
+.
+}
+
+# check if we're connected to some host, using inet_aton
+sub _connected_to {
+    my $site = shift;
+
+    return (
+        ( _load('Socket') and Socket::inet_aton($site) ) or _prompt(
+            qq(
+*** Your host cannot resolve the domain name '$site', which
+    probably means the Internet connections are unavailable.
+==> Should we try to install the required module(s) anyway?), 'n'
+          ) =~ /^[Yy]/
+    );
+}
+
+# check if a directory is writable; may create it on demand
+sub _can_write {
+    my $path = shift;
+    mkdir( $path, 0755 ) unless -e $path;
+
+    return 1 if -w $path;
+
+    print << ".";
+*** You are not allowed to write to the directory '$path';
+    the installation may fail due to insufficient permissions.
+.
+
+    if (
+        eval '$>' and lc(`sudo -V`) =~ /version/ and _prompt(
+            qq(
+==> Should we try to re-execute the autoinstall process with 'sudo'?),
+            ((-t STDIN) ? 'y' : 'n')
+        ) =~ /^[Yy]/
+      )
+    {
+
+        # try to bootstrap ourselves from sudo
+        print << ".";
+*** Trying to re-execute the autoinstall process with 'sudo'...
+.
+        my $missing = join( ',', @Missing );
+        my $config = join( ',',
+            UNIVERSAL::isa( $Config, 'HASH' ) ? %{$Config} : @{$Config} )
+          if $Config;
+
+        return
+          unless system( 'sudo', $^X, $0, "--config=$config",
+            "--installdeps=$missing" );
+
+        print << ".";
+*** The 'sudo' command exited with error!  Resuming...
+.
+    }
+
+    return _prompt(
+        qq(
+==> Should we try to install the required module(s) anyway?), 'n'
+    ) =~ /^[Yy]/;
+}
+
+# load a module and return the version it reports
+sub _load {
+    my $mod  = pop;    # class/instance doesn't matter
+    my $file = $mod;
+
+    $file =~ s|::|/|g;
+    $file .= '.pm';
+
+    local $@;
+    return eval { require $file; $mod->VERSION } || ( $@ ? undef: 0 );
+}
+
+# Load CPAN.pm and it's configuration
+sub _load_cpan {
+    return if $CPAN::VERSION;
+    require CPAN;
+    if ( $CPAN::HandleConfig::VERSION ) {
+        # Newer versions of CPAN have a HandleConfig module
+        CPAN::HandleConfig->load;
+    } else {
+    	# Older versions had the load method in Config directly
+        CPAN::Config->load;
+    }
+}
+
+# compare two versions, either use Sort::Versions or plain comparison
+sub _version_check {
+    my ( $cur, $min ) = @_;
+    return unless defined $cur;
+
+    $cur =~ s/\s+$//;
+
+    # check for version numbers that are not in decimal format
+    if ( ref($cur) or ref($min) or $cur =~ /v|\..*\./ or $min =~ /v|\..*\./ ) {
+        if ( ( $version::VERSION or defined( _load('version') )) and
+             version->can('new') 
+            ) {
+
+            # use version.pm if it is installed.
+            return (
+                ( version->new($cur) >= version->new($min) ) ? $cur : undef );
+        }
+        elsif ( $Sort::Versions::VERSION or defined( _load('Sort::Versions') ) )
+        {
+
+            # use Sort::Versions as the sorting algorithm for a.b.c versions
+            return ( ( Sort::Versions::versioncmp( $cur, $min ) != -1 )
+                ? $cur
+                : undef );
+        }
+
+        warn "Cannot reliably compare non-decimal formatted versions.\n"
+          . "Please install version.pm or Sort::Versions.\n";
+    }
+
+    # plain comparison
+    local $^W = 0;    # shuts off 'not numeric' bugs
+    return ( $cur >= $min ? $cur : undef );
+}
+
+# nothing; this usage is deprecated.
+sub main::PREREQ_PM { return {}; }
+
+sub _make_args {
+    my %args = @_;
+
+    $args{PREREQ_PM} = { %{ $args{PREREQ_PM} || {} }, @Existing, @Missing }
+      if $UnderCPAN or $TestOnly;
+
+    if ( $args{EXE_FILES} and -e 'MANIFEST' ) {
+        require ExtUtils::Manifest;
+        my $manifest = ExtUtils::Manifest::maniread('MANIFEST');
+
+        $args{EXE_FILES} =
+          [ grep { exists $manifest->{$_} } @{ $args{EXE_FILES} } ];
+    }
+
+    $args{test}{TESTS} ||= 't/*.t';
+    $args{test}{TESTS} = join( ' ',
+        grep { !exists( $DisabledTests{$_} ) }
+          map { glob($_) } split( /\s+/, $args{test}{TESTS} ) );
+
+    my $missing = join( ',', @Missing );
+    my $config =
+      join( ',', UNIVERSAL::isa( $Config, 'HASH' ) ? %{$Config} : @{$Config} )
+      if $Config;
+
+    $PostambleActions = (
+        $missing
+        ? "\$(PERL) $0 --config=$config --installdeps=$missing"
+        : "\$(NOECHO) \$(NOOP)"
+    );
+
+    return %args;
+}
+
+# a wrapper to ExtUtils::MakeMaker::WriteMakefile
+sub Write {
+    require Carp;
+    Carp::croak "WriteMakefile: Need even number of args" if @_ % 2;
+
+    if ($CheckOnly) {
+        print << ".";
+*** Makefile not written in check-only mode.
+.
+        return;
+    }
+
+    my %args = _make_args(@_);
+
+    no strict 'refs';
+
+    $PostambleUsed = 0;
+    local *MY::postamble = \&postamble unless defined &MY::postamble;
+    ExtUtils::MakeMaker::WriteMakefile(%args);
+
+    print << "." unless $PostambleUsed;
+*** WARNING: Makefile written with customized MY::postamble() without
+    including contents from Module::AutoInstall::postamble() --
+    auto installation features disabled.  Please contact the author.
+.
+
+    return 1;
+}
+
+sub postamble {
+    $PostambleUsed = 1;
+
+    return << ".";
+
+config :: installdeps
+\t\$(NOECHO) \$(NOOP)
+
+checkdeps ::
+\t\$(PERL) $0 --checkdeps
+
+installdeps ::
+\t$PostambleActions
+
+.
+
+}
+
+1;
+
+__END__
+
+#line 1003

Added: jifty/branches/schema-plugins/inc/Module/Install.pm
==============================================================================
--- (empty file)
+++ jifty/branches/schema-plugins/inc/Module/Install.pm	Mon Jan 29 21:05:02 2007
@@ -0,0 +1,281 @@
+#line 1
+package Module::Install;
+
+# For any maintainers:
+# The load order for Module::Install is a bit magic.
+# It goes something like this...
+#
+# IF ( host has Module::Install installed, creating author mode ) {
+#     1. Makefile.PL calls "use inc::Module::Install"
+#     2. $INC{inc/Module/Install.pm} set to installed version of inc::Module::Install
+#     3. The installed version of inc::Module::Install loads
+#     4. inc::Module::Install calls "require Module::Install"
+#     5. The ./inc/ version of Module::Install loads
+# } ELSE {
+#     1. Makefile.PL calls "use inc::Module::Install"
+#     2. $INC{inc/Module/Install.pm} set to ./inc/ version of Module::Install
+#     3. The ./inc/ version of Module::Install loads
+# }
+
+use 5.004;
+use strict 'vars';
+
+use vars qw{$VERSION};
+BEGIN {
+    # All Module::Install core packages now require synchronised versions.
+    # This will be used to ensure we don't accidentally load old or
+    # different versions of modules.
+    # This is not enforced yet, but will be some time in the next few
+    # releases once we can make sure it won't clash with custom
+    # Module::Install extensions.
+    $VERSION = '0.64';
+}
+
+# Whether or not inc::Module::Install is actually loaded, the
+# $INC{inc/Module/Install.pm} is what will still get set as long as
+# the caller loaded module this in the documented manner.
+# If not set, the caller may NOT have loaded the bundled version, and thus
+# they may not have a MI version that works with the Makefile.PL. This would
+# result in false errors or unexpected behaviour. And we don't want that.
+my $file = join( '/', 'inc', split /::/, __PACKAGE__ ) . '.pm';
+unless ( $INC{$file} ) {
+    die <<"END_DIE";
+Please invoke ${\__PACKAGE__} with:
+
+    use inc::${\__PACKAGE__};
+
+not:
+
+    use ${\__PACKAGE__};
+
+END_DIE
+}
+
+# If the script that is loading Module::Install is from the future,
+# then make will detect this and cause it to re-run over and over
+# again. This is bad. Rather than taking action to touch it (which
+# is unreliable on some platforms and requires write permissions)
+# for now we should catch this and refuse to run.
+if ( -f $0 and (stat($0))[9] > time ) {
+	die << "END_DIE";
+Your installer $0 has a modification time in the future.
+
+This is known to create infinite loops in make.
+
+Please correct this, then run $0 again.
+
+END_DIE
+}
+
+use Cwd        ();
+use File::Find ();
+use File::Path ();
+use FindBin;
+
+*inc::Module::Install::VERSION = *VERSION;
+ at inc::Module::Install::ISA     = __PACKAGE__;
+
+sub autoload {
+    my $self = shift;
+    my $who  = $self->_caller;
+    my $cwd  = Cwd::cwd();
+    my $sym  = "${who}::AUTOLOAD";
+    $sym->{$cwd} = sub {
+        my $pwd = Cwd::cwd();
+        if ( my $code = $sym->{$pwd} ) {
+            # delegate back to parent dirs
+            goto &$code unless $cwd eq $pwd;
+        }
+        $$sym =~ /([^:]+)$/ or die "Cannot autoload $who - $sym";
+        unshift @_, ($self, $1);
+        goto &{$self->can('call')} unless uc($1) eq $1;
+    };
+}
+
+sub import {
+    my $class = shift;
+    my $self  = $class->new(@_);
+    my $who   = $self->_caller;
+
+    unless ( -f $self->{file} ) {
+        require "$self->{path}/$self->{dispatch}.pm";
+        File::Path::mkpath("$self->{prefix}/$self->{author}");
+        $self->{admin} = "$self->{name}::$self->{dispatch}"->new( _top => $self );
+        $self->{admin}->init;
+        @_ = ($class, _self => $self);
+        goto &{"$self->{name}::import"};
+    }
+
+    *{"${who}::AUTOLOAD"} = $self->autoload;
+    $self->preload;
+
+    # Unregister loader and worker packages so subdirs can use them again
+    delete $INC{"$self->{file}"};
+    delete $INC{"$self->{path}.pm"};
+}
+
+sub preload {
+    my ($self) = @_;
+
+    unless ( $self->{extensions} ) {
+        $self->load_extensions(
+            "$self->{prefix}/$self->{path}", $self
+        );
+    }
+
+    my @exts = @{$self->{extensions}};
+    unless ( @exts ) {
+        my $admin = $self->{admin};
+        @exts = $admin->load_all_extensions;
+    }
+
+    my %seen;
+    foreach my $obj ( @exts ) {
+        while (my ($method, $glob) = each %{ref($obj) . '::'}) {
+            next unless $obj->can($method);
+            next if $method =~ /^_/;
+            next if $method eq uc($method);
+            $seen{$method}++;
+        }
+    }
+
+    my $who = $self->_caller;
+    foreach my $name ( sort keys %seen ) {
+        *{"${who}::$name"} = sub {
+            ${"${who}::AUTOLOAD"} = "${who}::$name";
+            goto &{"${who}::AUTOLOAD"};
+        };
+    }
+}
+
+sub new {
+    my ($class, %args) = @_;
+
+    # ignore the prefix on extension modules built from top level.
+    my $base_path = Cwd::abs_path($FindBin::Bin);
+    unless ( Cwd::abs_path(Cwd::cwd()) eq $base_path ) {
+        delete $args{prefix};
+    }
+
+    return $args{_self} if $args{_self};
+
+    $args{dispatch} ||= 'Admin';
+    $args{prefix}   ||= 'inc';
+    $args{author}   ||= ($^O eq 'VMS' ? '_author' : '.author');
+    $args{bundle}   ||= 'inc/BUNDLES';
+    $args{base}     ||= $base_path;
+    $class =~ s/^\Q$args{prefix}\E:://;
+    $args{name}     ||= $class;
+    $args{version}  ||= $class->VERSION;
+    unless ( $args{path} ) {
+        $args{path}  = $args{name};
+        $args{path}  =~ s!::!/!g;
+    }
+    $args{file}     ||= "$args{base}/$args{prefix}/$args{path}.pm";
+
+    bless( \%args, $class );
+}
+
+sub call {
+	my ($self, $method) = @_;
+	my $obj = $self->load($method) or return;
+        splice(@_, 0, 2, $obj);
+	goto &{$obj->can($method)};
+}
+
+sub load {
+    my ($self, $method) = @_;
+
+    $self->load_extensions(
+        "$self->{prefix}/$self->{path}", $self
+    ) unless $self->{extensions};
+
+    foreach my $obj (@{$self->{extensions}}) {
+        return $obj if $obj->can($method);
+    }
+
+    my $admin = $self->{admin} or die <<"END_DIE";
+The '$method' method does not exist in the '$self->{prefix}' path!
+Please remove the '$self->{prefix}' directory and run $0 again to load it.
+END_DIE
+
+    my $obj = $admin->load($method, 1);
+    push @{$self->{extensions}}, $obj;
+
+    $obj;
+}
+
+sub load_extensions {
+    my ($self, $path, $top) = @_;
+
+    unless ( grep { lc $_ eq lc $self->{prefix} } @INC ) {
+        unshift @INC, $self->{prefix};
+    }
+
+    foreach my $rv ( $self->find_extensions($path) ) {
+        my ($file, $pkg) = @{$rv};
+        next if $self->{pathnames}{$pkg};
+
+        local $@;
+        my $new = eval { require $file; $pkg->can('new') };
+        unless ( $new ) {
+            warn $@ if $@;
+            next;
+        }
+        $self->{pathnames}{$pkg} = delete $INC{$file};
+        push @{$self->{extensions}}, &{$new}($pkg, _top => $top );
+    }
+
+    $self->{extensions} ||= [];
+}
+
+sub find_extensions {
+    my ($self, $path) = @_;
+
+    my @found;
+    File::Find::find( sub {
+        my $file = $File::Find::name;
+        return unless $file =~ m!^\Q$path\E/(.+)\.pm\Z!is;
+        my $subpath = $1;
+        return if lc($subpath) eq lc($self->{dispatch});
+
+        $file = "$self->{path}/$subpath.pm";
+        my $pkg = "$self->{name}::$subpath";
+        $pkg =~ s!/!::!g;
+
+        # If we have a mixed-case package name, assume case has been preserved
+        # correctly.  Otherwise, root through the file to locate the case-preserved
+        # version of the package name.
+        if ( $subpath eq lc($subpath) || $subpath eq uc($subpath) ) {
+            open PKGFILE, "<$subpath.pm" or die "find_extensions: Can't open $subpath.pm: $!";
+            my $in_pod = 0;
+            while ( <PKGFILE> ) {
+                $in_pod = 1 if /^=\w/;
+                $in_pod = 0 if /^=cut/;
+                next if ($in_pod || /^=cut/);  # skip pod text
+                next if /^\s*#/;               # and comments
+                if ( m/^\s*package\s+($pkg)\s*;/i ) {
+                    $pkg = $1;
+                    last;
+                }
+            }
+            close PKGFILE;
+        }
+
+        push @found, [ $file, $pkg ];
+    }, $path ) if -d $path;
+
+    @found;
+}
+
+sub _caller {
+    my $depth = 0;
+    my $call  = caller($depth);
+    while ( $call eq __PACKAGE__ ) {
+        $depth++;
+        $call = caller($depth);
+    }
+    return $call;
+}
+
+1;

Added: jifty/branches/schema-plugins/inc/Module/Install/AutoInstall.pm
==============================================================================
--- (empty file)
+++ jifty/branches/schema-plugins/inc/Module/Install/AutoInstall.pm	Mon Jan 29 21:05:02 2007
@@ -0,0 +1,61 @@
+#line 1
+package Module::Install::AutoInstall;
+
+use strict;
+use Module::Install::Base;
+
+use vars qw{$VERSION $ISCORE @ISA};
+BEGIN {
+	$VERSION = '0.64';
+	$ISCORE  = 1;
+	@ISA     = qw{Module::Install::Base};
+}
+
+sub AutoInstall { $_[0] }
+
+sub run {
+    my $self = shift;
+    $self->auto_install_now(@_);
+}
+
+sub write {
+    my $self = shift;
+    $self->auto_install(@_);
+}
+
+sub auto_install {
+    my $self = shift;
+    return if $self->{done}++;
+
+    # Flatten array of arrays into a single array
+    my @core = map @$_, map @$_, grep ref,
+               $self->build_requires, $self->requires;
+
+    my @config = @_;
+
+    # We'll need Module::AutoInstall
+    $self->include('Module::AutoInstall');
+    require Module::AutoInstall;
+
+    Module::AutoInstall->import(
+        (@config ? (-config => \@config) : ()),
+        (@core   ? (-core   => \@core)   : ()),
+        $self->features,
+    );
+
+    $self->makemaker_args( Module::AutoInstall::_make_args() );
+
+    my $class = ref($self);
+    $self->postamble(
+        "# --- $class section:\n" .
+        Module::AutoInstall::postamble()
+    );
+}
+
+sub auto_install_now {
+    my $self = shift;
+    $self->auto_install(@_);
+    Module::AutoInstall::do_install();
+}
+
+1;

Added: jifty/branches/schema-plugins/inc/Module/Install/Base.pm
==============================================================================
--- (empty file)
+++ jifty/branches/schema-plugins/inc/Module/Install/Base.pm	Mon Jan 29 21:05:02 2007
@@ -0,0 +1,70 @@
+#line 1
+package Module::Install::Base;
+
+$VERSION = '0.64';
+
+# Suspend handler for "redefined" warnings
+BEGIN {
+	my $w = $SIG{__WARN__};
+	$SIG{__WARN__} = sub { $w };
+}
+
+### This is the ONLY module that shouldn't have strict on
+# use strict;
+
+#line 41
+
+sub new {
+    my ($class, %args) = @_;
+
+    foreach my $method ( qw(call load) ) {
+        *{"$class\::$method"} = sub {
+            shift()->_top->$method(@_);
+        } unless defined &{"$class\::$method"};
+    }
+
+    bless( \%args, $class );
+}
+
+#line 61
+
+sub AUTOLOAD {
+    my $self = shift;
+    local $@;
+    my $autoload = eval { $self->_top->autoload } or return;
+    goto &$autoload;
+}
+
+#line 76
+
+sub _top { $_[0]->{_top} }
+
+#line 89
+
+sub admin {
+    $_[0]->_top->{admin} or Module::Install::Base::FakeAdmin->new;
+}
+
+sub is_admin {
+    $_[0]->admin->VERSION;
+}
+
+sub DESTROY {}
+
+package Module::Install::Base::FakeAdmin;
+
+my $Fake;
+sub new { $Fake ||= bless(\@_, $_[0]) }
+
+sub AUTOLOAD {}
+
+sub DESTROY {}
+
+# Restore warning handler
+BEGIN {
+	$SIG{__WARN__} = $SIG{__WARN__}->();
+}
+
+1;
+
+#line 138

Added: jifty/branches/schema-plugins/inc/Module/Install/Can.pm
==============================================================================
--- (empty file)
+++ jifty/branches/schema-plugins/inc/Module/Install/Can.pm	Mon Jan 29 21:05:02 2007
@@ -0,0 +1,82 @@
+#line 1
+package Module::Install::Can;
+
+use strict;
+use Module::Install::Base;
+use Config ();
+### This adds a 5.005 Perl version dependency.
+### This is a bug and will be fixed.
+use File::Spec ();
+use ExtUtils::MakeMaker ();
+
+use vars qw{$VERSION $ISCORE @ISA};
+BEGIN {
+	$VERSION = '0.64';
+	$ISCORE  = 1;
+	@ISA     = qw{Module::Install::Base};
+}
+
+# check if we can load some module
+### Upgrade this to not have to load the module if possible
+sub can_use {
+	my ($self, $mod, $ver) = @_;
+	$mod =~ s{::|\\}{/}g;
+	$mod .= '.pm' unless $mod =~ /\.pm$/i;
+
+	my $pkg = $mod;
+	$pkg =~ s{/}{::}g;
+	$pkg =~ s{\.pm$}{}i;
+
+	local $@;
+	eval { require $mod; $pkg->VERSION($ver || 0); 1 };
+}
+
+# check if we can run some command
+sub can_run {
+	my ($self, $cmd) = @_;
+
+	my $_cmd = $cmd;
+	return $_cmd if (-x $_cmd or $_cmd = MM->maybe_command($_cmd));
+
+	for my $dir ((split /$Config::Config{path_sep}/, $ENV{PATH}), '.') {
+		my $abs = File::Spec->catfile($dir, $_[1]);
+		return $abs if (-x $abs or $abs = MM->maybe_command($abs));
+	}
+
+	return;
+}
+
+# can we locate a (the) C compiler
+sub can_cc {
+	my $self   = shift;
+	my @chunks = split(/ /, $Config::Config{cc}) or return;
+
+	# $Config{cc} may contain args; try to find out the program part
+	while (@chunks) {
+		return $self->can_run("@chunks") || (pop(@chunks), next);
+	}
+
+	return;
+}
+
+# Fix Cygwin bug on maybe_command();
+if ( $^O eq 'cygwin' ) {
+	require ExtUtils::MM_Cygwin;
+	require ExtUtils::MM_Win32;
+	if ( ! defined(&ExtUtils::MM_Cygwin::maybe_command) ) {
+		*ExtUtils::MM_Cygwin::maybe_command = sub {
+			my ($self, $file) = @_;
+			if ($file =~ m{^/cygdrive/}i and ExtUtils::MM_Win32->can('maybe_command')) {
+				ExtUtils::MM_Win32->maybe_command($file);
+			} else {
+				ExtUtils::MM_Unix->maybe_command($file);
+			}
+		}
+	}
+}
+
+1;
+
+__END__
+
+#line 157

Added: jifty/branches/schema-plugins/inc/Module/Install/Fetch.pm
==============================================================================
--- (empty file)
+++ jifty/branches/schema-plugins/inc/Module/Install/Fetch.pm	Mon Jan 29 21:05:02 2007
@@ -0,0 +1,93 @@
+#line 1
+package Module::Install::Fetch;
+
+use strict;
+use Module::Install::Base;
+
+use vars qw{$VERSION $ISCORE @ISA};
+BEGIN {
+	$VERSION = '0.64';
+	$ISCORE  = 1;
+	@ISA     = qw{Module::Install::Base};
+}
+
+sub get_file {
+    my ($self, %args) = @_;
+    my ($scheme, $host, $path, $file) = 
+        $args{url} =~ m|^(\w+)://([^/]+)(.+)/(.+)| or return;
+
+    if ( $scheme eq 'http' and ! eval { require LWP::Simple; 1 } ) {
+        $args{url} = $args{ftp_url}
+            or (warn("LWP support unavailable!\n"), return);
+        ($scheme, $host, $path, $file) = 
+            $args{url} =~ m|^(\w+)://([^/]+)(.+)/(.+)| or return;
+    }
+
+    $|++;
+    print "Fetching '$file' from $host... ";
+
+    unless (eval { require Socket; Socket::inet_aton($host) }) {
+        warn "'$host' resolve failed!\n";
+        return;
+    }
+
+    return unless $scheme eq 'ftp' or $scheme eq 'http';
+
+    require Cwd;
+    my $dir = Cwd::getcwd();
+    chdir $args{local_dir} or return if exists $args{local_dir};
+
+    if (eval { require LWP::Simple; 1 }) {
+        LWP::Simple::mirror($args{url}, $file);
+    }
+    elsif (eval { require Net::FTP; 1 }) { eval {
+        # use Net::FTP to get past firewall
+        my $ftp = Net::FTP->new($host, Passive => 1, Timeout => 600);
+        $ftp->login("anonymous", 'anonymous at example.com');
+        $ftp->cwd($path);
+        $ftp->binary;
+        $ftp->get($file) or (warn("$!\n"), return);
+        $ftp->quit;
+    } }
+    elsif (my $ftp = $self->can_run('ftp')) { eval {
+        # no Net::FTP, fallback to ftp.exe
+        require FileHandle;
+        my $fh = FileHandle->new;
+
+        local $SIG{CHLD} = 'IGNORE';
+        unless ($fh->open("|$ftp -n")) {
+            warn "Couldn't open ftp: $!\n";
+            chdir $dir; return;
+        }
+
+        my @dialog = split(/\n/, <<"END_FTP");
+open $host
+user anonymous anonymous\@example.com
+cd $path
+binary
+get $file $file
+quit
+END_FTP
+        foreach (@dialog) { $fh->print("$_\n") }
+        $fh->close;
+    } }
+    else {
+        warn "No working 'ftp' program available!\n";
+        chdir $dir; return;
+    }
+
+    unless (-f $file) {
+        warn "Fetching failed: $@\n";
+        chdir $dir; return;
+    }
+
+    return if exists $args{size} and -s $file != $args{size};
+    system($args{run}) if exists $args{run};
+    unlink($file) if $args{remove};
+
+    print(((!exists $args{check_for} or -e $args{check_for})
+        ? "done!" : "failed! ($!)"), "\n");
+    chdir $dir; return !$?;
+}
+
+1;

Added: jifty/branches/schema-plugins/inc/Module/Install/Include.pm
==============================================================================
--- (empty file)
+++ jifty/branches/schema-plugins/inc/Module/Install/Include.pm	Mon Jan 29 21:05:02 2007
@@ -0,0 +1,34 @@
+#line 1
+package Module::Install::Include;
+
+use strict;
+use Module::Install::Base;
+
+use vars qw{$VERSION $ISCORE @ISA};
+BEGIN {
+	$VERSION = '0.64';
+	$ISCORE  = 1;
+	@ISA     = qw{Module::Install::Base};
+}
+
+sub include {
+	shift()->admin->include(@_);
+}
+
+sub include_deps {
+	shift()->admin->include_deps(@_);
+}
+
+sub auto_include {
+	shift()->admin->auto_include(@_);
+}
+
+sub auto_include_deps {
+	shift()->admin->auto_include_deps(@_);
+}
+
+sub auto_include_dependent_dists {
+	shift()->admin->auto_include_dependent_dists(@_);
+}
+
+1;

Added: jifty/branches/schema-plugins/inc/Module/Install/Makefile.pm
==============================================================================
--- (empty file)
+++ jifty/branches/schema-plugins/inc/Module/Install/Makefile.pm	Mon Jan 29 21:05:02 2007
@@ -0,0 +1,208 @@
+#line 1
+package Module::Install::Makefile;
+
+use strict 'vars';
+use Module::Install::Base;
+use ExtUtils::MakeMaker ();
+
+use vars qw{$VERSION $ISCORE @ISA};
+BEGIN {
+	$VERSION = '0.64';
+	$ISCORE  = 1;
+	@ISA     = qw{Module::Install::Base};
+}
+
+sub Makefile { $_[0] }
+
+my %seen = ();
+
+sub prompt {
+    shift;
+
+    # Infinite loop protection
+    my @c = caller();
+    if ( ++$seen{"$c[1]|$c[2]|$_[0]"} > 3 ) {
+        die "Caught an potential prompt infinite loop ($c[1]|$c[2]|$_[0])";
+    }
+
+    # In automated testing, always use defaults
+    if ( $ENV{AUTOMATED_TESTING} and ! $ENV{PERL_MM_USE_DEFAULT} ) {
+        local $ENV{PERL_MM_USE_DEFAULT} = 1;
+        goto &ExtUtils::MakeMaker::prompt;
+    } else {
+        goto &ExtUtils::MakeMaker::prompt;
+    }
+}
+
+sub makemaker_args {
+    my $self = shift;
+    my $args = ($self->{makemaker_args} ||= {});
+    %$args = ( %$args, @_ ) if @_;
+    $args;
+}
+
+# For mm args that take multiple space-seperated args,
+# append an argument to the current list.
+sub makemaker_append {
+    my $self = shift;
+    my $name = shift;
+    my $args = $self->makemaker_args;
+    $args->{name} = defined $args->{$name}
+    	? join( ' ', $args->{name}, @_ )
+    	: join( ' ', @_ );
+}
+
+sub build_subdirs {
+    my $self    = shift;
+    my $subdirs = $self->makemaker_args->{DIR} ||= [];
+    for my $subdir (@_) {
+        push @$subdirs, $subdir;
+    }
+}
+
+sub clean_files {
+    my $self  = shift;
+    my $clean = $self->makemaker_args->{clean} ||= {};
+    %$clean = (
+        %$clean, 
+        FILES => join(' ', grep length, $clean->{FILES}, @_),
+    );
+}
+
+sub realclean_files {
+    my $self  = shift;
+    my $realclean = $self->makemaker_args->{realclean} ||= {};
+    %$realclean = (
+        %$realclean, 
+        FILES => join(' ', grep length, $realclean->{FILES}, @_),
+    );
+}
+
+sub libs {
+    my $self = shift;
+    my $libs = ref $_[0] ? shift : [ shift ];
+    $self->makemaker_args( LIBS => $libs );
+}
+
+sub inc {
+    my $self = shift;
+    $self->makemaker_args( INC => shift );
+}
+
+sub write {
+    my $self = shift;
+    die "&Makefile->write() takes no arguments\n" if @_;
+
+    my $args = $self->makemaker_args;
+    $args->{DISTNAME} = $self->name;
+    $args->{NAME}     = $self->module_name || $self->name || $self->determine_NAME($args);
+    $args->{VERSION}  = $self->version || $self->determine_VERSION($args);
+    $args->{NAME}     =~ s/-/::/g;
+    if ( $self->tests ) {
+        $args->{test} = { TESTS => $self->tests };
+    }
+    if ($] >= 5.005) {
+        $args->{ABSTRACT} = $self->abstract;
+        $args->{AUTHOR}   = $self->author;
+    }
+    if ( eval($ExtUtils::MakeMaker::VERSION) >= 6.10 ) {
+        $args->{NO_META} = 1;
+    }
+    if ( eval($ExtUtils::MakeMaker::VERSION) > 6.17 and $self->sign ) {
+        $args->{SIGN} = 1;
+    }
+    unless ( $self->is_admin ) {
+        delete $args->{SIGN};
+    }
+
+    # merge both kinds of requires into prereq_pm
+    my $prereq = ($args->{PREREQ_PM} ||= {});
+    %$prereq = ( %$prereq, map { @$_ } map { @$_ } grep $_,
+                 ($self->build_requires, $self->requires) );
+
+    # merge both kinds of requires into prereq_pm
+    my $subdirs = ($args->{DIR} ||= []);
+    if ($self->bundles) {
+        foreach my $bundle (@{ $self->bundles }) {
+            my ($file, $dir) = @$bundle;
+            push @$subdirs, $dir if -d $dir;
+            delete $prereq->{$file};
+        }
+    }
+
+    if ( my $perl_version = $self->perl_version ) {
+        eval "use $perl_version; 1"
+            or die "ERROR: perl: Version $] is installed, "
+                . "but we need version >= $perl_version";
+    }
+
+    my %args = map { ( $_ => $args->{$_} ) } grep {defined($args->{$_})} keys %$args;
+    if ($self->admin->preop) {
+        $args{dist} = $self->admin->preop;
+    }
+
+    my $mm = ExtUtils::MakeMaker::WriteMakefile(%args);
+    $self->fix_up_makefile($mm->{FIRST_MAKEFILE} || 'Makefile');
+}
+
+sub fix_up_makefile {
+    my $self          = shift;
+    my $makefile_name = shift;
+    my $top_class     = ref($self->_top) || '';
+    my $top_version   = $self->_top->VERSION || '';
+
+    my $preamble = $self->preamble 
+        ? "# Preamble by $top_class $top_version\n"
+            . $self->preamble
+        : '';
+    my $postamble = "# Postamble by $top_class $top_version\n"
+        . ($self->postamble || '');
+
+    local *MAKEFILE;
+    open MAKEFILE, "< $makefile_name" or die "fix_up_makefile: Couldn't open $makefile_name: $!";
+    my $makefile = do { local $/; <MAKEFILE> };
+    close MAKEFILE or die $!;
+
+    $makefile =~ s/\b(test_harness\(\$\(TEST_VERBOSE\), )/$1'inc', /;
+    $makefile =~ s/( -I\$\(INST_ARCHLIB\))/ -Iinc$1/g;
+    $makefile =~ s/( "-I\$\(INST_LIB\)")/ "-Iinc"$1/g;
+    $makefile =~ s/^(FULLPERL = .*)/$1 "-Iinc"/m;
+    $makefile =~ s/^(PERL = .*)/$1 "-Iinc"/m;
+
+    # Module::Install will never be used to build the Core Perl
+    # Sometimes PERL_LIB and PERL_ARCHLIB get written anyway, which breaks
+    # PREFIX/PERL5LIB, and thus, install_share. Blank them if they exist
+    $makefile =~ s/^PERL_LIB = .+/PERL_LIB =/m;
+    #$makefile =~ s/^PERL_ARCHLIB = .+/PERL_ARCHLIB =/m;
+
+    # Perl 5.005 mentions PERL_LIB explicitly, so we have to remove that as well.
+    $makefile =~ s/("?)-I\$\(PERL_LIB\)\1//g;
+
+    # XXX - This is currently unused; not sure if it breaks other MM-users
+    # $makefile =~ s/^pm_to_blib\s+:\s+/pm_to_blib :: /mg;
+
+    open  MAKEFILE, "> $makefile_name" or die "fix_up_makefile: Couldn't open $makefile_name: $!";
+    print MAKEFILE  "$preamble$makefile$postamble" or die $!;
+    close MAKEFILE  or die $!;
+
+    1;
+}
+
+sub preamble {
+    my ($self, $text) = @_;
+    $self->{preamble} = $text . $self->{preamble} if defined $text;
+    $self->{preamble};
+}
+
+sub postamble {
+    my ($self, $text) = @_;
+    $self->{postamble} ||= $self->admin->postamble;
+    $self->{postamble} .= $text if defined $text;
+    $self->{postamble}
+}
+
+1;
+
+__END__
+
+#line 334

Added: jifty/branches/schema-plugins/inc/Module/Install/Metadata.pm
==============================================================================
--- (empty file)
+++ jifty/branches/schema-plugins/inc/Module/Install/Metadata.pm	Mon Jan 29 21:05:02 2007
@@ -0,0 +1,315 @@
+#line 1
+package Module::Install::Metadata;
+
+use strict 'vars';
+use Module::Install::Base;
+
+use vars qw{$VERSION $ISCORE @ISA};
+BEGIN {
+	$VERSION = '0.64';
+	$ISCORE  = 1;
+	@ISA     = qw{Module::Install::Base};
+}
+
+my @scalar_keys = qw{
+    name module_name abstract author version license
+    distribution_type perl_version tests
+};
+
+my @tuple_keys = qw{
+    build_requires requires recommends bundles
+};
+
+sub Meta            { shift        }
+sub Meta_ScalarKeys { @scalar_keys }
+sub Meta_TupleKeys  { @tuple_keys  }
+
+foreach my $key (@scalar_keys) {
+    *$key = sub {
+        my $self = shift;
+        return $self->{values}{$key} if defined wantarray and !@_;
+        $self->{values}{$key} = shift;
+        return $self;
+    };
+}
+
+foreach my $key (@tuple_keys) {
+    *$key = sub {
+        my $self = shift;
+        return $self->{values}{$key} unless @_;
+
+        my @rv;
+        while (@_) {
+            my $module = shift or last;
+            my $version = shift || 0;
+            if ( $module eq 'perl' ) {
+                $version =~ s{^(\d+)\.(\d+)\.(\d+)}
+                             {$1 + $2/1_000 + $3/1_000_000}e;
+                $self->perl_version($version);
+                next;
+            }
+            my $rv = [ $module, $version ];
+            push @rv, $rv;
+        }
+        push @{ $self->{values}{$key} }, @rv;
+        @rv;
+    };
+}
+
+sub sign {
+    my $self = shift;
+    return $self->{'values'}{'sign'} if defined wantarray and !@_;
+    $self->{'values'}{'sign'} = ( @_ ? $_[0] : 1 );
+    return $self;
+}
+
+sub dynamic_config {
+	my $self = shift;
+	unless ( @_ ) {
+		warn "You MUST provide an explicit true/false value to dynamic_config, skipping\n";
+		return $self;
+	}
+	$self->{'values'}{'dynamic_config'} = $_[0] ? 1 : 0;
+	return $self;
+}
+
+sub all_from {
+    my ( $self, $file ) = @_;
+
+    unless ( defined($file) ) {
+        my $name = $self->name
+            or die "all_from called with no args without setting name() first";
+        $file = join('/', 'lib', split(/-/, $name)) . '.pm';
+        $file =~ s{.*/}{} unless -e $file;
+        die "all_from: cannot find $file from $name" unless -e $file;
+    }
+
+    $self->version_from($file)      unless $self->version;
+    $self->perl_version_from($file) unless $self->perl_version;
+
+    # The remaining probes read from POD sections; if the file
+    # has an accompanying .pod, use that instead
+    my $pod = $file;
+    if ( $pod =~ s/\.pm$/.pod/i and -e $pod ) {
+        $file = $pod;
+    }
+
+    $self->author_from($file)   unless $self->author;
+    $self->license_from($file)  unless $self->license;
+    $self->abstract_from($file) unless $self->abstract;
+}
+
+sub provides {
+    my $self     = shift;
+    my $provides = ( $self->{values}{provides} ||= {} );
+    %$provides = (%$provides, @_) if @_;
+    return $provides;
+}
+
+sub auto_provides {
+    my $self = shift;
+    return $self unless $self->is_admin;
+
+    unless (-e 'MANIFEST') {
+        warn "Cannot deduce auto_provides without a MANIFEST, skipping\n";
+        return $self;
+    }
+
+    # Avoid spurious warnings as we are not checking manifest here.
+
+    local $SIG{__WARN__} = sub {1};
+    require ExtUtils::Manifest;
+    local *ExtUtils::Manifest::manicheck = sub { return };
+
+    require Module::Build;
+    my $build = Module::Build->new(
+        dist_name    => $self->name,
+        dist_version => $self->version,
+        license      => $self->license,
+    );
+    $self->provides(%{ $build->find_dist_packages || {} });
+}
+
+sub feature {
+    my $self     = shift;
+    my $name     = shift;
+    my $features = ( $self->{values}{features} ||= [] );
+
+    my $mods;
+
+    if ( @_ == 1 and ref( $_[0] ) ) {
+        # The user used ->feature like ->features by passing in the second
+        # argument as a reference.  Accomodate for that.
+        $mods = $_[0];
+    } else {
+        $mods = \@_;
+    }
+
+    my $count = 0;
+    push @$features, (
+        $name => [
+            map {
+                ref($_) ? ( ref($_) eq 'HASH' ) ? %$_
+                                                : @$_
+                        : $_
+            } @$mods
+        ]
+    );
+
+    return @$features;
+}
+
+sub features {
+    my $self = shift;
+    while ( my ( $name, $mods ) = splice( @_, 0, 2 ) ) {
+        $self->feature( $name, @$mods );
+    }
+    return $self->{values}->{features}
+    	? @{ $self->{values}->{features} }
+    	: ();
+}
+
+sub no_index {
+    my $self = shift;
+    my $type = shift;
+    push @{ $self->{values}{no_index}{$type} }, @_ if $type;
+    return $self->{values}{no_index};
+}
+
+sub read {
+    my $self = shift;
+    $self->include_deps( 'YAML', 0 );
+
+    require YAML;
+    my $data = YAML::LoadFile('META.yml');
+
+    # Call methods explicitly in case user has already set some values.
+    while ( my ( $key, $value ) = each %$data ) {
+        next unless $self->can($key);
+        if ( ref $value eq 'HASH' ) {
+            while ( my ( $module, $version ) = each %$value ) {
+                $self->can($key)->($self, $module => $version );
+            }
+        }
+        else {
+            $self->can($key)->($self, $value);
+        }
+    }
+    return $self;
+}
+
+sub write {
+    my $self = shift;
+    return $self unless $self->is_admin;
+    $self->admin->write_meta;
+    return $self;
+}
+
+sub version_from {
+    my ( $self, $file ) = @_;
+    require ExtUtils::MM_Unix;
+    $self->version( ExtUtils::MM_Unix->parse_version($file) );
+}
+
+sub abstract_from {
+    my ( $self, $file ) = @_;
+    require ExtUtils::MM_Unix;
+    $self->abstract(
+        bless(
+            { DISTNAME => $self->name },
+            'ExtUtils::MM_Unix'
+        )->parse_abstract($file)
+     );
+}
+
+sub _slurp {
+    my ( $self, $file ) = @_;
+
+    local *FH;
+    open FH, "< $file" or die "Cannot open $file.pod: $!";
+    do { local $/; <FH> };
+}
+
+sub perl_version_from {
+    my ( $self, $file ) = @_;
+
+    if (
+        $self->_slurp($file) =~ m/
+        ^
+        use \s*
+        v?
+        ([\d_\.]+)
+        \s* ;
+    /ixms
+      )
+    {
+        my $v = $1;
+        $v =~ s{_}{}g;
+        $self->perl_version($1);
+    }
+    else {
+        warn "Cannot determine perl version info from $file\n";
+        return;
+    }
+}
+
+sub author_from {
+    my ( $self, $file ) = @_;
+    my $content = $self->_slurp($file);
+    if ($content =~ m/
+        =head \d \s+ (?:authors?)\b \s*
+        ([^\n]*)
+        |
+        =head \d \s+ (?:licen[cs]e|licensing|copyright|legal)\b \s*
+        .*? copyright .*? \d\d\d[\d.]+ \s* (?:\bby\b)? \s*
+        ([^\n]*)
+    /ixms) {
+        my $author = $1 || $2;
+        $author =~ s{E<lt>}{<}g;
+        $author =~ s{E<gt>}{>}g;
+        $self->author($author); 
+    }
+    else {
+        warn "Cannot determine author info from $file\n";
+    }
+}
+
+sub license_from {
+    my ( $self, $file ) = @_;
+
+    if (
+        $self->_slurp($file) =~ m/
+        =head \d \s+
+        (?:licen[cs]e|licensing|copyright|legal)\b
+        (.*?)
+        (=head\\d.*|=cut.*|)
+        \z
+    /ixms
+      )
+    {
+        my $license_text = $1;
+        my @phrases      = (
+            'under the same (?:terms|license) as perl itself' => 'perl',
+            'GNU public license'                              => 'gpl',
+            'GNU lesser public license'                       => 'gpl',
+            'BSD license'                                     => 'bsd',
+            'Artistic license'                                => 'artistic',
+            'GPL'                                             => 'gpl',
+            'LGPL'                                            => 'lgpl',
+            'BSD'                                             => 'bsd',
+            'Artistic'                                        => 'artistic',
+        );
+        while ( my ( $pattern, $license ) = splice( @phrases, 0, 2 ) ) {
+            $pattern =~ s{\s+}{\\s+}g;
+            if ( $license_text =~ /\b$pattern\b/i ) {
+                $self->license($license);
+                return 1;
+            }
+        }
+    }
+
+    warn "Cannot determine license info from $file\n";
+    return 'unknown';
+}
+
+1;

Added: jifty/branches/schema-plugins/inc/Module/Install/Scripts.pm
==============================================================================
--- (empty file)
+++ jifty/branches/schema-plugins/inc/Module/Install/Scripts.pm	Mon Jan 29 21:05:02 2007
@@ -0,0 +1,50 @@
+#line 1
+package Module::Install::Scripts;
+
+use strict;
+use Module::Install::Base;
+use File::Basename ();
+
+use vars qw{$VERSION $ISCORE @ISA};
+BEGIN {
+	$VERSION = '0.64';
+	$ISCORE  = 1;
+	@ISA     = qw{Module::Install::Base};
+}
+
+sub prompt_script {
+    my ($self, $script_file) = @_;
+
+    my ($prompt, $abstract, $default);
+    foreach my $line ( $self->_read_script($script_file) ) {
+        last unless $line =~ /^#/;
+        $prompt = $1   if $line =~ /^#\s*prompt:\s+(.*)/;
+        $default = $1  if $line =~ /^#\s*default:\s+(.*)/;
+        $abstract = $1 if $line =~ /^#\s*abstract:\s+(.*)/;
+    }
+    unless (defined $prompt) {
+        my $script_name = File::Basename::basename($script_file);
+        $prompt = "Do you want to install '$script_name'";
+        $prompt .= " ($abstract)" if defined $abstract;
+        $prompt .= '?';
+    }
+    return unless $self->prompt($prompt, ($default || 'n')) =~ /^[Yy]/;
+    $self->install_script($script_file);
+}
+
+sub install_script {
+    my $self = shift;
+    my $args = $self->makemaker_args;
+    my $exe_files = $args->{EXE_FILES} ||= [];
+    push @$exe_files, @_;
+}
+
+sub _read_script {
+    my ($self, $script_file) = @_;
+    local *SCRIPT;
+    open SCRIPT, $script_file
+      or die "Can't open '$script_file' for input: $!\n";
+    return <SCRIPT>;
+}
+
+1;

Added: jifty/branches/schema-plugins/inc/Module/Install/Share.pm
==============================================================================
--- (empty file)
+++ jifty/branches/schema-plugins/inc/Module/Install/Share.pm	Mon Jan 29 21:05:02 2007
@@ -0,0 +1,40 @@
+#line 1
+package Module::Install::Share;
+
+use strict;
+use Module::Install::Base;
+
+use vars qw{$VERSION $ISCORE @ISA};
+BEGIN {
+	$VERSION = '0.64';
+	$ISCORE  = 1;
+	@ISA     = qw{Module::Install::Base};
+}
+
+sub install_share {
+	my ($self, $dir) = @_;
+
+	if ( ! defined $dir ) {
+		die "Cannot find the 'share' directory" unless -d 'share';
+		$dir = 'share';
+	}
+
+	$self->postamble(<<"END_MAKEFILE");
+config ::
+\t\$(NOECHO) \$(MOD_INSTALL) \\
+\t\t\"$dir\" \$(INST_AUTODIR)
+
+END_MAKEFILE
+
+	# The above appears to behave incorrectly when used with old versions
+	# of ExtUtils::Install (known-bad on RHEL 3, with 5.8.0)
+	# So when we need to install a share directory, make sure we add a
+	# dependency on a moderately new version of ExtUtils::MakeMaker.
+	$self->build_requires( 'ExtUtils::MakeMaker' => '6.11' );
+}
+
+1;
+
+__END__
+
+#line 98

Added: jifty/branches/schema-plugins/inc/Module/Install/Win32.pm
==============================================================================
--- (empty file)
+++ jifty/branches/schema-plugins/inc/Module/Install/Win32.pm	Mon Jan 29 21:05:02 2007
@@ -0,0 +1,65 @@
+#line 1
+package Module::Install::Win32;
+
+use strict;
+use Module::Install::Base;
+
+use vars qw{$VERSION $ISCORE @ISA};
+BEGIN {
+	$VERSION = '0.64';
+	$ISCORE  = 1;
+	@ISA     = qw{Module::Install::Base};
+}
+
+# determine if the user needs nmake, and download it if needed
+sub check_nmake {
+	my $self = shift;
+	$self->load('can_run');
+	$self->load('get_file');
+	
+	require Config;
+	return unless (
+		$^O eq 'MSWin32'                     and
+		$Config::Config{make}                and
+		$Config::Config{make} =~ /^nmake\b/i and
+		! $self->can_run('nmake')
+	);
+
+	print "The required 'nmake' executable not found, fetching it...\n";
+
+	require File::Basename;
+	my $rv = $self->get_file(
+		url       => 'http://download.microsoft.com/download/vc15/Patch/1.52/W95/EN-US/Nmake15.exe',
+		ftp_url   => 'ftp://ftp.microsoft.com/Softlib/MSLFILES/Nmake15.exe',
+		local_dir => File::Basename::dirname($^X),
+		size      => 51928,
+		run       => 'Nmake15.exe /o > nul',
+		check_for => 'Nmake.exe',
+		remove    => 1,
+	);
+
+	if (!$rv) {
+        die <<'END_MESSAGE';
+
+-------------------------------------------------------------------------------
+
+Since you are using Microsoft Windows, you will need the 'nmake' utility
+before installation. It's available at:
+
+  http://download.microsoft.com/download/vc15/Patch/1.52/W95/EN-US/Nmake15.exe
+      or
+  ftp://ftp.microsoft.com/Softlib/MSLFILES/Nmake15.exe
+
+Please download the file manually, save it to a directory in %PATH% (e.g.
+C:\WINDOWS\COMMAND\), then launch the MS-DOS command line shell, "cd" to
+that directory, and run "Nmake15.exe" from there; that will create the
+'nmake.exe' file needed by this module.
+
+You may then resume the installation process described in README.
+
+-------------------------------------------------------------------------------
+END_MESSAGE
+	}
+}
+
+1;

Added: jifty/branches/schema-plugins/inc/Module/Install/WriteAll.pm
==============================================================================
--- (empty file)
+++ jifty/branches/schema-plugins/inc/Module/Install/WriteAll.pm	Mon Jan 29 21:05:02 2007
@@ -0,0 +1,43 @@
+#line 1
+package Module::Install::WriteAll;
+
+use strict;
+use Module::Install::Base;
+
+use vars qw{$VERSION $ISCORE @ISA};
+BEGIN {
+	$VERSION = '0.64';
+	$ISCORE  = 1;
+	@ISA     = qw{Module::Install::Base};
+}
+
+sub WriteAll {
+    my $self = shift;
+    my %args = (
+        meta        => 1,
+        sign        => 0,
+        inline      => 0,
+        check_nmake => 1,
+        @_
+    );
+
+    $self->sign(1)                if $args{sign};
+    $self->Meta->write            if $args{meta};
+    $self->admin->WriteAll(%args) if $self->is_admin;
+
+    if ( $0 =~ /Build.PL$/i ) {
+        $self->Build->write;
+    } else {
+        $self->check_nmake if $args{check_nmake};
+        unless ( $self->makemaker_args->{'PL_FILES'} ) {
+        	$self->makemaker_args( PL_FILES => {} );
+        }
+        if ($args{inline}) {
+            $self->Inline->write;
+        } else {
+            $self->Makefile->write;
+        }
+    }
+}
+
+1;

Added: jifty/branches/schema-plugins/lib/Email/Send/Jifty/Test.pm
==============================================================================
--- (empty file)
+++ jifty/branches/schema-plugins/lib/Email/Send/Jifty/Test.pm	Mon Jan 29 21:05:02 2007
@@ -0,0 +1,16 @@
+package Email::Send::Jifty::Test;
+require Jifty::Test;
+use strict;
+use warnings;
+
+=head1 WHY?
+
+Because L<Email::Send> 1.99_01 requires senders to be in this namespace.
+
+=cut
+
+*is_available = \&Jifty::Test::is_available;
+*send = \&Jifty::Test::send;
+
+1;
+

Added: jifty/branches/schema-plugins/lib/Jifty.pm
==============================================================================
--- (empty file)
+++ jifty/branches/schema-plugins/lib/Jifty.pm	Mon Jan 29 21:05:02 2007
@@ -0,0 +1,398 @@
+use warnings;
+use strict;
+
+package Jifty;
+use IPC::PubSub 0.22;
+use Data::UUID;
+use encoding 'utf8';
+# Work around the fact that Time::Local caches thing on first require
+BEGIN { local $ENV{'TZ'} = "GMT";  require Time::Local;}
+$Jifty::VERSION = '0.70117';
+
+=head1 NAME
+
+Jifty - an application framework
+
+=head1 DESCRIPTION
+
+Yet another web framework.
+
+=head2 What's cool about Jifty? (Buzzwords)
+
+=over 4
+
+=item DRY (Don't Repeat Yourself)
+
+Jifty tries not to make you say things more than once.
+
+=item Full-stack
+
+Out of the proverbial box, Jifty comes with one way to do everything
+you should need to do: One database mapper, one templating system, one
+web services layer, one AJAX toolkit, one set of handlers for
+standalone or FastCGI servers. We work hard to make all the bits play
+well together, so you don't have to.
+
+=item Continuations
+
+With Jifty, it's easy to let the user go off and do something else,
+like fill out a wizard, look something up in the help system or go
+twiddle their preferences and come right back to where they were.
+
+=item Form-based dispatch
+
+This is one of the things that Jifty does that we've not seen anywhere
+else. Jifty owns your form rendering and processing. This means you
+never need to write form handling logic. All you say is "I want an
+input for this argument here" and Jifty takes care of the rest. (Even
+autocomplete and validation)
+
+=item A Pony
+
+Jifty is the only web application framework that comes with a pony.
+
+=back
+
+=head2 Introduction
+
+If this is your first time using Jifty, L<Jifty::Manual::Tutorial> is
+probably a better place to start.
+
+=cut
+
+
+use base qw/Jifty::Object/;
+use Jifty::Everything;
+
+use vars qw/$HANDLE $CONFIG $LOGGER $HANDLER $API $CLASS_LOADER $PUB_SUB @PLUGINS/;
+
+=head1 METHODS
+
+=head2 new PARAMHASH
+
+This class method instantiates a new C<Jifty> object. This object
+deals with configuration files, logging and database handles for the
+system.  Before this method returns, it calls the application's C<start>
+method (i.e. C<MyApp-E<gt>start>) to handle any application-specific startup.
+
+Most of the time, the server will call this for you to set up
+your C<Jifty> object.  If you are writing command-line programs that
+want to use your libraries (as opposed to web services) you will need
+to call this yourself.
+
+See L<Jifty::Config> for details on how to configure your Jifty
+application.
+
+=head3 Arguments
+
+=over
+
+=item no_handle
+
+If this is set to true, Jifty will not create a L<Jifty::Handle> and
+connect to a database.  Only use this if you're about to drop the
+database or do something extreme like that; most of Jifty expects the
+handle to exist.  Defaults to false.
+
+=item logger_component
+
+The name that Jifty::Logger will log under.  If you don't specify anything
+Jifty::Logger will log under the empty string.  See L<Jifty::Logger> for
+more infomation.
+
+=back
+
+=cut
+
+sub new {
+    my $ignored_class = shift;
+
+    my %args = (
+        no_handle        => 0,
+        logger_component => undef,
+        @_
+    );
+
+    # Load the configuration. stash it in ->config
+    Jifty->config( Jifty::Config->new() );
+
+
+    # Now that we've loaded the configuration, we can remove the temporary 
+    # Jifty::DBI::Record baseclass for records and insert our "real" baseclass,
+    # which is likely Record::Cachable or Record::Memcached
+    @Jifty::Record::ISA = grep { $_ ne 'Jifty::DBI::Record' } @Jifty::Record::ISA;
+
+    my $record_base_class = Jifty->config->framework('Database')->{'RecordBaseClass'};
+    Jifty::Util->require( $record_base_class );
+    push @Jifty::Record::ISA, $record_base_class unless $record_base_class eq 'Jifty::Record';
+
+    Jifty->logger( Jifty::Logger->new( $args{'logger_component'} ) );
+
+    # Set up plugins
+    my @plugins;
+    for my $plugin (@{Jifty->config->framework('Plugins')}) {
+        my $class = "Jifty::Plugin::".(keys %{$plugin})[0];
+        my %options = %{ $plugin->{(keys %{$plugin})[0]} };
+        Jifty::Util->require($class);
+        Jifty::ClassLoader->new(base => $class)->require;
+        push @plugins, $class->new(%options);
+    }
+
+    Jifty->plugins(@plugins);
+
+    # Now that we have the config set up and loaded plugins,
+    # load the localization files.
+    Jifty::I18N->refresh();
+    
+    # Get a classloader set up
+    my $class_loader = Jifty::ClassLoader->new(
+        base => Jifty->app_class,
+    );
+
+    Jifty->class_loader($class_loader);
+    $class_loader->require;
+
+    Jifty->handler(Jifty::Handler->new());
+    Jifty->api(Jifty::API->new());
+
+    # Let's get the database rocking and rolling
+    Jifty->setup_database_connection(%args);
+
+    # Call the application's start method to let it do anything
+    # application specific for startup
+    my $app = Jifty->app_class;
+    
+    $app->start()
+        if $app->can('start');
+    
+}
+
+=head2 config
+
+An accessor for the L<Jifty::Config> object that stores the
+configuration for the Jifty application.
+
+=cut
+
+sub config {
+    my $class = shift;
+    $CONFIG = shift if (@_);
+    return $CONFIG;
+}
+
+=head2 logger
+
+An accessor for our L<Jifty::Logger> object for the application.
+
+=cut
+
+sub logger {
+    my $class = shift;
+    $LOGGER = shift if (@_);
+    return $LOGGER;
+}
+
+=head2 handler
+
+An accessor for our L<Jifty::Handler> object.
+
+=cut
+
+sub handler {
+    my $class = shift;
+    $HANDLER = shift if (@_);
+    return $HANDLER;
+}
+
+=head2 handle
+
+An accessor for the L<Jifty::Handle> object that stores the database
+handle for the application.
+
+=cut
+
+sub handle {
+    my $class = shift;
+    $HANDLE = shift if (@_);
+    return $HANDLE;
+}
+
+=head2 api
+
+An accessor for the L<Jifty::API> object that publishes and controls
+information about the application's L<Jifty::Action>s.
+
+=cut
+
+sub api {
+    my $class = shift;
+    $API = shift if (@_);
+    return $API;
+}
+
+=head2 app_class(@names)
+
+Return Class in application space.  For example C<app_class('Model', 'Foo')>
+returns YourApp::Model::Foo.
+
+=cut
+
+sub app_class {
+    shift;
+    join('::', Jifty->config->framework('ApplicationClass'), @_);
+}
+
+=head2 web
+
+An accessor for the L<Jifty::Web> object that the web interface uses. 
+
+=cut
+
+sub web {
+    $HTML::Mason::Commands::JiftyWeb ||= Jifty::Web->new();
+    return $HTML::Mason::Commands::JiftyWeb;
+}
+
+=head2 subs
+
+An accessor for the L<Jifty::Subs> object that the subscription uses. 
+
+=cut
+
+sub subs {
+    return Jifty::Subs->new;
+}
+
+=head2 bus
+
+Returns an IPC::PubSub object for the current application.
+
+=cut
+
+sub bus {
+
+    unless ($PUB_SUB) {
+        my @args;
+
+        my $backend = Jifty->config->framework('PubSub')->{'Backend'};
+        if ( $backend eq 'Memcached' ) {
+            require IO::Socket::INET;
+
+            # If there's a running memcached on the default port. this should become configurable
+            if ( IO::Socket::INET->new('127.0.0.1:11211') ) {
+                @args = ( Jifty->app_instance_id );
+            } else {
+                $backend = 'JiftyDBI';
+            }
+        } 
+        
+        if ($backend eq 'JiftyDBI' ) {
+                @args    = (
+                    db_config    => Jifty->handle->{db_config},
+                    table_prefix => '_jifty_pubsub_',
+                );
+            }
+        $PUB_SUB = IPC::PubSub->new( $backend => @args );
+
+    }
+    return $PUB_SUB;
+}
+
+=head2 plugins
+
+Returns a list of L<Jifty::Plugin> objects for this Jifty application.
+
+=cut
+
+sub plugins {
+    my $class = shift;
+    @PLUGINS = @_ if @_;
+    return @PLUGINS;
+}
+
+=head2 class_loader
+
+An accessor for the L<Jifty::ClassLoader> object that stores the loaded
+classes for the application.
+
+=cut
+
+sub class_loader {
+    my $class = shift;
+    $CLASS_LOADER = shift if (@_);
+    return $CLASS_LOADER;
+}
+
+=head2 setup_database_connection
+
+Set up our database connection. Optionally takes a param hash with a
+single argument.  This method is automatically called by L</new>.
+
+=over
+
+=item no_handle
+
+Defaults to false. If true, Jifty won't try to set up a database handle
+
+=back
+
+
+If C<no_handle> is set or our application's config file is missing a C<Database> configuration
+ section or I<has> a C<SkipDatabase: 1> directive in its framework configuration, does nothing.
+
+=cut
+
+sub setup_database_connection {
+    my $self = shift;
+    my %args = (no_handle =>0,
+                @_);
+    unless ( $args{'no_handle'}
+        or Jifty->config->framework('SkipDatabase')
+        or not Jifty->config->framework('Database') )
+    {
+
+        my $handle_class = Jifty->app_class("Handle");
+        Jifty::Util->require( $handle_class );
+        Jifty->handle( $handle_class->new );
+        Jifty->handle->connect();
+        Jifty->handle->check_schema_version();
+    }
+}
+
+
+=head2 app_instance_id
+
+Returns a globally unique id for this instance of this jifty 
+application. This value is generated the first time it's accessed
+
+=cut
+
+sub app_instance_id {
+    my $self = shift;
+    my $app_instance_id = Jifty::Model::Metadata->load("application_instance_uuid");
+    unless ($app_instance_id) {
+        require Data::UUID;
+        $app_instance_id = Data::UUID->new->create_str();
+        Jifty::Model::Metadata->store(application_instance_uuid => $app_instance_id );
+    }
+    return $app_instance_id;
+}
+
+
+=head1 LICENSE
+
+Jifty is Copyright 2005-2006 Best Practical Solutions, LLC.
+Jifty is distributed under the same terms as Perl itself.
+
+=head1 SEE ALSO
+
+L<http://jifty.org>
+
+=head1 AUTHORS
+
+Jesse Vincent, Alex Vandiver and David Glasser.
+
+
+=cut
+
+1;

Added: jifty/branches/schema-plugins/lib/Jifty/API.pm
==============================================================================
--- (empty file)
+++ jifty/branches/schema-plugins/lib/Jifty/API.pm	Mon Jan 29 21:05:02 2007
@@ -0,0 +1,225 @@
+use warnings;
+use strict;
+
+package Jifty::API;
+
+=head1 NAME
+
+Jifty::API - Manages and allow reflection on the Jifty::Actions that
+make up a Jifty application's API
+
+=cut
+
+
+use base qw/Class::Accessor::Fast Jifty::Object/;
+
+
+__PACKAGE__->mk_accessors(qw(action_limits));
+
+=head1 METHODS
+
+=head2 new
+
+Creates a new C<Jifty::API> object
+
+=cut
+
+sub new {
+    my $class = shift;
+    my $self  = bless {}, $class;
+
+    $self->reset;
+
+    Jifty::Module::Pluggable->import(
+        search_path => [
+            Jifty->app_class("Action"),
+            "Jifty::Action",
+            map {ref($_)."::Action"} Jifty->plugins,
+        ],
+        except   => qr/\.#/,
+        sub_name => "_actions",
+    );
+
+    return ($self);
+}
+
+=head2 qualify ACTIONNAME
+
+Returns the fully qualified package name for the given provided
+action.  If the C<ACTIONNAME> starts with C<Jifty::> or
+C<ApplicationClass>::Action, simply returns the given name; otherwise,
+it prefixes it with the C<ApplicationClass>::Action.
+
+=cut
+
+sub qualify {
+    my $self   = shift;
+    my $action = shift;
+
+    my $base_path = Jifty->app_class("Action");
+
+    return $action
+        if $action =~ /^Jifty::/
+        or $action =~ /^\Q$base_path\E/;
+
+    return $base_path . "::" . $action;
+}
+
+=head2 reset
+
+Resets which actions are allowed to the defaults; that is, all of the
+application's actions, L<Jifty::Action::Autocomplete>, and
+L<Jifty::Action::Redirect> are allowed; everything else is denied.
+See L</restrict> for the details of how limits are processed.
+
+=cut
+
+sub reset {
+    my $self = shift;
+
+    # Set up defaults
+    my $app_actions = Jifty->app_class("Action");
+
+    $self->action_limits(
+        [   { deny => 1, restriction => qr/.*/ },
+            {   allow       => 1,
+                restriction => qr/^\Q$app_actions\E/,
+            },
+            { allow => 1, restriction => 'Jifty::Action::Autocomplete' },
+            { allow => 1, restriction => 'Jifty::Action::Redirect' },
+        ]
+    );
+}
+
+=head2 allow RESTRICTIONS
+
+Takes a list of strings or regular expressions, and adds them in order
+to the list of limits for the purposes of L</is_allowed>.  See
+L</restrict> for the details of how limits are processed.
+
+=cut
+
+sub allow {
+    my $self = shift;
+    $self->restrict( allow => @_ );
+}
+
+=head2 deny RESTRICTIONS
+
+Takes a list of strings or regular expressions, and adds them in order
+to the list of limits for the purposes of L</is_allowed>.  See
+L</restrict> for the details of how limits are processed.
+
+=cut
+
+sub deny {
+    my $self = shift;
+    $self->restrict( deny => @_ );
+}
+
+=head2 restrict POLARITY RESTRICTIONS
+
+Method that L</allow> and L</deny> call internally; I<POLARITY> is
+either C<allow> or C<deny>.  Allow and deny limits are evaluated in
+the order they're called.  The last limit that applies will be the one
+which takes effect.  Regexes are matched against the class; strings
+are fully L</qualify|qualified> and used as an exact match against the
+class name.  The base set of restrictions (which is reset every
+request) is set in L</reset>, and usually modified by the
+application's L<Jifty::Dispatcher> if need be.
+
+If you call:
+
+    Jifty->api->deny  ( qr'Foo' );
+    Jifty->api->allow ( qr'FooBar' );
+    Jifty->api->deny  ( qr'FooBarDeleteTheWorld' );
+
+..then:
+
+    calls to MyApp::Action::Baz will succeed.
+    calls to MyApp::Action::Foo will fail.
+    calls to MyApp::Action::FooBar will pass.
+    calls to MyApp::Action::TrueFoo will fail.
+    calls to MyApp::Action::TrueFooBar will pass.
+    calls to MyApp::Action::TrueFooBarDeleteTheWorld will fail.
+    calls to MyApp::Action::FooBarDeleteTheWorld will fail.
+
+=cut
+
+sub restrict {
+    my $self         = shift;
+    my $polarity     = shift;
+    my @restrictions = @_;
+
+    die "Polarity must be 'allow' or 'deny'"
+        unless $polarity eq "allow"
+        or $polarity     eq "deny";
+
+    for my $restriction (@restrictions) {
+
+        # Don't let the user "allow .*"
+        die "For security reasons, Jifty won't let you allow all actions"
+            if $polarity eq "allow"
+            and ref $restriction
+            and $restriction =~ /^\(\?[-xism]*:\^?\.\*\$?\)$/;
+
+        # Fully qualify it if it's a string
+        $restriction = $self->qualify($restriction)
+            unless ref $restriction;
+
+        # Add to list of restrictions
+        push @{ $self->action_limits },
+            { $polarity => 1, restriction => $restriction };
+    }
+}
+
+=head2 is_allowed CLASS
+
+Returns false if the I<CLASS> name (which is fully qualified if it is
+not already) is allowed to be executed.  See L</restrict> above for
+the rules that the class name must pass.
+
+=cut
+
+sub is_allowed {
+    my $self  = shift;
+    my $class = shift;
+
+    # Qualify the action
+    $class = $self->qualify($class);
+
+    # Assume that it doesn't pass; however, the real fallbacks are
+    # controlled by L</reset>, above.
+    my $allow = 0;
+
+    # Walk all of the limits
+    for my $limit ( @{ $self->action_limits } ) {
+
+        # Regexes are =~ matches, strigns are eq matches
+        if ( ( ref $limit->{restriction} and $class =~ $limit->{restriction} )
+            or ( $class eq $limit->{restriction} ) )
+        {
+
+            # If the restriction passes, set the current allow/deny
+            # bit according to if this was a positive or negative
+            # limit
+            $allow = $limit->{allow} ? 1 : 0;
+        }
+    }
+    return $allow;
+}
+
+=head2 actions
+
+Lists the class names of all of the allowed actions for this Jifty
+application; this may include actions under the C<Jifty::Action::>
+namespace, in addition to your application's actions.
+
+=cut
+
+sub actions {
+    my $self = shift;
+    return sort grep { $self->is_allowed($_) } $self->_actions;
+}
+
+1;

Added: jifty/branches/schema-plugins/lib/Jifty/Action.pm
==============================================================================
--- (empty file)
+++ jifty/branches/schema-plugins/lib/Jifty/Action.pm	Mon Jan 29 21:05:02 2007
@@ -0,0 +1,1115 @@
+use warnings;
+use strict;
+
+package Jifty::Action;
+
+=head1 NAME
+
+Jifty::Action - The ability to Do Things in the framework
+
+=head1 SYNOPSIS
+
+    package MyApp::Action::Foo;
+    use Jifty::Param::Schema;
+    use Jifty::Action schema {
+
+    param bar =>
+        type is 'checkbox',
+        label is 'Want Bar?',
+        hints is 'Bar is this cool thing that you really want.',
+        default is 0;
+
+    };
+  
+    sub take_action {
+        ...
+    }
+  
+  1;
+
+=head1 DESCRIPTION
+
+C<Jifty::Action> is the superclass for all actions in Jifty.
+Action classes form the meat of the L<Jifty> framework; they
+control how form elements interact with the underlying model.
+
+See also L<Jifty::Action::Record> for data-oriented actions, 
+L<Jifty::Result> for how to return values from actions.
+
+See L<Jifty::Param::Schema> for more details on the declarative 
+syntax.
+
+See L<Jifty::Manual::Actions> for examples of using actions.
+
+=cut
+
+
+use base qw/Jifty::Object Class::Accessor::Fast Class::Data::Inheritable/;
+
+__PACKAGE__->mk_accessors(qw(moniker argument_values values_from_request order result sticky_on_success sticky_on_failure));
+__PACKAGE__->mk_classdata(qw/PARAMS/);
+
+=head1 COMMON METHODS
+
+These common methods are designed to 
+
+=head2 new 
+
+Construct a new action.  Subclasses who need do custom initialization
+should start with:
+
+    my $class = shift; my $self = $class->SUPER::new(@_)
+
+B<Do not call this yourself>; always go through C<<
+Jifty->web->new_action >>!  The arguments that this will be
+called with include:
+
+=over
+
+=item moniker
+
+The L<moniker|Jifty::Manual::Glossary/moniker> of the action.  Defaults to an
+autogenerated moniker.
+
+=item order
+
+An integer that determines the ordering of the action's execution.
+Lower numbers occur before higher numbers.  Defaults to 0.
+
+=item arguments
+
+A hash reference of default values for the
+L<arguments|Jifty::Manual::Glossary/argument> of the action.  Defaults to
+none.
+
+=item sticky_on_failure
+
+A boolean value that determines if the form fields are
+L<sticky|Jifty::Manual::Glossary/sticky> when the action fails.  Defaults to
+true.
+
+=item sticky_on_success
+
+A boolean value that determines if the form fields are
+L<sticky|Jifty::Manual::Glossary/sticky> when the action succeeds.  Defaults
+to false.
+
+=begin private
+
+=item request_arguments
+
+A hashref of arguments passed in as part of the
+L<Jifty::Request>. Internal use only.
+
+=end private
+
+=back
+
+=cut
+
+sub new {
+    my $class = shift;
+    my $self = bless {}, $class;
+    my %args = (
+        order      => undef,
+        arguments  => {},
+        request_arguments => {},
+        sticky_on_success => 0,
+        sticky_on_failure => 1,
+        current_user => undef,
+        @_);
+
+    if ($args{'current_user'}) {
+        $self->current_user($args{current_user});
+    } else {
+        $self->_get_current_user();
+    }
+
+    if ($args{'moniker'}) {
+        $self->moniker($args{'moniker'});
+    } else {
+        $self->moniker($self->_generate_moniker);
+    }
+    $self->order($args{'order'});
+
+    $self->argument_values( { %{ $args{'request_arguments' } }, %{ $args{'arguments'} } } );
+
+    # Keep track of whether arguments came from the request, or were
+    # programmatically set elsewhere
+    $self->values_from_request({});
+    $self->values_from_request->{$_} = 1 for keys %{ $args{'request_arguments' } };
+    $self->values_from_request->{$_} = 0 for keys %{ $args{'arguments' } };
+    
+    $self->result(Jifty->web->response->result($self->moniker) || Jifty::Result->new);
+    $self->result->action_class(ref($self));
+
+    $self->sticky_on_success($args{sticky_on_success});
+    $self->sticky_on_failure($args{sticky_on_failure});
+
+    return $self;
+}
+
+=head2 _generate_moniker 
+
+Construct a moniker for a new (or soon-to-be-constructed) action that did not have
+an explicit moniker specified.  The algorithm is simple: We snapshot the call stack,
+prefix it with the action class, and then append it with an per-request autoincrement
+counter in case the same class/stack is encountered twice, which can happen if the
+programmer placed a C<new_action> call inside a loop.
+
+Monikers generated this way are guaranteed to work across requests.
+
+=cut
+
+sub _generate_moniker {
+    my $self = shift;
+
+    use Digest::MD5 qw(md5_hex);
+    my $frame = 1;
+    my @stack = (ref($self) || $self);
+    while (my ($pkg, $filename, $line) = caller($frame++)) {
+        push @stack, $pkg, $filename, $line;
+    }
+
+    # Increment the per-request moniker digest counter, for the case of looped action generation
+    my $digest = md5_hex("@stack");
+    # We should always have a stash. but if we don't, fake something up
+    # (some hiveminder tests create actions outside of a Jifty::Web)
+    my $serial = Jifty->handler->stash ? ++(Jifty->handler->stash->{monikers}{$digest}) : rand();
+    my $moniker = "auto-$digest-$serial";
+    $self->log->debug("Generating moniker $moniker from stack for $self");
+    return $moniker;
+}
+
+
+=head2 arguments
+
+B<Note>: this API is now deprecated in favour of the declarative syntax
+offered by L<Jifty::Param::Schema>.
+
+This method, along with L</take_action>, is the most commonly
+overridden method.  It should return a hash which describes the
+L<arguments|Jifty::Manual::Glossary/argument> this action takes:
+
+  {
+    argument_name    => {label => "properties go in this hash"},
+    another_argument => {mandatory => 1}
+  }
+
+Each argument listed in the hash will be turned into a
+L<Jifty::Web::Form::Field> object.  For each argument, the hash that
+describes it is used to set up the L<Jifty::Web::Form::Field> object by
+calling the keys as methods with the values as arguments.  That is, in
+the above example, Jifty will run code similar to the following:
+
+  # For 'argument_name'
+  $f = Jifty::Web::Form::Field->new;
+  $f->name( "argument_name" );
+  $f->label( "Properties go in this hash" );
+
+If an action has parameters that B<must> be passed to it to execute,
+these should have the L<constructor|Jifty::Manual::Glossary/constructor>
+property set.  This is separate from the
+L<mandatory|Jifty::Manual::Glossary/mandatory> property, which deal with
+requiring that the user enter a value for that field.
+
+
+=cut
+
+sub arguments {
+    my  $self= shift;
+    return($self->PARAMS || {});
+}
+
+=head2 run
+
+This routine, unsurprisingly, actually runs the action.
+
+If the result of the action is currently a success (validation did not
+fail), C<run> calls L</take_action>, and finally L</cleanup>.
+
+If you're writing your own actions, you probably want to override
+C<take_action> instead.
+
+=cut
+
+sub run {
+    my $self = shift;
+    $self->log->debug("Running action ".ref($self) . " " .$self->moniker);
+    unless ($self->result->success) {
+        $self->log->debug("Not taking action, as it doesn't validate");
+
+        # dump field warnings and errors to debug log
+        foreach my $what (qw/warnings errors/) {
+            my $f = "field_" . $what;
+            my @r =
+                map {
+                    $_ . ": " . $self->result->{$f}->{$_}
+                } grep { $self->result->{$f}->{$_} }
+                    keys %{ $self->result->{$f} };
+            $self->log->debug("Action result $what:\n\t", join("\n\t", @r)) if (@r);
+        }
+
+        return;
+    }
+    $self->log->debug("Taking action ".ref($self) . " " .$self->moniker);
+    my $ret = $self->take_action;
+    $self->log->debug("Result: ".(defined $ret ? $ret : "(undef)"));
+    
+    $self->cleanup;
+}
+
+=head2 validate
+
+
+Checks authorization with L</check_authorization>, calls C</setup>,
+canonicalizes and validates each argument that was submitted, but
+doesn't actually call L</take_action>.
+
+The outcome of all of this is stored on the L</result> of the action.
+
+=cut
+
+sub validate {
+    my $self = shift;
+    $self->check_authorization || return;
+    $self->setup || return;
+    $self->_canonicalize_arguments;
+    $self->_validate_arguments;
+}
+
+=head2 check_authorization
+
+Returns true if whoever invoked this action is authorized to perform
+this action. 
+
+By default, always returns true.
+
+=cut
+
+sub check_authorization { 1; }
+
+
+=head2 setup
+
+C<setup> is expected to return a true value, or
+L</run> will skip all other actions.
+
+By default, does nothing.
+
+=cut
+
+sub setup { 1; }
+
+
+=head2 take_action
+
+Do whatever the action is supposed to do.  This and
+L</arguments> are the most commonly overridden methods.
+
+By default, does nothing.
+
+The return value from this method is NOT returned. (Instead, you
+should be using the L</result> object to store a result).
+
+=cut
+
+sub take_action { 1; }
+
+
+=head2 cleanup
+
+Perform any action-specific cleanup.  By default, does nothing.
+
+Runs after L</take_action> -- whether or not L</take_action> returns success.
+
+=cut
+
+sub cleanup { 1; }
+
+=head2 moniker
+
+Returns the L<moniker|Jifty::Manual::Glossary/moniker> for this action.
+
+=head2 argument_value ARGUMENT [VALUE]
+
+Returns the value from the argument with the given name, for this
+action.  If I<VALUE> is provided, sets the value.
+
+=cut
+
+sub argument_value {
+    my $self = shift;
+    my $arg = shift;
+
+    if(@_) {
+        $self->values_from_request->{$arg} = 0;
+        $self->argument_values->{$arg} = shift;
+    }
+    return $self->argument_values->{$arg};
+}
+
+
+=head2 has_argument ARGUMENT
+
+Returns true if the action has been provided with an value for the
+given argument, including a default_value, and false if none was ever
+passed in.
+
+=cut
+
+sub has_argument {
+    my $self = shift;
+    my $arg = shift;
+
+    return exists $self->argument_values->{$arg};
+}
+
+
+=head2 form_field ARGUMENT
+
+Returns a L<Jifty::Web::Form::Field> object for this argument.  If
+there is no entry in the L</arguments> hash that matches the given
+C<ARGUMENT>, returns C<undef>.
+
+=cut
+
+
+sub form_field {
+    my $self = shift;
+    my $arg_name = shift;
+
+    my $mode = $self->arguments->{$arg_name}{'render_mode'};
+    $mode = 'update' unless $mode && $mode eq 'read';
+
+    $self->_form_widget( argument => $arg_name,
+                         render_mode => $mode,
+                         @_);
+}
+
+
+=head2 form_value ARGUMENT
+
+Returns a L<Jifty::Web::Form::Field> object that renders a display
+value instead of an editable widget for this argument.  If there is no
+entry in the L</arguments> hash that matches the given C<ARGUMENT>,
+returns C<undef>.
+
+=cut
+
+sub form_value {
+    my $self = shift;
+    my $arg_name = shift;
+    $self->_form_widget( argument => $arg_name,
+                         render_mode => 'read',
+                         @_);
+
+}
+
+# Generalized helper for the two above
+sub _form_widget {
+    my $self       = shift;
+    my %args = ( argument => undef,
+                 render_mode => 'update',
+                 @_);
+
+    my $field = $args{'argument'};
+    
+    my $arg_name = $field. '!!' .$args{'render_mode'};
+
+    if ( not exists $self->{_private_form_fields_hash}{$arg_name} ) {
+
+        my $field_info = $self->arguments->{$field};
+
+        my $sticky = 0;
+        # Check stickiness iff the values came from the request
+        if(Jifty->web->response->result($self->moniker)) {
+            $sticky = 1 if $self->sticky_on_failure and $self->result->failure;
+            $sticky = 1 if $self->sticky_on_success and $self->result->success;
+        }
+
+        # $sticky can be overrided per-parameter
+        $sticky = $field_info->{sticky} if defined $field_info->{sticky};
+
+        if ($field_info) {
+            # form_fields overrides stickiness of what the user last entered.
+            my $default_value;
+            $default_value = $field_info->{'default_value'}
+              if exists $field_info->{'default_value'};
+            $default_value = $self->argument_value($field)
+              if $self->has_argument($field) && !$self->values_from_request->{$field};
+
+            $self->{_private_form_fields_hash}{$arg_name}
+                = Jifty::Web::Form::Field->new(
+                %$field_info,
+                action        => $self,
+                name          => $field,
+                sticky        => $sticky,
+                sticky_value  => $self->argument_value($field),
+                default_value => $default_value,
+                render_mode   => $args{'render_mode'},
+                %args
+                );
+
+        }    # else $field remains undef
+        else {
+            Jifty->log->warn("$arg_name isn't a valid field for $self");
+        }
+    } elsif ( $args{render_as} ) {
+        bless $self->{_private_form_fields_hash}{$arg_name},
+          "Jifty::Web::Form::Field::$args{render_as}";
+    }
+    return $self->{_private_form_fields_hash}{$arg_name};
+}
+
+=head2 hidden ARGUMENT VALUE
+
+A shortcut for specifying a form field C<ARGUMENT> which should render
+as a hidden form field, with the default value C<VALUE>.
+
+=cut
+
+sub hidden {
+    my $self = shift;
+    my ($arg, $value, @other) = @_;
+    $self->form_field( $arg, render_as => 'hidden', default_value => $value, @other);
+}
+
+=head2 order [INTEGER]
+
+Gets or sets the order that the action will be run in.  This should be
+an integer, with lower numbers being run first.  Defaults to zero.
+
+=head2 result [RESULT]
+
+Returns the L<Jifty::Result> method associated with this action.  If
+an action with the same moniker existed in the B<last> request, then
+this contains the results of that action.
+
+=head2 register
+
+Registers this action as being present, by outputting a snippet of
+HTML.  This expects that an HTML form has already been opened.  Note
+that this is not a guarantee that the action will be run, even if the
+form is submitted.  See L<Jifty::Request> for the definition of
+"L<active|Jifty::Manual::Glossary/active>" actions.
+
+Normally, L<Jifty::Web/new_action> takes care of calling this when it
+is needed.
+
+=cut
+
+sub register {
+    my $self = shift;
+    Jifty->web->out( qq!<div class="hidden"><input type="hidden"! .
+                       qq! name="@{[$self->register_name]}"! .
+                       qq! id="@{[$self->register_name]}"! .
+                       qq! value="@{[ref($self)]}"! .
+                       qq! /></div>\n! );
+
+
+
+    my %args = %{$self->arguments};
+
+    while ( my ( $name, $info ) = each %args ) {
+        next unless $info->{'constructor'};
+        Jifty::Web::Form::Field->new(
+            %$info,
+            action        => $self,
+            input_name    => $self->fallback_form_field_name($name),
+            sticky        => 0,
+            default_value => ($self->argument_value($name) || $info->{'default_value'}),
+            render_as     => 'Hidden'
+        )->render();
+    }
+    return '';
+}
+
+=head2 render_errors
+
+Render any the L<Jifty::Result/error> of this action, if any, as HTML.
+Returns nothing.
+
+=cut
+
+sub render_errors {
+    my $self = shift;
+    
+    if (defined $self->result->error) {
+        # XXX TODO FIXME escape?
+        Jifty->web->out( '<div class="form_errors">'
+                . '<span class="error">'
+                . $self->result->error
+                . '</span>'
+                . '</div>' );
+    }
+    return '';
+}
+
+=head2 button arguments => { KEY => VALUE }, PARAMHASH
+
+Create and render a button.  It functions nearly identically like
+L<Jifty::Web/link>, except it takes C<arguments> in addition to
+C<parameters>, and defaults to submitting this L<Jifty::Action>.
+Returns nothing. 
+
+Recommended reading: L<Jifty::Web::Form::Element>, where most of 
+the cool options to button and other things of its ilk are documented.
+
+=cut
+
+sub button {
+    my $self = shift;
+    my %args = ( arguments => {},
+                 submit    => $self,
+                 register  => 0,
+                 @_);
+
+    if ($args{register}) {
+        # If they ask us to register the action, do so
+        Jifty->web->form->register_action( $self );
+        Jifty->web->form->print_action_registration($self->moniker);
+    } elsif ( not Jifty->web->form->printed_actions->{ $self->moniker } ) {
+        # Otherwise, if we're not registered yet, do it in the button
+        my $arguments = $self->arguments;
+        $args{parameters}{ $self->register_name } = ref $self;
+        $args{parameters}{ $self->fallback_form_field_name($_) }
+            = $self->argument_value($_) || $arguments->{$_}->{'default_value'}
+            for grep { $arguments->{$_}{constructor} } keys %{ $arguments };
+    }
+    $args{parameters}{$self->form_field_name($_)} = $args{arguments}{$_}
+      for keys %{$args{arguments}};
+
+    Jifty->web->link(%args);
+}
+
+=head3 return PARAMHASH
+
+Creates and renders a button, like L</button>, which additionally
+defaults to calling the current continuation.
+
+Takes an additional argument, C<to>, which can specify a default path
+to return to if there is no current continuation.
+
+=cut
+
+sub return {
+    my $self = shift;
+    my %args = (@_);
+    my $continuation = Jifty->web->request->continuation;
+    if (not $continuation and $args{to}) {
+        $continuation = Jifty::Continuation->new(request => Jifty::Request->new(path => $args{to}));
+    }
+    delete $args{to};
+
+    $self->button( call => $continuation, %args );
+}
+
+
+=head1 NAMING METHODS
+
+These methods return the names of HTML form elements related to this
+action.
+
+=head2 register_name
+
+Returns the name of the "registration" query argument for this action
+in a web form.
+
+=cut
+
+sub register_name {
+    my $self = shift;
+    return 'J:A-' . (defined $self->order ? $self->order . "-" : "") .$self->moniker;
+}
+
+
+sub _prefix_field {
+    my $self = shift;
+    my ($field_name, $prefix) = @_;
+    return join("-", $prefix, $field_name, $self->moniker);
+}
+
+=head2 form_field_name ARGUMENT
+
+Turn one of this action's L<arguments|Jifty::Manual::Glossary/arguments> into
+a fully qualified name; takes the name of the field as an argument.
+
+=cut
+
+sub form_field_name {
+    my $self = shift;
+    return $self->_prefix_field(shift, "J:A:F");
+}
+
+=head2 fallback_form_field_name ARGUMENT
+
+Turn one of this action's L<arguments|Jifty::Manual::Glossary/arguments> into
+a fully qualified "fallback" name; takes the name of the field as an
+argument.
+
+This is specifically to support checkboxes, which only show up in the
+query string if they are checked.  Jifty creates a checkbox with the
+value of L<form_field_name> as its name and a value of 1, and a hidden
+input with the value of L<fallback_form_field_name> as its name and a
+value of 0; using this information, L<Jifty::Request> can both
+determine if the checkbox was present at all in the form, as well as
+its true value.
+
+=cut
+
+sub fallback_form_field_name {
+    my $self = shift;
+    return $self->_prefix_field(shift, "J:A:F:F");
+}
+
+=head2 error_div_id ARGUMENT
+
+Turn one of this action's L<arguments|Jifty::Manual::Glossary/arguments> into
+the id for the div in which its errors live; takes name of the field
+as an argument.
+
+=cut
+
+sub error_div_id {
+  my $self = shift;
+  my $field_name = shift;
+  return 'errors-' . $self->form_field_name($field_name);
+}
+
+=head2 warning_div_id ARGUMENT
+
+Turn one of this action's L<arguments|Jifty::Manual::Glossary/arguments> into
+the id for the div in which its warnings live; takes name of the field
+as an argument.
+
+=cut
+
+sub warning_div_id {
+  my $self = shift;
+  my $field_name = shift;
+  return 'warnings-' . $self->form_field_name($field_name);
+}
+
+=head2 canonicalization_note_div_id ARGUMENT
+
+Turn one of this action's L<arguments|Jifty::Manual::Glossary/arguments> into
+the id for the div in which its canonicalization notes live; takes name of the field
+as an argument.
+
+=cut
+
+sub canonicalization_note_div_id {
+  my $self = shift;
+  my $field_name = shift;
+  return 'canonicalization_note-' . $self->form_field_name($field_name);
+}
+
+
+=head1 VALIDATION METHODS
+
+=head2 argument_names
+
+Returns the list of argument names.  This information is extracted
+from L</arguments>.
+
+=cut
+
+
+sub argument_names {
+    my $self      = shift;
+    my %arguments = %{ $self->arguments };
+    return (
+        sort {
+            (($arguments{$a}->{'sort_order'} ||0 ) <=> ($arguments{$b}->{'sort_order'} || 0))
+                || (($arguments{$a}->{'name'} || '') cmp ($arguments{$b}->{'name'} ||'' ))
+                || $a cmp $b
+            } keys %arguments
+    );
+}
+
+
+=head2 _canonicalize_arguments
+
+Canonicalizes each of the L<arguments|Jifty::Manual::Glossary/arguments> that
+this action knows about.
+
+This is done by calling L</_canonicalize_argument> for each field
+described by L</arguments>.
+
+=cut
+
+# XXX TODO: This is named with an underscore to prevent infinite
+# looping with arguments named "argument" or "arguments".  We need a
+# better solution.
+sub _canonicalize_arguments {
+    my $self   = shift;
+
+    $self->_canonicalize_argument($_)
+      for $self->argument_names;
+}
+
+
+=head2 _canonicalize_argument ARGUMENT
+
+Canonicalizes the value of an L<argument|Jifty::Manual::Glossary/argument>.
+If the argument has an attribute named B<canonicalizer>, call the
+subroutine reference that attribute points points to.
+
+If it doesn't have a B<canonicalizer> attribute, but the action has a
+C<canonicalize_I<ARGUMENT>> function, also invoke that function.
+
+If neither of those are true, by default canonicalize dates using
+_canonicalize_date
+
+Note that it is possible that a canonicalizer will be called multiple
+times on the same field -- canonicalizers should be careful to do
+nothing to already-canonicalized data.
+
+=cut
+
+# XXX TODO: This is named with an underscore to prevent infinite
+# looping with arguments named "argument" or "arguments".  We need a
+# better solution.
+sub _canonicalize_argument {
+    my $self  = shift;
+    my $field = shift;
+
+    my $field_info = $self->arguments->{$field};
+    my $value = $self->argument_value($field);
+    my $default_method = 'canonicalize_' . $field;
+
+    # XXX TODO: Do we really want to skip undef values?
+    return unless defined $value;
+
+    if ( $field_info->{canonicalizer}
+        and defined &{ $field_info->{canonicalizer} } )
+    {
+        $value = $field_info->{canonicalizer}->( $self, $value );
+    } elsif ( $self->can($default_method) ) {
+        $value = $self->$default_method( $value );
+    } elsif (   defined( $field_info->{render_as} )
+             && lc( $field_info->{render_as} ) eq 'date') {
+        $value = $self->_canonicalize_date( $value );
+    }
+
+    $self->argument_value($field => $value);
+}
+
+
+=head2 _canonicalize_date DATE
+
+Parses and returns the date using L<Jifty::DateTime::new_from_string>.
+
+=cut
+
+sub _canonicalize_date {
+    my $self = shift;
+    my $val = shift;
+    return undef unless defined $val and $val =~ /\S/;
+    return undef unless my $obj = Jifty::DateTime->new_from_string($val);
+    return $obj->ymd;
+}
+
+=head2 _validate_arguments
+
+Validates the form fields.  This is done by calling
+L</_validate_argument> for each field described by L</arguments>
+
+=cut
+
+# XXX TODO: This is named with an underscore to prevent infinite
+# looping with arguments named "argument" or "arguments".  We need a
+# better solution.
+sub _validate_arguments {
+    my $self   = shift;
+    
+    $self->_validate_argument($_)
+      for $self->argument_names;
+
+
+    return $self->result->success;
+}
+
+=head2 _validate_argument ARGUMENT
+
+Validate your form fields.  If the field C<ARGUMENT> is mandatory,
+checks for a value.  If the field has an attribute named B<validator>,
+call the subroutine reference validator points to.
+
+If the action doesn't have an explicit B<validator> attribute, but
+does have a C<validate_I<ARGUMENT>> function, invoke that function.
+
+=cut
+
+# XXX TODO: This is named with an underscore to prevent infinite
+# looping with arguments named "argument" or "arguments".  We need a
+# better solution.
+sub _validate_argument {
+    my $self  = shift;
+    my $field = shift;
+
+    return unless $field;
+    
+    $self->log->debug(" validating argument $field");
+
+    my $field_info = $self->arguments->{$field};
+    return unless $field_info;
+
+    my $value = $self->argument_value($field);
+    
+    if ( !defined $value || !length $value ) {
+        if ( $field_info->{mandatory} ) {
+            return $self->validation_error( $field => _("You need to fill in this field") );
+        }
+    }
+
+    # If we have a set of allowed values, let's check that out.
+    # XXX TODO this should be a validate_valid_values sub
+    if ( $value && $field_info->{valid_values} ) {
+
+        unless ( grep $_->{'value'} eq $value,
+            @{ $self->valid_values($field) } )
+        {
+
+            return $self->validation_error(
+                $field => _("That doesn't look like a correct value") );
+        }
+
+   # ... but still check through a validator function even if it's in the list
+    }
+
+    my $default_validator = 'validate_' . $field;
+
+    # Finally, fall back to running a validator sub
+    if ( $field_info->{validator}
+        and defined &{ $field_info->{validator} } )
+    {
+        return $field_info->{validator}->( $self, $value );
+    }
+
+    elsif ( $self->can($default_validator) ) {
+        return $self->$default_validator( $value );
+    }
+
+    # If none of the checks have failed so far, then it's ok
+    else {
+        return $self->validation_ok($field);
+    }
+}
+
+=head2 _autocomplete_argument ARGUMENT
+
+Get back a list of possible completions for C<ARGUMENT>.  The list
+should either be a list of scalar values or a list of hash references.
+Each hash reference must have a key named C<value>.  There can also
+additionally be a key named C<label> which, if present, will be used
+as the user visible label.  If C<label> is not present then the
+contents of C<value> will be used for the label.
+
+If the field has an attribute named B<autocompleter>, call the
+subroutine reference B<autocompleter> points to.
+
+If the field doesn't have an explicit B<autocompleter> attribute, but
+does have a C<autocomplete_I<ARGUMENT>> function, invoke that
+function.
+
+
+=cut
+
+# XXX TODO: This is named with an underscore to prevent infinite
+# looping with arguments named "argument" or "arguments".  We need a
+# better solution.
+sub _autocomplete_argument {
+    my $self  = shift;
+    my $field = shift;
+    my $field_info = $self->arguments->{$field};
+    my $value = $self->argument_value($field);
+
+    my $default_autocomplete = 'autocomplete_' . $field;
+
+    if ( $field_info->{autocompleter}  )
+    {
+        return $field_info->{autocompleter}->( $self, $value );
+    }
+
+    elsif ( $self->can($default_autocomplete) ) {
+        return $self->$default_autocomplete( $value );
+    }
+
+}
+
+=head2 valid_values ARGUMENT
+
+Given an L<parameter|Jifty::Manual::Glossary/parameter> name, returns the
+list of valid values for it, based on its C<valid_values> field.
+
+This method returns a hash referenece with a C<display> field for the string
+to display for the value, and a C<value> field for the value to actually send
+to the server.
+
+(Avoid using this -- this is not the appropriate place for this logic
+to be!)
+
+=cut
+
+sub valid_values {
+    my $self = shift;
+    my $field = shift;
+
+    $self->_values_for_field( $field => 'valid' );
+}
+
+=head2 available_values ARGUMENT
+
+Just like L<valid_values>, but if our action has a set of available
+recommended values, returns that instead. (We use this to
+differentiate between a list of acceptable values and a list of
+suggested values)
+
+=cut
+
+sub available_values {
+    my $self = shift;
+    my $field = shift;
+
+    $self->_values_for_field( $field => 'available' ) || $self->_values_for_field( $field => 'valid' );
+
+}
+
+# TODO XXX FIXME this is probably in the wrong place, logically
+sub _values_for_field {
+    my $self  = shift;
+    my $field = shift;
+    my $type = shift;
+
+    my $vv_orig = $self->arguments->{$field}{$type .'_values'};
+    local $@;
+    my @values = eval { @$vv_orig } or return $vv_orig;
+
+    my $vv = [];
+
+    for my $v (@values) {
+        if ( ref $v eq 'HASH' ) {
+            if ( $v->{'collection'} ) {
+                my $disp = $v->{'display_from'};
+                my $val  = $v->{'value_from'};
+                # XXX TODO: wrap this in an eval?
+                push @$vv, map {
+                    {
+                        display => ( $_->$disp() || '' ),
+                        value   => ( $_->$val()  || '' )
+                    }
+                } grep {$_->check_read_rights} @{ $v->{'collection'}->items_array_ref };
+
+            }
+            else {
+
+                # assume it's already display/value
+                push @$vv, $v;
+            }
+        }
+        else {
+
+            # just a string
+            push @$vv, { display => $v, value => $v };
+        }
+    }
+
+    return $vv;
+}
+
+=head2 validation_error ARGUMENT => ERROR TEXT
+
+Used to report an error during validation.  Inside a validator you
+should write:
+
+  return $self->validation_error( $field => "error");
+
+..where C<$field> is the name of the argument which is at fault.
+
+=cut
+
+sub validation_error {
+    my $self = shift;
+    my $field = shift;
+    my $error = shift;
+  
+    $self->result->field_error($field => $error); 
+  
+    return 0;
+}
+
+=head2 validation_warning ARGUMENT => WARNING TEXT
+
+Used to report a warning during validation.  Inside a validator you
+should write:
+
+  return $self->validation_warning( $field => "warning");
+
+..where C<$field> is the name of the argument which is at fault.
+
+=cut
+
+sub validation_warning {
+    my $self = shift;
+    my $field = shift;
+    my $warning = shift;
+  
+    $self->result->field_warning($field => $warning); 
+  
+    return 0;
+}
+
+=head2 validation_ok ARGUMENT
+
+Used to report that a field B<does> validate.  Inside a validator you
+should write:
+
+  return $self->validation_ok($field);
+
+=cut
+
+sub validation_ok {
+    my $self = shift;
+    my $field = shift;
+
+    $self->result->field_error($field => undef);
+    $self->result->field_warning($field => undef);
+
+    return 1;
+}
+
+=head2 canonicalization_note ARGUMENT => NOTE
+
+Used to send an informational message to the user from the canonicalizer.  
+Inside a canonicalizer you can write:
+
+  $self->canonicalization_note( $field => "I changed $field for you");
+
+..where C<$field> is the name of the argument which the canonicalizer is 
+processing
+
+=cut
+
+sub canonicalization_note {
+    my $self = shift;
+    my $field = shift;
+    my $info = shift;
+  
+    $self->result->field_canonicalization_note($field => $info); 
+
+    return;
+
+}
+
+=head2 autogenerated
+
+Autogenerated Actions will always return true when this method is called. 
+"Regular" actions will return false.
+
+=cut
+
+sub autogenerated {0}
+
+1;

Added: jifty/branches/schema-plugins/lib/Jifty/Action/Autocomplete.pm
==============================================================================
--- (empty file)
+++ jifty/branches/schema-plugins/lib/Jifty/Action/Autocomplete.pm	Mon Jan 29 21:05:02 2007
@@ -0,0 +1,75 @@
+use warnings;
+use strict;
+
+=head1 NAME
+
+Jifty::Action::Autocomplete
+
+=head1 DESCRIPTION
+
+A built-in L<Jifty::Action> which returns suggested autocompletions
+for a given argument of an action. Generally this is called by Jifty's
+internals through C</__jifty/autocomplete.xml>.
+
+This action gets its data to C</__jifty/autocomplete.xml> by filling in the
+C<completions> of the L<Jifty::Result/content>.
+
+=cut
+
+
+
+package Jifty::Action::Autocomplete;
+use base qw/Jifty::Action/;
+
+=head2 arguments
+
+The arguments for C<Autocomplete> are:
+
+=over 4
+
+=item action
+
+The L<moniker|Jifty::Manual::Glossary/moniker> of an action we want to pull a
+field to autocomplete from.
+
+=item argument
+
+The fully qualified name of the L<argument|Jifty::Manual::Glossary/argument>
+to C<action> that we want to complete.
+
+=back
+
+=cut
+
+sub arguments {
+    {
+        moniker => {},
+        argument => {}
+    }
+}
+
+=head2 take_action
+
+Find the submitted action in the L<Jifty::Request> named by the
+C<action> above, and ask it for autocompletion possibilites for the
+L<argument> in question.
+
+=cut
+
+sub take_action {
+    my $self = shift;
+
+    my $moniker = $self->argument_value('moniker');
+    my $argument = $self->argument_value('argument');
+
+    my $request_action = Jifty->web->request->action($moniker);
+    my $action = Jifty->web->new_action_from_request($request_action);
+
+    my @completions = $action->_autocomplete_argument($argument);
+    $self->result->content->{completions} = \@completions;
+
+    return 1;
+}
+
+1;
+

Added: jifty/branches/schema-plugins/lib/Jifty/Action/Record.pm
==============================================================================
--- (empty file)
+++ jifty/branches/schema-plugins/lib/Jifty/Action/Record.pm	Mon Jan 29 21:05:02 2007
@@ -0,0 +1,399 @@
+use warnings;
+use strict;
+
+package Jifty::Action::Record;
+
+=head1 NAME
+
+Jifty::Action::Record -- An action tied to a record in the database.
+
+=head1 DESCRIPTION
+
+Represents a web-based action that is a create, update, or delete of a
+L<Jifty::Record> object.  This automatically populates the arguments
+method of L<Jifty::Action> so that you don't need to bother.  To
+actually use this class, you probably want to inherit from one of
+L<Jifty::Action::Record::Create>, L<Jifty::Action::Record::Update>, or
+L<Jifty::Action::Record::Delete> and override the C<record_class>
+method.
+
+=cut
+
+use base qw/Jifty::Action/;
+
+use Scalar::Util qw/ blessed /;
+
+__PACKAGE__->mk_accessors(qw(record _cached_arguments));
+
+=head1 METHODS
+
+=head2 record
+
+Access to the underlying L<Jifty::Record> object for this action is
+through the C<record> accessor.
+
+=head2 record_class
+
+This method can either be overridden to return a string specifying the
+name of the record class, or the name of the class can be passed to
+the constructor.
+
+=cut
+
+sub record_class {
+    my $self = shift;
+    my $class = ref $self;
+    my $hint = $class eq __PACKAGE__ ? "" :
+        " (did you forget to override record_class in $class?)";
+    $self->log->fatal("Jifty::Action::Record must be subclassed to be used" .
+        $hint);
+}
+
+=head2 new PARAMHASH
+
+Construct a new C<Jifty::Action::Record> (as mentioned in
+L<Jifty::Action>, this should only be called by C<<
+framework->new_action >>.  The C<record> value, if provided in the
+PARAMHASH, will be used to load the L</record>; otherwise, the
+parimary keys will be loaded from the action's argument values, and
+the L</record> loaded from those primary keys.
+
+=cut
+
+sub new {
+    my $class = shift;
+    my %args  = (
+        record => undef,
+        @_,
+    );
+    my $self = $class->SUPER::new(%args);
+
+
+    my $record_class = $self->record_class;
+    Jifty::Util->require($record_class);
+
+    if (ref $args{'record'} && !$args{'record'}->isa($record_class)) {
+        Carp::confess($args{'record'}." isn't a $record_class");
+    }
+
+
+
+    # Set up record
+    if ( ref $record_class ) {
+        $self->record($record_class);
+        $self->argument_value( $_, $self->record->$_ )
+            for @{ $self->record->_primary_keys };
+    } elsif ( ref $args{record} and $args{record}->isa($record_class) ) {
+        $self->record( $args{record} );
+        $self->argument_value( $_, $self->record->$_ )
+            for @{ $self->record->_primary_keys };
+    } else {
+
+        # We could leave out the explicit current user, but it'd have
+        # a slight negative performance implications
+        $self->record(
+            $record_class->new( current_user => $self->current_user ) );
+        my %given_pks = ();
+        for my $pk ( @{ $self->record->_primary_keys } ) {
+            $given_pks{$pk} = $self->argument_value($pk)
+                if defined $self->argument_value($pk);
+        }
+        $self->record->load_by_primary_keys(%given_pks) if %given_pks;
+    }
+    return $self;
+}
+
+=head2 arguments
+
+Overrides the L<Jifty::Action/arguments> method, to automatically
+provide a form field for every writable attribute of the underlying
+L</record>.
+
+This also creates built-in validation and autocompletion methods
+(validate_$fieldname and autocomplete_$fieldname) for action fields
+that are defined "validate" or "autocomplete". These methods can
+be overridden in any Action which inherits from this class.
+
+Additionally, if our model class defines canonicalize_, validate_, or
+autocomplete_ FIELD, generate appropriate an appropriate
+canonicalizer, validator, or autocompleter that will call that method
+with the value to be validated, canonicalized, or autocompleted.
+
+C<validate_FIELD> should return a (success boolean, message) list.
+
+C<autocomplete_FIELD> should return a the same kind of list as
+L<Jifty::Action::_autocomplete_argument|Jifty::Action/_autocomplete_argument>
+
+C<canonicalized_FIELD> should return the canonicalized value.
+
+=cut
+
+sub arguments {
+    my $self = shift;
+
+    return $self->_cached_arguments if $self->_cached_arguments;
+
+        my $field_info = {};
+
+        my @fields = $self->possible_fields;
+
+        # we use a while here because we may be modifying the fields
+        # on the fly.
+        while ( my $field = shift @fields ) {
+            my $info = {};
+            my $column;
+            if ( ref $field ) {
+                $column = $field;
+                $field  = $column->name;
+            } else {
+                $column = $self->record->column($field);
+                my $current_value = $self->record->$field;
+
+                # If the current value is actually a pointer to
+                # another object, dereference it
+                $current_value = $current_value->id
+                    if blessed($current_value)
+                    and $current_value->isa('Jifty::Record');
+                $info->{default_value} = $current_value if $self->record->id;
+            }
+
+            # 
+            #  if($field =~ /^(.*)_id$/ && $self->record->column($1)) {
+            #    $column = $self->record->column($1);
+            #}
+
+            ##################
+            my $render_as = $column->render_as;
+            $render_as = defined $render_as ? lc($render_as) : '';
+
+            if ( defined (my $valid_values = $column->valid_values)) {
+                $info->{valid_values} = [ @$valid_values ];
+                $info->{render_as}    = 'Select';
+            } elsif ( defined $column->type && $column->type =~ /^bool/i ) {
+                $info->{render_as} = 'Checkbox';
+            } elsif ( $render_as eq 'password' )
+            {
+                my $same = sub {
+                    my ( $self, $value ) = @_;
+                    if ( $value ne $self->argument_value($field) ) {
+                        return $self->validation_error(
+                            ($field.'_confirm') => _("The passwords you typed didn't match each other")
+                        );
+                    } else {
+                        return $self->validation_ok( $field . '_confirm' );
+                    }
+                };
+
+                $field_info->{ $field . "_confirm" } = {
+                    render_as => 'Password',
+                    virtual => '1',
+                    validator => $same,
+                    sort_order => ($column->sort_order +.01),
+                    mandatory => 0
+                };
+            }
+
+            elsif ( defined (my $refers_to = $column->refers_to) ) {
+                if ( UNIVERSAL::isa( $refers_to, 'Jifty::Record' ) ) {
+
+                    my $collection = Jifty::Collection->new(
+                        record_class => $refers_to,
+                        current_user => $self->record->current_user
+                    );
+                    $collection->unlimit;
+
+                    my $method = $refers_to->_brief_description();
+
+                    $info->{valid_values} = [
+                        {   display_from => $refers_to->can($method) ? $method : "id",
+                            value_from => 'id',
+                            collection => $collection
+                        }
+                    ];
+
+                    $info->{render_as} = 'Select';
+                } else {
+                    # No need to generate arguments for
+                    # JDBI::Collections, as we can't do anything
+                    # useful with them yet, anyways.
+                    next;
+                }
+            }
+
+	    #########
+
+
+            # build up a validator sub if the column implements validation
+            # and we're not overriding it at the action level
+            my $validate_method = "validate_" . $field;
+
+            if ( $column->validator and not $self->can($validate_method) ) {
+                $info->{ajax_validates} = 1;
+                $info->{validator} = sub {
+                    my $self  = shift;
+                    my $value = shift;
+                    my ( $is_valid, $message )
+                        = &{ $column->validator }( $self->record, $value );
+
+                    if ($is_valid) {
+                        return $self->validation_ok($field);
+                    } else {
+                        unless ($message) {
+                            $self->log->error(
+                                qq{Schema validator for $field didn't explain why the value '$value' is invalid}
+                            );
+                        }
+                        return (
+                            $self->validation_error(
+                                $field => ($message || _("That doesn't look right, but I don't know why"))
+                            )
+                        );
+                    }
+                };
+            }
+            my $autocomplete_method = "autocomplete_" . $field;
+
+            if ( $self->record->can($autocomplete_method) ) {
+                $info->{'autocompleter'} ||= sub {
+                    my ( $self, $value ) = @_;
+                    my %columns;
+                    $columns{$_} = $self->argument_value($_)
+                        for grep { $_ ne $field } $self->possible_fields;
+                    return $self->record->$autocomplete_method( $value,
+                        %columns );
+                };
+            }
+            elsif ($column->autocompleted) {
+                # Auto-generated autocompleter
+                $info->{'autocompleter'} ||= sub {
+                    my ( $self, $value ) = @_;
+
+                    my $collection = Jifty::Collection->new(
+                        record_class => $self->record_class,
+                        current_user => $self->record->current_user
+                    );
+
+                    $collection->unlimit;
+                    $collection->rows_per_page(20);
+                    $collection->limit(column => $field, value => $value, operator => 'STARTSWITH', entry_aggregator => 'AND') if length($value);
+                    $collection->limit(column => $field, value => 'NULL', operator => 'IS NOT', entry_aggregator => 'AND');
+                    $collection->limit(column => $field, value => '', operator => '!=', entry_aggregator => 'AND');
+                    $collection->columns('id', $field);
+                    $collection->order_by(column => $field);
+                    $collection->group_by(column => $field);
+
+                    my @choices;
+                    while (my $record = $collection->next) {
+                        push @choices, $record->$field;
+                    }
+                    return @choices;
+                };
+            }
+
+            my $canonicalize_method = "canonicalize_" . $field;
+            if ( $self->record->can($canonicalize_method) ) {
+                $info->{'ajax_canonicalizes'} = 1;
+                $info->{'canonicalizer'} ||= sub {
+                    my ( $self, $value ) = @_;
+                    return $self->record->$canonicalize_method($value);
+                };
+            } elsif ( $render_as eq 'date')
+            {
+                $info->{'ajax_canonicalizes'} = 1;
+            }
+
+            # If we're hand-coding a render_as, hints or label, let's use it.
+            for (qw(render_as label hints max_length mandatory sort_order)) {
+
+                if ( defined (my $val = $column->$_) ) {
+                    $info->{$_} = $val;
+                }
+            }
+            $field_info->{$field} = $info;
+        }
+
+    if ($self->can('PARAMS')) {
+        # User-defined declarative schema fields can override default ones here
+        my $params = $self->PARAMS;
+
+        # We really, really want our sort_order to prevail over user-defined ones
+        # (as opposed to all other param fields).  So we do exactly that here.
+        while (my ($key, $param) = each %$params) {
+            defined(my $sort_order = $param->sort_order) or next;
+
+            # The .99 below means that it's autogenerated by Jifty::Param::Schema.
+            if ($sort_order =~ /\.99$/) {
+                $param->sort_order($field_info->{$key}{sort_order});
+            }
+        }
+
+        use Jifty::Param::Schema ();
+        $self->_cached_arguments(Jifty::Param::Schema::merge_params($field_info, $params));
+    }
+    else {
+        $self->_cached_arguments($field_info);
+    }
+
+    return $self->_cached_arguments();
+}
+
+=head2 possible_fields
+
+Returns the list of fields on the object that the action can update.
+This defaults to all of the fields of the object.
+
+=cut
+
+sub possible_fields {
+    my $self = shift;
+    return map { $_->name } grep { $_->type ne "serial" } $self->record->columns;
+}
+
+=head2 take_action
+
+Throws an error unless it is overridden; use
+Jifty::Action::Record::Create, ::Update, or ::Delete
+
+=cut
+
+sub take_action {
+    my $self = shift;
+    $self->log->fatal(
+        "Use one of the Jifty::Action::Record subclasses, ::Create, ::Update or ::Delete or ::Search"
+    );
+}
+
+sub _setup_event_before_action {
+    my $self = shift;
+
+    my $event_info = {};
+    $event_info->{as_hash_before} = $self->record->as_hash;
+    $event_info->{record_id} = $self->record->id;
+    $event_info->{record_class} = ref($self->record);
+    $event_info->{action_class} = ref($self);
+    $event_info->{action_arguments} = $self->argument_values; # XXX does this work?
+    $event_info->{current_user_id} = $self->current_user->id || 0;
+    return ($event_info);
+}
+
+sub _setup_event_after_action {
+    my $self = shift;
+    my $event_info = shift;
+    $event_info->{result} = $self->result;    
+    $event_info->{timestamp} = time(); 
+    $event_info->{as_hash_after} = $self->record->as_hash;
+
+    my $event_class = $event_info->{'record_class'};
+    $event_class =~ s/::Model::/::Event::Model::/g;
+    Jifty::Util->require($event_class);
+    $event_class->new($event_info)->publish;
+}
+
+=head1 SEE ALSO
+
+L<Jifty::Action>, L<Jifty::Record>, L<Jifty::DBI::Record>,
+L<Jifty::Action::Record::Create>, L<Jifty::Action::Record::Update>
+
+=cut
+
+1;

Added: jifty/branches/schema-plugins/lib/Jifty/Action/Record/Create.pm
==============================================================================
--- (empty file)
+++ jifty/branches/schema-plugins/lib/Jifty/Action/Record/Create.pm	Mon Jan 29 21:05:02 2007
@@ -0,0 +1,109 @@
+use warnings;
+use strict;
+
+package Jifty::Action::Record::Create;
+
+=head1 NAME
+
+Jifty::Action::Record::Create - Automagic creation action
+
+=head1 DESCRIPTION
+
+This class is used as the base class for L<Jifty::Action>s that are
+merely creating L<Jifty::Record> objects.  To use it, subclass it and
+override the C<record_class> method to return the name of the
+L<Jifty::Record> subclass that this action creates.
+
+=cut
+
+use base qw/Jifty::Action::Record/;
+
+=head1 METHODS
+
+=head2 arguments
+
+Set the default value in each of the fields to whatever the default of
+the column is in the model
+
+=cut
+
+sub arguments {
+    my $self = shift;
+    
+    my $args = $self->SUPER::arguments;
+    for my $arg (keys %{$args}) {
+        my $column = $self->record->column($arg) or next;
+        $args->{$arg}{default_value} = $column->default
+          if not $args->{$arg}->{default_value};
+    }
+    return $args;
+}
+
+=head2 take_action
+
+Overrides the virtual C<take_action> method on L<Jifty::Action> to call
+the appropriate C<Jifty::Record>'s C<create> method when the action is
+run, thus creating a new object in the database.
+
+The C<id> of the new row is returned in the C<id> content of the
+L<Jifty::Result> for the action.  You can use this in conjunction with
+L<request mapping|Jifty::Request::Mapper> in order to give later parts
+of the request access to the C<id>.
+
+=cut
+
+sub take_action {
+    my $self   = shift;
+    my $record = $self->record;
+
+    my $event_info = $self->_setup_event_before_action();
+    
+    
+    my %values;
+    # Virtual arguments aren't really ever backed by data structures. they're added by jifty for things like confirmations
+    for (grep { defined $self->argument_value($_) && !$self->arguments->{$_}->{virtual} } $self->argument_names) {
+        $values{$_} = $self->argument_value($_);
+        if (ref $values{$_} eq "Fh") { # CGI.pm's "lightweight filehandle class"
+            local $/;
+            my $fh = $values{$_};
+            binmode $fh;
+            $values{$_} = scalar <$fh>;
+        }
+    }
+    my $id;
+    my $msg = $record->create(%values);
+    # Handle errors?
+    if (ref($msg)) { # If it's a Class::ReturnValue
+        ($id,$msg) = $msg->as_array;
+    }
+
+    if (! $record->id ) {
+        $self->log->debug(_("Create of %1 failed: %2", ref($record), $msg));
+        $self->result->error($msg || _("An error occurred.  Try again later"));
+    }
+
+    else { 
+        # Return the id that we created
+        $self->result->content(id => $self->record->id);
+        $self->report_success if  not $self->result->failure;
+    }
+    $self->_setup_event_after_action($event_info) ;
+
+    return ($self->record->id);
+}
+
+=head2 report_success
+
+Sets the L<Jifty::Result/message> to default success message,
+"Created". Override this if you want to report some other
+more user-friendly result.
+
+=cut
+
+sub report_success {
+    my $self = shift;
+    $self->result->message(_("Created"))
+}
+
+
+1;

Added: jifty/branches/schema-plugins/lib/Jifty/Action/Record/Delete.pm
==============================================================================
--- (empty file)
+++ jifty/branches/schema-plugins/lib/Jifty/Action/Record/Delete.pm	Mon Jan 29 21:05:02 2007
@@ -0,0 +1,79 @@
+use warnings;
+use strict;
+
+package Jifty::Action::Record::Delete;
+
+=head1 NAME
+
+Jifty::Action::Record::Delete - Automagic delete action
+
+=head1 DESCRIPTION
+
+This class is used as the base class for L<Jifty::Action>s that are
+merely deleting L<Jifty::Record> objects.  To use it, subclass it and
+override the C<record_class> method to return the name of the
+L<Jifty::Record> subclass that this action should delete.
+
+=cut
+
+use base qw/Jifty::Action::Record/;
+
+=head1 METHODS
+
+=head2 arguments
+
+Overrides the L<Jifty::Action::Record/arguments> method to specify
+that all of the primary keys B<must> have values when submitted; that
+is, they are L<constructors|Jifty::Manual::Glossary/constructors>.  No other
+arguments are required.
+
+=cut
+
+sub arguments {
+    my $self = shift;
+    my $arguments = {};
+
+    for my $pk (@{ $self->record->_primary_keys }) {
+        $arguments->{$pk}{'constructor'} = 1;
+        # XXX TODO IS THERE A BETTER WAY TO NOT RENDER AN ITEM IN arguments
+        $arguments->{$pk}{'render_as'} = 'Unrendered'; 
+        # primary key fields should always be hidden fields
+    }
+    return $arguments;
+}
+
+=head2 take_action
+
+Overrides the virtual C<take_action> method on L<Jifty::Action> to
+delete the row from the database.
+
+=cut
+
+sub take_action {
+    my $self = shift;
+
+    my $event_info = $self->_setup_event_before_action();
+
+    my ( $val, $msg ) = $self->record->delete;
+    $self->result->error($msg) if not $val and $msg;
+
+    $self->report_success if not $self->result->failure;
+    $self->_setup_event_after_action($event_info);
+
+    return 1;
+}
+
+=head2 report_success
+
+Sets the L<Jifty::Result/message> to default success message,
+"Deleted". Override this if you want to report some other more
+user-friendly result.
+
+=cut
+
+sub report_success {
+    my $self = shift;
+    $self->result->message(_("Deleted"))
+}
+
+1;

Added: jifty/branches/schema-plugins/lib/Jifty/Action/Record/Search.pm
==============================================================================
--- (empty file)
+++ jifty/branches/schema-plugins/lib/Jifty/Action/Record/Search.pm	Mon Jan 29 21:05:02 2007
@@ -0,0 +1,253 @@
+use warnings;
+use strict;
+
+=head1 NAME
+
+Jifty::Action::Record::Search
+
+=head1 DESCRIPTION
+
+The class is a base class for L<Jifty::Action>s that serve to provide
+an interface to general searches through L<Jifty::Record> objects. To
+use it, subclass it and override the C<record_class> method to return
+the fully qualified name of the model to do searches over.
+
+=cut
+
+package Jifty::Action::Record::Search;
+use base qw/Jifty::Action::Record/;
+
+=head1 METHODS
+
+=head2 arguments
+
+Remove validators from arguments, as well as ``mandatory''
+restrictions. Remove any arguments that render as password fields, or
+refer to collections.
+
+Generate additional search arguments for each field based on the
+following criteria:
+
+=over 4
+
+=item C<text>, C<char> or C<varchar> fields
+
+Create C<field>_contains and C<field>_lacks arguments
+
+=item C<date>, or C<timestamp> fields
+
+Create C<field>_before, C<field>_after, C<field>_since and
+C<field>_until arguments.
+
+=item C<integer>, C<float>, C<double>, C<decimal> or C<numeric> fields
+
+Generate C<field>_lt, C<field>_gt, C<field>_le and C<field>_ge arguments, as
+well as a C<field>_dwim field that accepts a prefixed comparison operator in
+the search value, such as C<< >100 >> and C<< !100 >>.
+
+=back
+
+=cut
+
+sub arguments {
+    my $self = shift;
+    return $self->_cached_arguments if $self->_cached_arguments;
+    
+    my $args = $self->SUPER::arguments;
+    for my $field (keys %$args) {
+        
+        my $info = $args->{$field};
+
+        my $column = $self->record->column($field);
+        # First, modify the ``exact match'' search field (same name as
+        # the original argument)
+
+        delete $info->{validator};
+        delete $info->{mandatory};
+
+        if($info->{valid_values}) {
+            my $valid_values = $info->{valid_values};
+
+            local $@;
+            $info->{valid_values} = $valid_values = (eval { [ @$valid_values ] } || [$valid_values]);
+
+            # For radio display, display an "any" label as empty choices looks weird
+            if (lc $info->{render_as} eq 'radio') {
+                if (@$valid_values > 1) {
+                    unshift @$valid_values, { display => _("(any)"), value => '' };
+                    $info->{default_value} ||= '';
+                }
+                else {
+                    # We've got only one choice anyway...
+                    $info->{default_value} ||= $valid_values->[0];
+                }
+            }
+            else {
+                unshift @$valid_values, "";
+            }
+        }
+
+        if(lc $info->{'render_as'} eq 'password') {
+            delete $args->{$field};
+            next;
+        }
+
+        warn "No column for: $field" unless($column);
+        
+        if(defined(my $refers_to = $column->refers_to)) {
+            delete $args->{$field}
+             if UNIVERSAL::isa($refers_to, 'Jifty::Collection');
+        }
+        # XXX TODO: What about booleans? Checkbox doesn't quite work,
+        # since there are three choices: yes, no, either.
+
+        # Magic _id refers_to columns
+        next if($field =~ /^(.*)_id$/ && $self->record->column($1));
+
+        my $label = $info->{label} || $field;
+        $args->{"${field}_not"} = { %$info, label => _("%1 is not", $label) };
+        my $type = lc($column->type);
+        if($type =~ /(?:text|char)/) {
+            $info->{render_as} = 'text';
+            $args->{"${field}_contains"} = { %$info, label => _("%1 contains", $label) };
+            $args->{"${field}_lacks"} = { %$info, label => _("%1 lacks", $label) };
+        } elsif($type =~ /(?:date|time)/) {
+            $args->{"${field}_after"} = { %$info, label => _("%1 after", $label) };
+            $args->{"${field}_before"} = { %$info, label => _("%1 before", $label) };
+            $args->{"${field}_since"} = { %$info, label => _("%1 since", $label) };
+            $args->{"${field}_until"} = { %$info, label => _("%1 until", $label) };
+        } elsif(    $type =~ /(?:int|float|double|decimal|numeric)/
+                && !$column->refers_to) {
+            $args->{"${field}_gt"} = { %$info, label => _("%1 greater than", $label) };
+            $args->{"${field}_lt"} = { %$info, label => _("%1 less than", $label) };
+            $args->{"${field}_ge"} = { %$info, label => _("%1 greater or equal to", $label) };
+            $args->{"${field}_le"} = { %$info, label => _("%1 less or equal to", $label) };
+            $args->{"${field}_dwim"} = { %$info, hints => _('!=>< allowed') };
+        }
+    }
+
+    $args->{contains} = { type => 'text', label => _('Any field contains') };
+    $args->{lacks} = { type => 'text', label => _('No field contains') };
+
+    return $self->_cached_arguments($args);
+}
+
+=head2 take_action
+
+Return a collection with the result of the search specified by the
+given arguments.
+
+We interpret a C<undef> argument as SQL C<NULL>, and ignore empty or
+non-present arguments.
+
+=cut
+
+sub take_action {
+    my $self = shift;
+
+    my $collection = Jifty::Collection->new(
+        record_class => $self->record_class,
+        current_user => $self->record->current_user
+    );
+
+    $collection->unlimit;
+
+    for my $field (grep {$self->has_argument($_)} $self->argument_names) {
+        next if $field eq 'contains';
+        my $value = $self->argument_value($field);
+        
+        my $column = $self->record->column($field);
+        my $op = undef;
+        
+        if (!$column) {
+            # If we don't have a column, this is a comparison or
+            # substring search. Skip undef values for those, since
+            # NULL makes no sense.
+            next unless defined($value);
+            next if $value =~ /^\s*$/;
+
+            if ($field =~ m{^(.*)_([[:alpha:]]+)$}) {
+                $field = $1;
+                $op = $2;
+                if($op eq 'not') {
+                    $op = '!=';
+                } elsif($op eq 'contains') {
+                    $op = 'LIKE';
+                    $value = "%$value%";
+                } elsif($op eq 'lacks') {
+                    $op = 'NOT LIKE';
+                    $value = "%$value%";
+                } elsif($op eq 'after' || $op eq 'gt') {
+                    $op = '>';
+                } elsif($op eq 'before' || $op eq 'lt') {
+                    $op = '<';
+                } elsif($op eq 'since' || $op eq 'ge') {
+                    $op = '>=';
+                } elsif($op eq 'until' || $op eq 'le') {
+                    $op = '<=';
+                } elsif($op eq 'dwim') {
+                    $op = '=';
+                    if (defined($value) and $value =~ s/^\s*([<>!=]{1,2})\s*//) {
+                        $op = $1;
+                        $op = '!=' if $op eq '!';
+                        $op = '=' if $op eq '==';
+                    }
+                }
+            } else {
+                next;
+            }
+        }
+        
+        if(defined($value)) {
+            next if $value =~ /^\s*$/;
+           
+            if ($op && $op =~ /^(?:!=|NOT LIKE)$/) {
+                $collection->limit( column   => $field, value    => $value, operator => $op || "=", entry_aggregator => 'OR', $op ? (case_sensitive => 0) : (),);
+                $collection->limit( column   => $field, value    => 'NULL', operator => 'IS');
+            } else { 
+
+            
+            $collection->limit(
+                column   => $field,
+                value    => $value,
+                operator => $op || "=",
+                entry_aggregator => 'AND',
+                $op ? (case_sensitive => 0) : (),
+               );
+
+            } 
+
+
+        } else {
+            $collection->limit(
+                column   => $field,
+                value    => 'NULL',
+                operator => 'IS'
+               );
+        }
+    }
+
+    if($self->has_argument('contains')) {
+        my $any = $self->argument_value('contains');
+        for my $col ($self->record->columns) {
+            if($col->type =~ /(?:text|varchar)/) {
+                $collection->limit(column   => $col->name,
+                                   value    => "%$any%",
+                                   operator => 'LIKE',
+                                   entry_aggregator => 'OR',
+                                   subclause => 'contains');
+            }
+        }
+    }
+
+    $self->result->content(search => $collection);
+    $self->result->success;
+}
+
+=head1 SEE ALSO
+
+L<Jifty::Action::Record>, L<Jifty::Collection>
+
+=cut
+
+1;

Added: jifty/branches/schema-plugins/lib/Jifty/Action/Record/Update.pm
==============================================================================
--- (empty file)
+++ jifty/branches/schema-plugins/lib/Jifty/Action/Record/Update.pm	Mon Jan 29 21:05:02 2007
@@ -0,0 +1,159 @@
+use warnings;
+use strict;
+
+package Jifty::Action::Record::Update;
+
+=head1 NAME
+
+Jifty::Action::Record::Update - Automagic update action
+
+=head1 DESCRIPTION
+
+This class is used as the base class for L<Jifty::Action>s that are
+merely updating L<Jifty::Record> objects.  To use it, subclass it and
+override the C<record_class> method to return the name of the
+L<Jifty::Record> subclass that this action should update.
+
+=cut
+
+use base qw/Jifty::Action::Record/;
+
+=head1 METHODS
+
+=head2 arguments
+
+Overrides the L<Jifty::Action::Record/arguments> method to further
+specify that all of the primary keys B<must> have values when
+submitted; that is, they are
+L<constructors|Jifty::Manual::Glossary/constructors>.
+
+=cut
+
+sub arguments {
+    my $self = shift;
+    my $arguments = $self->SUPER::arguments(@_);
+
+    for my $column ( $self->record->columns ) {
+        if ( not $column->writable and $column->readable ) {
+            $arguments->{$column->name}{'render_mode'} = 'read';
+        }
+    }
+
+    for my $pk (@{ $self->record->_primary_keys }) {
+        $arguments->{$pk}{'constructor'} = 1;
+        $arguments->{$pk}{'mandatory'} = 1;
+        # XXX TODO IS THERE A BETTER WAY TO NOT RENDER AN ITEM IN arguments
+        $arguments->{$pk}{'render_as'} = 'Unrendered'; 
+        # primary key fields should always be hidden fields
+    }
+    return $arguments;
+}
+
+=head2 validate_arguments
+
+We only need to validate arguments that got B<submitted> -- thus, a
+mandatory argument that isn't submitted isn't invalid, as it's not
+going to change the record.  This is opposed to the behavior inherited
+from L<Jifty::Action>, where mandatory arguments B<must> be present
+for the action to run.
+
+However, constructor arguments are still required.
+
+=cut
+
+sub _validate_arguments {
+    my $self = shift;
+
+    $self->_validate_argument($_) for grep {
+        $self->has_argument($_)
+            or $self->arguments->{$_}->{constructor}
+    } $self->argument_names;
+
+    return $self->result->success;
+}
+
+=head2 take_action
+
+Overrides the virtual C<take_action> method on L<Jifty::Action> to
+call the appropriate C<Jifty::Record>'s C<set_> methods when the
+action is run, thus updating the object in the database.
+
+=cut
+
+sub take_action {
+    my $self = shift;
+    my $changed = 0;
+
+    my $event_info = $self->_setup_event_before_action();
+
+    for my $field ( $self->argument_names ) {
+        # Skip values that weren't submitted
+        next unless $self->has_argument($field);
+
+        my $column = $self->record->column($field);
+
+        # Skip nonexistent fields
+        next unless $column;
+
+        # Grab the value
+        my $value = $self->argument_value($field);
+
+        # Boolean and integer fields should be set to NULL if blank.
+        # (This logic should be moved into SB or something.)
+        $value = undef
+            if ( defined $column->type and ( $column->type =~ /^bool/i || $column->type =~ /^int/i )
+            and defined $value and $value eq '' );
+
+        # Skip file uploads if blank
+        next if lc $self->arguments->{$field}{render_as} eq "upload"
+          and (not defined $value or not ref $value);
+
+        if (ref $value eq "Fh") { # CGI.pm's "lightweight filehandle class"
+            local $/;
+            binmode $value;
+            $value = scalar <$value>;
+        }
+
+        # Skip fields that have not changed
+        my $old = $self->record->$field;
+        # XXX TODO: This ignore "by" on columns
+        $old = $old->id if ref($old) and $old->isa( 'Jifty::Record' );
+    
+        # if both the new and old values are defined and equal, we don't want to change em
+        # XXX TODO "$old" is a cheap hack to scalarize datetime objects
+        next if ( defined $old and defined $value and "$old" eq "$value" );
+
+        # If _both_ the values are ''
+        next if (  (not defined $old or not length $old)
+                    and ( not defined $value or not length $value ));
+
+        my $setter = "set_$field";
+        my ( $val, $msg ) = $self->record->$setter( $value );
+        $self->result->field_error($field, $msg)
+          if not $val and $msg;
+
+        $changed = 1 if $val;
+    }
+
+    $self->report_success
+      if $changed and not $self->result->failure;
+
+    $self->_setup_event_after_action($event_info);
+
+    return 1;
+}
+
+=head2 report_success
+
+Sets the L<Jifty::Result/message> to default success message,
+"Updated". Override this if you want to report some other more
+user-friendly result.
+
+=cut
+
+sub report_success {
+    my $self = shift;
+    $self->result->message(_("Updated"))
+}
+
+1;

Added: jifty/branches/schema-plugins/lib/Jifty/Action/Redirect.pm
==============================================================================
--- (empty file)
+++ jifty/branches/schema-plugins/lib/Jifty/Action/Redirect.pm	Mon Jan 29 21:05:02 2007
@@ -0,0 +1,66 @@
+use warnings;
+use strict;
+
+=head1 NAME
+
+Jifty::Action::Redirect - Redirect the browser
+
+=cut
+
+package Jifty::Action::Redirect;
+use base qw/Jifty::Action/;
+
+=head2 new
+
+By default, redirect actions happen as late as possible in the run
+order.  Defaults the L<Jifty::Action/order> to be 100 so it runs later
+than most actions.
+
+=cut
+
+sub new {
+    my $class = shift;
+    my $self = $class->SUPER::new(@_);
+
+    # XXX TODO This is wrong -- it should be -1 or some equivilent, so
+    # it is sorted last all the time.
+    $self->order(100) unless defined $self->order;
+    return $self;
+}
+
+=head2 arguments
+
+The only argument to redirect is the C<url> to redirect to.
+
+=cut
+
+sub arguments {
+        {
+            url => { constructor => 1 },
+        }
+
+}
+
+=head2 take_action
+
+If the other actions in the request have been a success so far,
+redirects to the provided C<url>.  The redirect preserves all of the
+L<Jifty::Result>s for this action, in case the destination page wishes
+to inspect them.
+
+=cut
+
+sub take_action {
+    my $self = shift;
+    return 1 unless ($self->argument_value('url'));
+    return 0 unless Jifty->web->response->success;
+
+    my $page = $self->argument_value('url');
+
+    Jifty->web->next_page($page);
+    Jifty->web->force_redirect(1);
+    return 1;
+}
+
+1;
+

Added: jifty/branches/schema-plugins/lib/Jifty/Bootstrap.pm
==============================================================================
--- (empty file)
+++ jifty/branches/schema-plugins/lib/Jifty/Bootstrap.pm	Mon Jan 29 21:05:02 2007
@@ -0,0 +1,33 @@
+use warnings;
+use strict;
+
+=head1 NAME
+
+Jifty::Bootstrap - Insert initial data into your database
+
+=head1 DESCRIPTION
+
+C<Jifty::Bootstrap> is an abstract base class for your application's
+bootstrapping.  Use it to set up initial data in your database when
+your application is first installed.
+
+=cut
+
+package Jifty::Bootstrap;
+
+use base qw/Jifty::Object/;
+
+=head2 run
+
+C<run> is the workhorse method for the Bootstrap class.  This takes care of
+setting up internal data structures and initializing things in an
+application-dependent manner.
+
+=cut
+
+sub run { 
+    1;
+}
+
+
+1;

Added: jifty/branches/schema-plugins/lib/Jifty/ClassLoader.pm
==============================================================================
--- (empty file)
+++ jifty/branches/schema-plugins/lib/Jifty/ClassLoader.pm	Mon Jan 29 21:05:02 2007
@@ -0,0 +1,306 @@
+use warnings;
+use strict;
+
+package Jifty::ClassLoader;
+
+=head1 NAME
+
+Jifty::ClassLoader - Loads the application classes
+
+=head1 DESCRIPTION
+
+C<Jifty::ClassLoader> loads all of the application's model and action
+classes, generating classes on the fly for Collections of pre-existing
+models.
+
+=head2 new
+
+Returns a new ClassLoader object.  Doing this installs a hook into
+C<@INC> that allows L<Jifty::ClassLoader> to dynamically create
+needed classes if they do not exist already.  This works because if
+use/require encounters a blessed reference in C<@INC>, it will
+invoke the INC method with the name of the module it is searching
+for on the reference.
+
+Takes one mandatory argument, C<base>, which should be the the
+application's base path; all of the classes under this will be
+automatically loaded.
+
+=cut
+
+sub new {
+    my $class = shift;
+    my $self = bless {@_}, $class;
+
+    push @INC, $self;
+    return $self;
+}
+
+=head2 INC
+
+The hook that is called when a module has been C<require>'d that
+cannot be found on disk.  The following stub classes are
+auto-generated:
+
+=over
+
+=item I<Application>
+
+An empty application base class is created that doen't provide any
+methods or inherit from anything.
+
+=item I<Application>::Record
+
+An empty class that descends from L<Jifty::Record> is created.
+
+=item I<Application>::Event
+
+An empty class that descends from L<Jifty::Event> is created.
+
+=item I<Application>::Collection
+
+An empty class that descends from L<Jifty::Collection> is created.
+
+=item I<Application>::Notification
+
+An empty class that descends from L<Jifty::Notification>.
+
+=item I<Application>::Dispatcher
+
+An empty class that descends from L<Jifty::Dispatcher>.
+
+=item I<Application>::Handle
+
+An empty class that descends from L<Jifty::Handle> is created.
+
+=item I<Application>::Bootstrap
+
+An empty class that descends from L<Jifty::Bootstrap>.
+
+=item I<Application>::Upgrade
+
+An empty class that descends from L<Jifty::Upgrade>.
+
+=item I<Application>::CurrentUser
+
+An empty class that descends from L<Jifty::CurrentUser>.
+
+=item I<Application>::Model::I<Anything>Collection
+
+If C<I<Application>::Model::I<Something>> is a valid model class, then
+it creates a subclass of L<Jifty::Collection> whose C<record_class> is
+C<I<Application>::Model::I<Something>>.
+
+=item I<Application>::Action::(Create or Update or Delete)I<Anything>
+
+If C<I<Application>::Model::I<Something>> is a valid model class, then
+it creates a subclass of L<Jifty::Action::Record::Create>,
+L<Jifty::Action::Record::Update>, or L<Jifty::Action::Record::Delete>
+whose I<record_class> is C<I<Application>::Model::I<Something>>.
+
+=back
+
+=cut
+
+# This subroutine's name is fully qualified, as perl will ignore a 'sub INC'
+sub Jifty::ClassLoader::INC {
+    my ( $self, $module ) = @_;
+    my $base = $self->{base};
+    return undef unless ( $module and $base );
+
+    # Canonicalize $module to :: style rather than / and .pm style;
+    $module =~ s/.pm$//;
+    $module =~ s{/}{::}g;
+
+    # The quick check
+    return undef unless $module =~ m!^$base!;
+
+    if ( $module =~ m!^(?:$base)$! ) {
+        return $self->return_class(
+            "use warnings; use strict; package " . $base . ";\n" . " 1;" );
+    }
+#    elsif ( $module =~ m!^(?:$base)::Action$! ) {
+#        return $self->return_class(
+#                  "use warnings; use strict; package $module;\n"
+#                . "use base qw/Jifty::Action/; sub _autogenerated { 1 };\n"
+#                . "1;" );
+#    }
+    elsif ( $module =~ m!^(?:$base)::(Record|Collection|Notification|Dispatcher|Bootstrap|Upgrade|Handle|Event|Event::Model|Action::Record::\w+)$! ) {
+        return $self->return_class(
+                  "use warnings; use strict; package $module;\n"
+                . "use base qw/Jifty::$1/; sub _autogenerated { 1 };\n"
+                . "1;" );
+    } elsif ( $module =~ m!^(?:$base)::CurrentUser$! ) {
+        return $self->return_class(
+                  "use warnings; use strict; package $module;\n"
+                . "use base qw/Jifty::CurrentUser/; sub _autogenerated { 1 };\n"
+                . "1;" );
+    } elsif ( $module =~ m!^(?:$base)::Model::(\w+)Collection$! ) {
+        return $self->return_class(
+                  "use warnings; use strict; package $module;\n"
+                . "use base qw/@{[$base]}::Collection/;\n"
+                . "sub record_class { '@{[$base]}::Model::$1' }\n"
+                . "1;" );
+    } elsif ( $module =~ m!^(?:$base)::Event::Model::([^\.]+)$! ) {
+        my $modelclass = $base . "::Model::" . $1;
+        Jifty::Util->require($modelclass);
+
+        return undef unless eval { $modelclass->table };
+
+        return $self->return_class(
+                  "use warnings; use strict; package $module;\n"
+                . "use base qw/${base}::Event::Model/;\n"
+                . "sub record_class { '$modelclass' };\n"
+                . "sub autogenerated { 1 };\n"
+                . "1;" );
+    } elsif ( $module =~ m!^(?:$base)::Action::(Create|Update|Delete|Search)([^\.]+)$! ) {
+        my $modelclass = $base . "::Model::" . $2;
+
+        Jifty::Util->require($modelclass);
+
+        return undef unless eval { $modelclass->table };
+
+        return $self->return_class(
+                  "use warnings; use strict; package $module;\n"
+                . "use base qw/$base\::Action::Record::$1/;\n"
+                . "sub record_class { '$modelclass' };\n"
+                . "sub autogenerated { 1 };\n"
+                . "1;" );
+    }
+    return undef;
+}
+
+=head2 return_class CODE
+
+A helper method; takes CODE as a string and returns an open filehandle
+containing that CODE.
+
+=cut
+
+sub return_class {
+    my $self = shift;
+    my $content = shift;
+
+
+    open my $fh, '<', \$content;
+    return $fh;
+
+}
+
+=head2 require
+
+Loads all of the application's Actions and Models.  It additionally
+C<require>'s all Collections and Create/Update actions for each Model
+base class -- which will auto-create them using the above code if they
+do not exist on disk.
+
+=cut
+
+sub require {
+    my $self = shift;
+    
+    my $base = $self->{base};
+    # if we don't even have an application class, this trick will not work
+    return unless ($base); 
+    Jifty::Util->require($base);
+    Jifty::Util->require($base."::CurrentUser");
+
+    my %models;
+    
+
+    Jifty::Module::Pluggable->import(
+        search_path =>
+          [ map { $base . "::" . $_ } 'Model', 'Action', 'Notification', 'Event' ],
+        require => 1,
+        except  => qr/\.#/,
+        inner   => 0
+    );
+    $models{$_} = 1 for grep {/^($base)::Model::(.*)$/ and not /Collection$/} $self->plugins;
+    $self->models(sort keys %models);
+    for my $full ($self->models) {
+        $self->_require_model_related_classes($full);
+    }
+        
+}
+
+sub _require_model_related_classes {
+    my $self = shift;
+    my $full = shift;
+    my $base = $self->{base};
+        my($short) = $full =~ /::Model::(.*)/;
+        Jifty::Util->require($full . "Collection");
+        Jifty::Util->require($base . "::Action::" . $_ . $short)
+            for qw/Create Update Delete Search/;
+
+}
+
+
+=head2 require_classes_from_database
+
+Jifty supports model classes that aren't files on disk but instead records
+in your database. It's a little bit mind bending, but basically, you can
+build an application entirely out of the database without ever writing a 
+line of code(*). 
+
+* As of early 2007, this forward looking statement is mostly a lie. But we're 
+working on it.
+
+This method finds all database-backed models and instantiates jifty classes for 
+them it returns a list of classnames of the models it created.
+
+=cut
+
+sub require_classes_from_database {
+    my $self = shift;
+    my @instantiated;
+
+    require Jifty::Model::ModelClassCollection;
+    require Jifty::Model::ModelClass;
+    my $models = Jifty::Model::ModelClassCollection->new(current_user => Jifty::CurrentUser->superuser);
+    $models->unlimit();
+    while (my $model = $models->next) {
+        $model->instantiate();
+        $self->_require_model_related_classes($model->qualified_class);
+    }
+}
+
+=head2 models
+
+Accessor to the list of models this application has loaded.
+
+In scalar context, returns a mutable array reference; in list context,
+return the content of the array.
+
+=cut
+
+sub models {
+    my $self = shift;
+    if (@_) {
+        $self->{models} = ref($_[0]) ? $_[0] : \@_;
+    }
+    wantarray ? @{ $self->{models} ||= [] } : $self->{models};
+}
+
+
+=head1 Writing your own classes
+
+If you require more functionality than is provided by the classes
+created by ClassLoader then you should create a class with the
+appropriate name and add your extra logic to it.
+
+For example you will almost certainly want to write your own
+dispatcher, so something like:
+
+ package MyApp::Dispatcher;
+ use Jifty::Dispatcher -base;
+
+If you want to add some application specific behaviour to a model's
+collection class, say for the User model, create F<UserCollection.pm>
+in your applications Model directory.
+
+ package MyApp::Model::UserCollection;
+ use base 'MyApp::Collection';
+
+=cut
+
+1;

Added: jifty/branches/schema-plugins/lib/Jifty/Client.pm
==============================================================================
--- (empty file)
+++ jifty/branches/schema-plugins/lib/Jifty/Client.pm	Mon Jan 29 21:05:02 2007
@@ -0,0 +1,345 @@
+use strict;
+use warnings;
+
+package Jifty::Client;
+use base qw/WWW::Mechanize/;
+
+$ENV{'http_proxy'} = ''; # Otherwise WWW::Mechanize tries to go through your HTTP proxy
+
+use Jifty::YAML;
+use HTTP::Cookies;
+use XML::XPath;
+use Hook::LexWrap;
+use List::Util qw(first);
+use Carp;
+
+
+=head1 NAME
+
+Jifty::Client --- Subclass of L<WWW::Mechanize> with extra Jifty features
+
+=head1 DESCRIPTION
+
+This module is a base for building robots to interact with Jifty applications.
+It currently contains much overlapping code with C<Jifty::Test::WWW::Mechanize>,
+except that it does not inherit from C<Test::WWW::Mechanize>.
+
+Expect this code to be refactored in the near future.
+
+=head1 METHODS
+
+=head2 new
+
+Overrides L<WWW::Mechanize>'s C<new> to automatically give the
+bot a cookie jar.
+
+=cut
+
+sub new {
+    my $class = shift;
+    my $self = $class->SUPER::new(@_);
+    $self->cookie_jar(HTTP::Cookies->new);
+    return $self;
+} 
+
+=head2 moniker_for ACTION, FIELD1 => VALUE1, FIELD2 => VALUE2
+
+Finds the moniker of the first action of type I<ACTION> whose
+"constructor" field I<FIELD1> is I<VALUE1>, and so on.
+
+=cut
+
+sub moniker_for {
+  my $self = shift;
+  my $action = Jifty->api->qualify(shift);
+  my %args = @_;
+
+  for my $f ($self->forms) {
+  INPUT: 
+    for my $input ($f->inputs) {
+      if ($input->type eq "hidden" and $input->name =~ /^J:A-(?:\d+-)?(.*)/ and $input->value eq $action) {
+
+        my $moniker = $1;
+
+        for my $id (keys %args) {
+          my $idfield = $f->find_input("J:A:F:F-$id-$moniker");
+          next INPUT unless $idfield and $idfield->value eq $args{$id};
+        }
+
+        return $1;
+      }
+    }
+  }
+  return undef;
+}
+
+=head2 fill_in_action MONIKER, FIELD1 => VALUE1, FIELD2 => VALUE2, ...
+
+Finds the fields on the current page with the names FIELD1, FIELD2,
+etc in the MONIKER action, and fills them in.  Returns the
+L<HTML::Form> object of the form that the action is in, or undef if it
+can't find all the fields.
+
+=cut
+
+sub fill_in_action {
+    my $self = shift;
+    my $moniker = shift;
+    my %args = @_;
+
+    my $action_form = $self->action_form($moniker, keys %args);
+    return unless $action_form;
+
+    for my $arg (keys %args) {
+        my $input = $action_form->find_input("J:A:F-$arg-$moniker");
+        unless ($input) {
+            return;
+        } 
+        $input->value($args{$arg});
+    } 
+
+    return $action_form;
+}
+
+=head2 action_form MONIKER [ARGUMENTNAMES]
+
+Returns the form (as an L<HTML::Form> object) corresponding to the
+given moniker (which also contains inputs for the given
+argumentnames), and also selects it as the current form.  Returns
+undef if it can't be found.
+
+=cut
+
+sub action_form {
+    my $self = shift;
+    my $moniker = shift;
+    my @fields = @_;
+    Carp::confess("No moniker") unless $moniker;
+
+    my $i;
+    for my $form ($self->forms) {
+        no warnings 'uninitialized';
+
+        $i++;
+        next unless first {   $_->name =~ /J:A-(?:\d+-)?$moniker/
+                           && $_->type eq "hidden" }
+                        $form->inputs;
+        next if grep {not $form->find_input("J:A:F-$_-$moniker")} @fields;
+
+        $self->form_number($i); #select it, for $mech->submit etc
+        return $form;
+    } 
+    return;
+} 
+
+=head2 action_field_value MONIKER, FIELD
+
+Finds the fields on the current page with the names FIELD in the
+action MONIKER, and returns its value, or undef if it can't be found.
+
+=cut
+
+sub action_field_value {
+    my $self = shift;
+    my $moniker = shift;
+    my $field = shift;
+
+    my $action_form = $self->action_form($moniker, $field);
+    return unless $action_form;
+    
+    my $input = $action_form->find_input("J:A:F-$field-$moniker");
+    return unless $input;
+    return $input->value;
+}
+
+=head2 send_action CLASS ARGUMENT => VALUE, [ ... ]
+
+Sends a request to the server via the webservices API, and returns the
+L<Jifty::Result> of the action.  C<CLASS> specifies the class of the
+action, and all parameters thereafter supply argument keys and values.
+
+The URI of the page is unchanged after this; this is accomplished by
+using the "back button" after making the webservice request.
+
+=cut
+
+sub send_action {
+    my $self = shift;
+    my $class = shift;
+    my %args = @_;
+
+
+    my $uri = $self->uri->clone;
+    $uri->path("__jifty/webservices/yaml");
+
+    my $request = HTTP::Request->new(
+        POST => $uri,
+        [ 'Content-Type' => 'text/x-yaml' ],
+        Jifty::YAML::Dump(
+            {   path => $uri->path,
+                actions => {
+                    action => {
+                        moniker => 'action',
+                        class   => $class,
+                        fields  => \%args
+                    }
+                }
+            }
+        )
+    );
+    my $result = $self->request( $request );
+    my $content = eval { Jifty::YAML::Load($result->content)->{action} } || undef;
+    $self->back;
+    return $content;
+}
+
+=head2 fragment_request PATH ARGUMENT => VALUE, [ ... ]
+
+Makes a request for the fragment at PATH, using the webservices API,
+and returns the string of the result.
+
+=cut
+
+sub fragment_request {
+    my $self = shift;
+    my $path = shift;
+    my %args = @_;
+
+    my $uri = $self->uri->clone;
+    $uri->path("__jifty/webservices/xml");
+
+    my $request = HTTP::Request->new(
+        POST => $uri,
+        [ 'Content-Type' => 'text/x-yaml' ],
+        Jifty::YAML::Dump(
+            {   path => $uri->path,
+                fragments => {
+                    fragment => {
+                        name  => 'fragment',
+                        path  => $path,
+                        args  => \%args
+                    }
+                }
+            }
+        )
+    );
+    my $result = $self->request( $request );
+    use XML::Simple;
+    my $content = eval { XML::Simple::XMLin($result->content, SuppressEmpty => '')->{fragment}{content} } || '';
+    $self->back;
+    return $content;
+}
+
+
+# When it sees something like
+# http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd as a DOCTYPE, this will make
+# it open static/dtd/xhtml1-strict.dtd instead -- great for offline hacking!
+ 
+# This "require" is just to give us something to hook on to, and to prevent a
+# future require from taking effect.
+require 'XML/Parser/LWPExternEnt.pl';
+wrap 'XML::Parser::lwp_ext_ent_handler', pre => sub {
+    my $root = Jifty::Util->share_root;
+    $_[2] =~ s{ \A .+ / ([^/]+) \z }{$root/dtd/$1}xms;
+    open my $fh, '<', $_[2] or die "can't open $_[2]: $!";
+    my $content = do {local $/; <$fh>};
+    close $fh;
+    $_[-1] = $content; # override return value
+};
+wrap 'XML::Parser::lwp_ext_ent_cleanup', pre => sub {
+    $_[-1] = 1; # just return please
+};
+
+=head2 field_error_text MONIKER, FIELD
+
+Finds the error span on the current page for the name FIELD in the
+action MONIKER, and returns the text (tags stripped) from it.  (If the
+field can't be found.
+
+=cut
+
+sub field_error_text {
+    my $self = shift;
+    my $moniker = shift;
+    my $field = shift;
+
+    my $xp = XML::XPath->new( xml => $self->content );
+
+    my $id = "errors-J:A:F-$field-$moniker";
+
+    my $nodeset = $xp->findnodes(qq{//span[\@id = "$id"]});
+    return unless $nodeset->size == 1;
+    
+    # Note that $xp->getNodeText does not actually return undef for nodes that
+    # aren't found, even though it's documented to.  Thus the workaround above.
+    return $xp->getNodeText(qq{//span[\@id = "$id" ]});
+} 
+
+=head2 uri
+
+L<WWW::Mechanize> has a bug where it returns the wrong value for
+C<uri> after redirect.  This fixes that.  See
+http://rt.cpan.org/NoAuth/Bug.html?id=9059
+
+=cut
+
+sub uri { shift->response->request->uri }
+
+=head2 session
+
+Returns the server-side L<Jifty::Web::Session> object associated with
+this Mechanize object.
+
+=cut
+
+sub session {
+    my $self = shift;
+
+    return undef unless $self->cookie_jar->as_string =~ /JIFTY_SID_\d+=([^;]+)/;
+
+    my $session = Jifty::Web::Session->new;
+    $session->load($1);
+    return $session;
+}
+
+=head2 continuation [ID]
+
+Returns the current continuation of the Mechanize object, if any.  Or,
+given an ID, returns the continuation with that ID.
+
+=cut
+
+sub continuation {
+    my $self = shift;
+
+    my $session = $self->session;
+    return undef unless $session;
+    
+    my $id = shift;
+    ($id) = $self->uri =~ /J:(?:C|CALL|RETURN)=([^&;]+)/ unless $id;
+
+    return $session->get_continuation($id);
+}
+
+=head2 current_user
+
+Returns the L<Jifty::CurrentUser> object or descendant, if any.
+
+=cut
+
+sub current_user {
+    my $self = shift;
+
+    my $session = $self->session;
+    return undef unless $session;
+
+    my $id = $session->get('user_id');
+    my $object = Jifty->app_class("CurrentUser")->new();
+    my $user = $session->get('user_ref')->new( current_user => $object );
+    $user->load_by_cols( id => $id );
+    $object->user_object($user);
+
+    return $object;
+}
+
+1;

Added: jifty/branches/schema-plugins/lib/Jifty/Collection.pm
==============================================================================
--- (empty file)
+++ jifty/branches/schema-plugins/lib/Jifty/Collection.pm	Mon Jan 29 21:05:02 2007
@@ -0,0 +1,121 @@
+use warnings;
+use strict;
+
+package Jifty::Collection;
+
+=head1 NAME
+
+Jifty::Collection - Collection of Jifty::Record objects
+
+=head1 SYNOPSIS
+
+  package Foo::Model::BarCollection
+  use base qw/Jifty::Collection/;
+
+=head1 DESCRIPTION
+
+This is a wrapper over L<Jifty::DBI::Collection> that at the same time
+is a L<Jifty::Object>.  To use it, subclass it.
+
+Alternatively, an 'anonymous' collection can be made by creating a new
+C<Jifty::Collection> object, and calling
+C<record_class('Application::Model::Foo')> or similar on it.
+
+In addition, each L<Jifty::Collection> includes a L<Data::Page> object
+to help with calculations related to paged data.  You should B<not>
+call the C<first_row> and C<rows_per_page> methods from
+L<Jifty::DBI::Collection> on a L<Jifty::Collection>.  Instead, if
+you'd like to use paging, you should use the C<set_page_info> method
+to B<set> the number of records per page and first record on the
+current page, and you should use the L<Data::Page> object returned by
+the C<pager> method to B<get> information related to paging.
+
+=cut
+
+use base qw/Jifty::Object Jifty::DBI::Collection Class::Accessor::Fast/;
+use Data::Page;
+
+=head1 MODEL
+
+=head2 pager
+
+Returns a L<Data::Page> object associated with this collection.  This
+object defaults to 10 entries per page.  You should use only use
+L<Data::Page>  methods on this object to B<get> information about paging,
+not to B<set> it; use C<set_page_info> to set paging information.
+
+=head2 results_are_readable
+
+If your results from the query is guaranteed to be readable by
+current_user, you can create the collection with
+C<results_are_readable => 1>.  This is cause check_read_rights to
+bypass normal current_user_can checks.
+
+=cut
+
+__PACKAGE__->mk_accessors(qw(pager results_are_readable));
+
+=head2 add_record
+
+Only add records to the collection that we can read
+
+=cut
+
+sub add_record {
+    my $self = shift;
+    my($record) = (@_);
+
+    $record->_is_readable(1)
+        if $self->results_are_readable;
+
+    $self->SUPER::add_record($record)
+        if $self->results_are_readable || $record->check_read_rights;
+}
+
+sub _init {
+    my $self = shift;
+
+    my %args = (
+        record_class => undef,
+        current_user => undef,
+        results_are_readable => undef,
+        @_
+    );
+
+    $self->_get_current_user(%args);
+    $self->record_class($args{record_class}) if defined $args{record_class};
+    $self->results_are_readable($args{results_are_readable});
+    unless ($self->current_user) {
+        Carp::confess("Collection created without a current user");
+    }
+    $self->table($self->new_item->table());
+    $self->SUPER::_init(%args);
+}
+
+=head2 implicit_clauses
+
+Defaults to ordering by the C<id> column.
+
+=cut
+
+sub implicit_clauses {
+    my $self = shift;
+    $self->order_by( column => 'id',order => 'asc');
+}
+
+=head2 new_item
+
+Overrides L<Jifty::DBI::Collection>'s new_item to pass in the current
+user.
+
+=cut
+
+sub new_item {
+    my $self = shift;
+    my $class =$self->record_class();
+
+    # We do this as a performance optimization, so we don't need to do the stackwalking to find it
+    return $class->new(current_user => $self->current_user);
+}
+
+1;

Added: jifty/branches/schema-plugins/lib/Jifty/Config.pm
==============================================================================
--- (empty file)
+++ jifty/branches/schema-plugins/lib/Jifty/Config.pm	Mon Jan 29 21:05:02 2007
@@ -0,0 +1,364 @@
+use warnings;
+use strict;
+
+package Jifty::Config;
+
+=head1 NAME
+
+Jifty::Config -- wrap a jifty configuration file
+
+=head1 DESCRIPTION
+
+
+=cut
+
+use Jifty::Util;
+use Jifty::YAML;
+use File::Spec;
+use File::Basename;
+use Log::Log4perl;
+use Hash::Merge;
+Hash::Merge::set_behavior('RIGHT_PRECEDENT');
+
+use File::Basename();
+use base qw/Class::Accessor::Fast/;
+
+use vars qw/$CONFIG/;
+
+__PACKAGE__->mk_accessors(qw/stash/);
+
+=head1 METHODS
+
+=head2 new PARAMHASH
+
+This class method instantiates a new C<Jifty::Config> object. This
+object deals with configuration files.  
+
+PARAMHASH currently takes a single option
+
+=over
+
+=item load_config
+
+This boolean defaults to true. If true, L</load> will be called upon initialization.
+
+=back
+
+
+=cut
+
+sub new {
+    my $proto = shift;
+    my %args = ( load_config => 1,
+                 @_ 
+             );
+    my $self  = {};
+    bless $self, $proto;
+    $self->stash( {} );
+
+    $self->load() if ($args{'load_config'});
+    return $self;
+}
+
+=head2 load
+
+
+Jifty first loads the main
+configuration file for the application, looking for the
+C<JIFTY_CONFIG> environment variable or C<etc/config.yml> under the
+application's base directory.
+
+It uses the main configuration file to find a vendor configuration
+file -- if it doesn't find a framework variable named 'VendorConfig',
+it will use the C<JIFTY_VENDOR_CONFIG> environment variable.
+
+After loading the vendor configuration file (if it exists), the
+framework will look for a site configuration file, specified in either
+the framework's C<SiteConfig> or the C<JIFTY_SITE_CONFIG> environment
+variable. (Usually in C<etc/site_config.yml>.)
+
+After loading the site configuration file (if it exists), the
+framework will look for a test configuration file, specified in either
+the framework's C<TestConfig> or the C<JIFTY_TEST_CONFIG> environment
+variable.
+
+Values in the test configuration will clobber the site configuration.
+Values in the site configuration file clobber those in the vendor
+configuration file. Values in the vendor configuration file clobber
+those in the application configuration file.
+
+Once we're all done loading from files, several defaults are
+assumed based on the name of the application -- see L</guess>. 
+
+After we have the config file, we call the coderef in C<$Jifty::Config::postload>,
+if it exists.
+
+If the value begins and ends with %, converts it with
+C<Jifty::Util/absolute_path> to an absolute path.  (This is
+unnecessary for most configuration variables which specify files, but
+is needed for variables such as C<MailerArgs> that only sometimes
+specify files.)
+
+=cut
+
+sub load {
+    my $self = shift;
+
+    $self->stash( Hash::Merge::merge( $self->_default_config_files, $self->stash ));
+
+    my $file = $ENV{'JIFTY_CONFIG'} || Jifty::Util->app_root . '/etc/config.yml';
+
+    my $app;
+
+    # Override anything in the default guessed config with anything from a config file
+    if ( -f $file and -r $file ) {
+        $app = $self->load_file($file);
+        $app = Hash::Merge::merge( $self->stash, $app );
+
+        # Load the $app so we know where to find the vendor config file
+        $self->stash($app);
+    }
+    my $vendor = $self->load_file(
+        Jifty::Util->absolute_path(
+            $self->framework('VendorConfig') || $ENV{'JIFTY_VENDOR_CONFIG'}
+        )
+    );
+
+    # First, we load the app and vendor configs. This way, we can
+    # figure out if we have a special name for the siteconfig file
+    my $config = Hash::Merge::merge( $self->stash, $vendor );
+    $self->stash($config);
+
+
+    my $site = $self->load_file(
+        Jifty::Util->absolute_path(
+            $self->framework('SiteConfig') || $ENV{'JIFTY_SITE_CONFIG'}
+        )
+    );
+
+    $config = Hash::Merge::merge( $self->stash, $site );
+    $self->stash($config);
+
+    my $test = $self->load_file(
+        Jifty::Util->absolute_path(
+            $self->framework('TestConfig') || $ENV{'JIFTY_TEST_CONFIG'}
+        )
+    );
+    $config = Hash::Merge::merge( $self->stash, $test );
+    $self->stash($config);
+
+    # Merge guessed values in for anything we didn't explicitly define
+    # Whatever's in the stash overrides anything we guess
+    $self->stash( Hash::Merge::merge( $self->guess, $self->stash ));
+    
+    # There are a couple things we want to guess that we don't want
+    # getting stuck in a default config file for an app
+    $self->stash( Hash::Merge::merge( $self->defaults, $self->stash));
+
+    # Finally, check for global postload hooks (these are used by the
+    # test harness)
+    $self->$Jifty::Config::postload()
+      if $Jifty::Config::postload;
+}
+
+=head2 framework VARIABLE
+
+Get the framework configuration variable C<VARIABLE>.  
+
+=cut
+
+sub framework {
+    my $self = shift;
+    my $var  = shift;
+
+    $self->_get( 'framework', $var );
+}
+
+=head2 app VARIABLE
+
+Get the application configuration variable C<VARIABLE>.
+
+=cut
+
+sub app {
+    my $self = shift;
+    my $var  = shift;
+
+    $self->_get( 'application', $var );
+}
+
+sub _get {
+    my $self    = shift;
+    my $section = shift;
+    my $var     = shift;
+
+    return  $self->stash->{$section}->{$var} 
+}
+
+
+sub _default_config_files {
+    my $self = shift;
+    my $config  = {
+        framework => {
+            SiteConfig => 'etc/site_config.yml'
+        }
+    };
+    return $self->_expand_relative_paths($config);
+}
+
+
+=head2 guess
+
+Attempts to guess (and return) a configuration hash based solely
+on what we already know. (Often, in the complete absence of
+a configuration file).  It uses the name of the directory containing
+the Jifty binary as a default for C<ApplicationName> if it can't find one.
+
+=cut
+
+sub guess {
+    my $self = shift;
+
+    # Walk around a potential loop by calling guess to get the app name
+    my $app_name;
+    if (@_) {
+        $app_name = shift;
+    } elsif ($self->stash->{framework}->{ApplicationName}) {
+        $app_name =  $self->stash->{framework}->{ApplicationName};
+    } else {
+        $app_name =  Jifty::Util->default_app_name;
+    }
+
+    my $app_class =  $self->stash->{framework}->{ApplicationClass} ||$app_name;
+    $app_class =~ s/-/::/g;
+    my $db_name = lc $app_name;
+    $db_name =~ s/-/_/g;
+    my $app_uuid = Jifty::Util->generate_uuid;
+
+    my $guess = {
+        framework => {
+            AdminMode        => 1,
+            DevelMode        => 1,
+            ApplicationClass => $app_class,
+            ApplicationName  => $app_name,
+            ApplicationUUID  => $app_uuid,
+            LogLevel         => 'INFO',
+            PubSub           => {
+                Enable => undef,
+                Backend => 'Memcached',
+                    },
+            Database         => {
+                Database =>  $db_name,
+                Driver   => "SQLite",
+                Host     => "localhost",
+                Password => "",
+                User     => "",
+                Version  => "0.0.1",
+                RecordBaseClass => 'Jifty::DBI::Record::Cachable',
+                CheckSchema => '1'
+            },
+            Mailer     => 'Sendmail',
+            MailerArgs => [],
+            L10N       => {
+                PoDir => "share/po",
+            },
+            Plugins    => [],
+            Web        => {
+                Port => '8888',
+                BaseURL => 'http://localhost',
+                DataDir     => "var/mason",
+                StaticRoot   => "share/web/static",
+                TemplateRoot => "share/web/templates",
+                ServeStaticFiles => 1,
+                MasonConfig => {
+                    autoflush    => 0,
+                    error_mode   => 'fatal',
+                    error_format => 'text',
+                    default_escape_flags => 'h',
+                },
+                Globals      => [],
+            },
+        },
+    };
+
+    return $self->_expand_relative_paths($guess);
+
+}
+
+
+=head2 defaults
+
+We have a couple default values that shouldn't be included in the
+"guessed" config, as that routine is used when initializing a new 
+application. Generally, these are platform-specific file locations.
+
+=cut
+
+sub defaults {
+    my $self = shift;
+    return {
+        framework => {
+            L10N => {
+                DefaultPoDir => Jifty::Util->share_root . '/po',
+            },
+            Web => {
+                DefaultStaticRoot => Jifty::Util->share_root . '/web/static',
+                DefaultTemplateRoot => Jifty::Util->share_root . '/web/templates',
+            },
+        }
+    };
+
+}
+
+=head2 load_file PATH
+
+Loads a YAML configuration file and returns a hashref to that file's
+data.
+
+=cut
+
+sub load_file {
+
+    my $self = shift;
+    my $file = shift;
+
+    # only try to load files that exist
+    return {} unless ( $file && -f $file );
+    my $hashref = Jifty::YAML::LoadFile($file)
+        or die "I couldn't load config file $file: $!";
+
+    $hashref = $self->_expand_relative_paths($hashref);
+    return $hashref;
+}
+
+
+# Does a DFS, turning all leaves that look like C<%paths%> into absolute paths.
+sub _expand_relative_paths {
+    my $self  = shift;
+    my $datum = shift;
+
+    if ( ref $datum eq 'ARRAY' ) {
+        return [ map { $self->_expand_relative_paths($_) } @$datum ];
+    } elsif ( ref $datum eq 'HASH' ) {
+        for my $key ( keys %$datum ) {
+            my $new_val = $self->_expand_relative_paths( $datum->{$key} );
+            $datum->{$key} = $new_val;
+        }
+        return $datum;
+    } elsif ( ref $datum ) {
+        return $datum;
+    } else {
+        if ( defined $datum and $datum =~ /^%(.+)%$/ ) {
+            $datum = Jifty::Util->absolute_path($1);
+        }
+        return $datum;
+    }
+}
+
+=head1 AUTHOR
+
+Various folks at BestPractical Solutions, LLC.
+
+=cut
+
+1;

Added: jifty/branches/schema-plugins/lib/Jifty/Continuation.pm
==============================================================================
--- (empty file)
+++ jifty/branches/schema-plugins/lib/Jifty/Continuation.pm	Mon Jan 29 21:05:02 2007
@@ -0,0 +1,237 @@
+use warnings;
+use strict;
+
+package Jifty::Continuation;
+
+=head1 NAME
+
+Jifty::Continuation - Allows for basic continuation-based programming
+
+=head1 DESCRIPTION
+
+C<Jifty::Continuation> wraps up the information about a context that
+might have been expecting some sort of answer.  It allows one to
+re-visit that context later by providing the continuation again.
+Continuations are stored on the user's session.
+
+Continuations store a L<Jifty::Request> object and the
+L<Jifty::Response> object for the request.  They can also store
+arbitrary code to be run when the continuation is called.
+
+Continuations can also be arbitrarily nested.  This means that
+returning from one continuation will drop you into the continuation
+that is one higher in the stack.
+
+Continuations are generally created just before their request would
+take effect, activated by the presence of certain query parameters.
+The rest of the request is saved, its execution to be continued at a
+later time.
+
+Continuations are run after any actions have run.  When a continuation
+is run, it restores the request that it has saved away into it, and
+pulls into that request the values any return values that were
+specified when it was created.  The continuations code block, if any,
+is then called, and then the filled-in request is then passed to the
+L<Jifty::Dispatcher>.
+
+=cut
+
+
+use Storable 'dclone';
+
+use base qw/Class::Accessor::Fast/;
+
+__PACKAGE__->mk_accessors(qw(id parent
+                             request response code
+                             ));
+
+=head2 new PARAMHASH
+
+Saves a continuation at the current state.  Possible arguments in the
+C<PARAMHASH>:
+
+=over
+
+=item parent
+
+A L<Jifty::Continuation> object, or the C<id> of one.  This represents
+the continuation that this continuation should return to when it is
+called.  Defaults to the current continuation of the current
+L<Jifty::Request>.
+
+=item request
+
+The L<Jifty::Request> object to save away.  Defaults to an empty
+L<Jifty::Request> object.
+
+=item response
+
+The L<Jifty::Response> object that will be loaded up when the
+continuation is run.  Most of the time, the response isn't stored in
+the continuation, since the continuation was saved away B<before> the
+actions got run.  In the case when continuations are used to preserve
+state across a redirect, however, we tuck the L<Jifty::Response> value
+of the previous request into the continuation as well.  Defaults to an
+empty L<Jifty::Response> object.
+
+=item code
+
+An optional subroutine reference to evaluate when the continuation is
+called.
+
+=back
+
+=cut
+
+sub new {
+    my $class = shift;
+    my $self = bless { }, $class;
+
+    my %args = (
+                parent   => Jifty->web->request->continuation,
+                request  => Jifty::Request->new(),
+                response => Jifty::Response->new(),
+                code     => undef,
+                @_
+               );
+
+    # We don't want refs
+    $args{parent} = $args{parent}->id
+      if $args{parent} and ref $args{parent};
+
+    # We're getting most of our properties from the arguments
+    for (keys %args) {
+        $self->$_($args{$_}) if $self->can($_);
+    }
+
+    # Generate a hopefully unique ID
+    # FIXME: use a real ID
+    my $key = Jifty->web->serial . "_" . int(rand(10)) . int(rand(10)) . int(rand(10)) . int(rand(10)) . int(rand(10)) . int(rand(10));
+    $self->id($key);
+
+    # Save it into the session
+    Jifty->web->session->set_continuation($key => $self);
+
+    return $self;
+}
+
+=head2 return_path_matches
+
+Returns true if the continuation matches the current request's path,
+and it would return to its caller in this context.  This can be used
+to ask "are we about to call a continuation?"
+
+=cut
+
+sub return_path_matches {
+    my $self = shift;
+    my $called_uri = $ENV{'REQUEST_URI'};
+    my $request_path = $self->request->path;
+
+    # XXX TODO: WE should be using URI canonicalization
+
+    my $escape;
+    $called_uri =~ s{/+}{/}g;
+    $called_uri = Encode::encode_utf8($called_uri);
+    $called_uri = $escape while $called_uri ne ($escape = URI::Escape::uri_unescape($called_uri));
+    $request_path =~ s{/+}{/}g; 
+    $request_path = Encode::encode_utf8($request_path);
+    $request_path = $escape while $request_path ne ($escape = URI::Escape::uri_unescape($request_path));
+
+    return $called_uri =~ /^\Q$request_path\E[?&;]J:RETURN=@{[$self->id]}$/;
+}
+
+=head2 call
+
+Call the continuation; this is generally done during request
+processing, after an actions have been run.
+L<Jifty::Request::Mapper>-controlled values are filled into the stored
+request based on the current request and response.  During the
+process, another continuation is created, with the filled-in results
+of the current actions included, and the browser is redirected to the
+proper path, with that continuation.
+
+=cut
+
+sub call {
+    my $self = shift;
+
+    # If we needed to fix up the path (it contains invalid
+    # characters) then warn, because this may cause infinite
+    # redirects
+    Jifty->log->warn("Redirect to '@{[$self->request->path]}' contains unsafe characters")
+      if $self->request->path =~ m{[^A-Za-z0-9\-_.!~*'()/?&;+]};
+
+    # Clone our request
+    my $request = $self->request->clone;
+
+    # Fill in return value(s) into correct part of $request
+    $request->do_mapping;
+
+    my $response = $self->response;
+    # If the current response has results, we need to pull them
+    # in.  For safety, monikers from the saved continuation
+    # override those from the request prior to the call
+    if (Jifty->web->response->results) {
+        $response = dclone(Jifty->web->response);
+        my %results = $self->response->results;
+        $response->result($_ => $results{$_}) for keys %results;
+    }
+
+    # Make a new continuation with that request
+    my $next = Jifty::Continuation->new(parent => $self->parent, 
+                                        request => $request,
+                                        response => $response,
+                                        code => $self->code,
+                                       );
+    $next->request->continuation(Jifty->web->session->get_continuation($next->parent))
+      if defined $next->parent;
+
+    # Redirect to right page if we're not there already
+    Jifty->web->_redirect($next->request->path . "?J:RETURN=" . $next->id);
+}
+
+=head2 return
+
+Returns from the continuation by pulling out the stored request, and
+setting that to be the active request.  This shouldn't need to be
+called by hand -- use L<Jifty::Request/return_from_continuation>,
+which ensures that all requirements are ment before it calls this.
+
+=cut
+
+sub return {
+    my $self = shift;
+
+    # Pull state information out of the continuation and set it
+    # up; we use clone so that the continuation itself is
+    # immutable.
+    Jifty->web->response(dclone($self->response));
+
+    # Run any code in the continuation
+    $self->code->(Jifty->web->request)
+      if $self->code;
+
+    # Set the current request to the one in the continuation
+    return Jifty->web->request($self->request->clone);
+}
+
+=head2 delete
+
+Remove the continuation, and any continuations that would return to
+its scope, from the session.
+
+=cut
+
+sub delete {
+    my $self = shift;
+
+    # Remove all continuations that point to me
+    $_->delete for grep {$_->parent eq $self->id} values %{Jifty->web->session->continuations};
+
+    # Finally, remove me from the list of continuations
+    Jifty->web->session->remove_continuation($self->id);
+
+}
+
+1;

Added: jifty/branches/schema-plugins/lib/Jifty/CurrentUser.pm
==============================================================================
--- (empty file)
+++ jifty/branches/schema-plugins/lib/Jifty/CurrentUser.pm	Mon Jan 29 21:05:02 2007
@@ -0,0 +1,215 @@
+use warnings;
+use strict;
+
+package Jifty::CurrentUser;
+
+use base qw/Jifty::Object Class::Accessor::Fast/;
+
+__PACKAGE__->mk_accessors(qw(is_superuser is_bootstrap_user user_object));
+
+
+=head1 NAME
+
+Jifty::CurrentUser
+
+=head1 DESCRIPTION
+
+Most applications need to have a concept of who the current user
+is. So Jifty supports this concept internally. Every L<Jifty::Object>
+(which most things in Jifty are descended from) except the CurrentUser
+itself is instantiated with a L<Jifty::CurrentUser> subclass as a
+parameter to the creator.
+
+This class describes (and implements a trivial version) of the access
+control API that a Jifty application needs to implement to provide
+user-based access control
+
+It's generally expected that your application will override this class
+if you want any sort of access control.
+
+=cut
+
+=head2 new
+
+Creates a new L<Jifty::CurrentUser> object.  Calls L<_init>, an
+app-specific initialization routine.
+
+=cut
+
+sub new {
+    my $class = shift;
+    my $self  = {};
+    bless $self, $class;
+    my %args = (@_);
+    if ( delete $args{'_bootstrap'} ) { $self->is_bootstrap_user(1); }
+    $self->_init(%args);
+    return $self;
+}
+
+sub _init { 1}
+
+=head2 superuser
+
+A convenience constructor that returns a new CurrentUser object that's
+marked as a superuser.
+
+=cut
+
+sub superuser {
+    my $class = shift;
+    my $self = $class->new();
+    $self->is_superuser(1);
+    return $self;
+}
+
+=head2 user_object 
+
+This gets or sets your application's user object for the current
+user. Generally, you're expected to set and load it in the _init method
+in your L<Jifty::CurrentUser> subclass.
+
+Example:  
+
+	sub _init {
+	    my $self = shift;
+	    my %args = (@_);
+	
+            if (keys %args) {
+	        $self->user_object(Wifty::Model::User->new(current_user => $self));
+	        $self->user_object->load_by_cols(%args);
+	    }
+	    $self->SUPER::_init(%args);
+	}
+	
+
+=cut
+
+=head2 id
+
+Returns C<0> if we don't have a L<user_object>.  When we I<do> have a
+user_object, return that user's id.
+
+=cut
+
+sub id {
+    my $self = shift;
+    if ($self->user_object) {
+        return ($self->user_object->id());
+    } else {
+        return '0';
+    }
+
+}
+
+=head2 current_user
+
+Every class in a Jifty application has a L</current_user> method that
+returns the user who's doing things, in the form of a
+L<Jifty::CurrentUser> object a subclass thereof.  For the somewhat
+obvious reason that you can't actually lift yourself up by tugging on
+your own bootstraps, a L<Jifty::CurrentUser> object return I<itself>
+rather than another C<Jifty::CurrentUser object>
+
+=cut
+
+sub current_user {
+    my $self = shift;
+    return $self;
+}
+
+=head1 AUTHENTICATION AND AUTHORIZATION
+
+To use Jifty's built-in authentication and authorization system, your
+user objects need to implement the following API methods:
+
+=head2 password_is STRING
+
+Your L<user_object> should have a method called C<password_is> which
+returns true if passed a string that matches the user's current
+password.
+
+=cut
+
+sub password_is {
+    my $self = shift;
+    return undef unless ($self->user_object);
+    return($self->user_object->password_is(@_));
+
+}
+
+=head2 username
+
+Return a string which identifies the user in some way.
+
+=cut
+
+sub username {
+    my $self = shift;
+    return undef unless ($self->user_object);
+    return($self->user_object->username(@_));
+}
+
+=head2 auth_token
+
+Return a string which proves that the user is who they claim to be.  A
+simple way to do this, for example, would be to hash the username and
+some server-side secret.
+
+=cut
+
+sub auth_token {
+    my $self = shift;
+    return undef unless ($self->user_object);
+    return ($self->user_object->auth_token);
+
+}
+
+=head1 RIGHTS AND ACCESS CONTROL
+
+In any system that relies on users' rights to perform actions, it's
+sometimes necessary to walk around the access control system. There
+are two primary cases for this:
+
+=cut
+
+=head2 is_superuser 
+
+Sometimes, while the system is running, you need to do something on
+behalf of a user that they shouldn't be able to do themselves. Maybe
+you need to let a new user sign up for your service (You don't want to
+let any user create more users, right?) or to write an entry to a
+changelog. If the user has the C<is_superuser> flag set, things still
+get read from the database, but the user can walk around any and all
+ACL checks. Think "Neo" from the Matrix. The superuser can walk
+through walls, stop bullets and so on.
+
+
+=cut
+
+=head2 is_bootstrap_user
+
+When your system is first getting going, you can't assume
+B<anything>. There probably aren't any rights in the system to
+check. A user with the L</is_bootstrap_user> flag set is a
+self-reliant superuser. Nothing is read from the database, no ACLs are
+checked.  You probably never need to do anything with bootstrap users.
+
+=cut
+
+
+=head2 current_user_can ACTION
+
+For a current user object, the current user can always C<read>, but
+never write or do anything else.
+
+=cut
+
+
+sub current_user_can {
+    my $self = shift;
+    my $action = shift;
+    return (1) if $action eq 'read';
+    return (0);
+}
+
+1;

Added: jifty/branches/schema-plugins/lib/Jifty/DateTime.pm
==============================================================================
--- (empty file)
+++ jifty/branches/schema-plugins/lib/Jifty/DateTime.pm	Mon Jan 29 21:05:02 2007
@@ -0,0 +1,98 @@
+use warnings;
+use strict;
+
+package Jifty::DateTime;
+
+=head1 NAME
+
+Jifty::DateTime - a DateTime subclass that knows about Jifty users
+
+
+=head1 DESCRIPTION
+
+Jifty natively stores timestamps in the database in GMT.  Dates are stored
+without timezone. This class loads and parses dates and sets them
+into the proper timezone.
+
+=cut
+
+use base qw(Jifty::Object DateTime);
+
+
+=head2 new ARGS
+
+See L<DateTime/new>.  After calling that method, set this object's
+timezone to the current user's time zone, if the current user has a
+method called C<time_zone>.
+
+=cut
+
+sub new {
+    my $class = shift;
+    my %args  = (@_);
+    my $self  = $class->SUPER::new(%args);
+
+    # Unless the user has explicitly said they want a floating time,
+    # we want to convert to the end-user's timezone.  This is
+    # complicated by the fact that DateTime auto-appends
+    if (!$args{time_zone} and my $tz = $self->current_user_has_timezone) {
+        $self->set_time_zone("UTC");
+        $self->set_time_zone( $tz );
+    }
+    return $self;
+}
+
+=head2 current_user_has_timezone
+
+Return timezone if the current user has it
+
+=cut
+
+sub current_user_has_timezone {
+    my $self = shift;
+    $self->_get_current_user();
+    my $user_obj = $self->current_user->user_object or return;
+    my $f = $user_obj->can('time_zone') or return;
+    return $f->($user_obj);
+}
+
+=head2 new_from_string STRING
+
+Take some user defined string like "tomorrow" and turn it into a
+C<Jifty::Datetime> object.  If the string appears to be a _date_, keep
+it in the floating timezone, otherwise, set it to the current user's
+timezone.
+
+=cut
+
+sub new_from_string {
+    my $class  = shift;
+    my $string = shift;
+    my $now;
+
+    {
+        # Date::Manip interprets days of the week (eg, ''monday'') as
+        # days within the *current* week. Detect these and prepend
+        # ``next''
+        # XXX TODO: Find a real solution (better date-parsing library?)
+        if($string =~ /^\s* (?:monday|tuesday|wednesday|thursday|friday|saturday|sunday)$/xi) {
+            $string = "next $string";
+        }
+        
+        # Why are we parsing this as GMT? This feels really wrong.  It will get the wrong answer
+        # if the current user is in another tz.
+        require Date::Manip;
+        Date::Manip::Date_Init("TZ=GMT");
+        $now = Date::Manip::UnixDate( $string, "%o" );
+    }
+    return undef unless $now;
+    my $self = $class->from_epoch( epoch => $now, time_zone => 'gmt' );
+    if (my $tz = $self->current_user_has_timezone) {
+        $self->set_time_zone("floating")
+            unless ( $self->hour or $self->minute or $self->second );
+        $self->set_time_zone( $tz );
+    }
+    return $self;
+}
+
+1;

Added: jifty/branches/schema-plugins/lib/Jifty/Dispatcher.pm
==============================================================================
--- (empty file)
+++ jifty/branches/schema-plugins/lib/Jifty/Dispatcher.pm	Mon Jan 29 21:05:02 2007
@@ -0,0 +1,1309 @@
+package Jifty::Dispatcher;
+use strict;
+use warnings;
+use Exporter;
+use Jifty::YAML;
+use base qw/Exporter Jifty::Object/;
+           
+
+=head1 NAME
+
+Jifty::Dispatcher - The Jifty Dispatcher
+
+=head1 SYNOPSIS
+
+In B<MyApp::Dispatcher>:
+
+    package MyApp::Dispatcher;
+    use Jifty::Dispatcher -base;
+
+    under ['blog', 'wiki'] => [
+        run {
+            default model => "MyApp::Model::\u$1"
+        },
+        on PUT 'entries/*' => run {
+            set entry_id => $1;
+            show '/display/entry';
+        },
+        on '*/*' => run {
+            my ($page, $op) = ($1, $2);
+            my $item = get('model')->load($page) or next_rule;
+
+            set item => $item;
+            set page => $page;
+            set op   => $op;
+
+            show "/display/$op";
+        },
+        on '*' => run { dispatch "$1/view" },
+        on ''  => show '/display/list',
+    ];
+    under qr{logs/(\d+)} => [
+        when { $1 > 100 } => show '/error',
+        set model => 'MyApp::Model::Log',
+        run { dispatch "/wiki/LogPage-$1" },
+    ];
+    # ... more rules ...
+
+=head1 DESCRIPTION
+
+C<Jifty::Dispatcher> takes requests for pages, walks through a
+dispatch table, possibly running code or transforming the request
+before finally handing off control to the templating system to display
+the page the user requested or whatever else the system has decided to
+display instead.
+
+Generally, this is B<not> the place to be performing model and user
+specific access control checks or updating your database based on what
+the user has sent in. You want to do that in your model
+classes. (Well, I<we> want you to do that, but you're free to ignore
+our advice).
+
+The Dispatcher runs rules in several stages:
+
+=over
+
+=item before
+
+B<before> rules are run before Jifty evaluates actions. They're the
+perfect place to enable or disable L<Jifty::Action>s using
+L<Jifty::API/allow> and L<Jifty::API/deny> or to completely disallow
+user access to private I<component> templates such as the F<_elements>
+directory in a default Jifty application.  They're also the right way
+to enable L<Jifty::LetMe> actions.
+
+You can entirely stop processing with the C<redirect>, C<tangent> and
+C<abort> directives, though L</after> rules will still run.
+
+=item on
+
+L<on> rules are run after Jifty evaluates actions, so they have full
+access to the results actions users have performed. They're the right
+place to set up view-specific objects or load up values for your
+templates.
+
+Dispatcher directives are evaluated in order until we get to either a
+C<show>, C<redirect>, C<tangent> or C<abort>.
+
+=item after
+
+L<after> rules let you clean up after rendering your page. Delete your
+cache files, write your transaction logs, whatever.
+
+At this point, it's too late to C<show>, C<redirect>, C<tangent> or C<abort>
+page display.
+
+=back
+
+C<Jifty::Dispatcher> is intended to replace all the F<autohandler>,
+F<dhandler> and C<index.html> boilerplate code commonly found in Mason
+applications, but there's nothing stopping you from using those
+features in your application when they're more convenient.
+
+Each directive's code block runs in its own scope, but all share a
+common C<$Dispatcher> object.
+
+=cut
+
+=head1 Plugins and rule ordering
+
+By default, L<Jifty::Plugin> dispatcher rules are added in the order
+they are specified in the application's configuration file; that is,
+after all the plugin dispatchers have run in order, then the
+application's dispatcher runs.  It is possible to specify rules which
+should be reordered with respect to this rule, however.  This is done
+by using a variant on the C<before> and C<after> syntax:
+
+    before plugin NAME =>
+        RULE(S);
+    
+    after plugin NAME =>
+        RULE(S);
+
+C<NAME> may either be a string, which must match the plugin name
+exactly, or a regular expression, which is matched against the plugin
+name.  The rule will be placed at the first boundary that it matches --
+that is, given a C<before plugin qr/^Jifty::Plugin::Auth::/> and both
+a C<Jifty::Plugin::Auth::Basic> and a C<Jifty::Plugin::Auth::Complex>,
+the rules will be placed before the first.
+
+C<RULES> may either be a single C<before>, C<on>, C<under>, or
+C<after> rule to change the ordering of, or an array reference of
+rules to reorder.
+
+=cut
+
+=head1 Data your dispatch routines has access to
+
+=head2 request
+
+The current L<Jifty::Request> object.
+
+=head2 $Dispatcher
+
+The current dispatcher object.
+
+=head2 get $arg
+
+Return the argument value. 
+
+=head1 Things your dispatch routine might do
+
+=head2 under $match => $rule
+
+Match against the current requested path.  If matched, set the current
+context to the directory and process the rule.
+
+The C<$rule> may be an array reference of more rules, a code reference, a
+method name of your dispatcher class, or a fully qualified subroutine name.
+
+All wildcards in the C<$match> string becomes capturing regex patterns.  You
+can also pass in an array reference of matches, or a regex pattern.
+
+The C<$match> string may be qualified with a HTTP method name, such as
+
+=over
+
+=item GET
+
+=item POST
+
+=item PUT
+
+=item OPTIONS
+
+=item DELETE
+
+=item HEAD
+
+=back
+
+=head2 on $match => $rule
+
+Like C<under>, except it has to match the whole path instead of just the prefix.
+Does not set current directory context for its rules.
+
+=head2 before $match => $rule
+
+Just like C<on>, except it runs I<before> actions are evaluated.
+
+=head2 after $match => $rule
+
+Just like C<on>, except it runs I<after> the page is rendered.
+
+
+=head2 when {...} => $rule
+
+Like C<under>, except using an user-supplied test condition.  You can stick 
+any Perl you want inside the {...}; it's just an anonymous subroutine.
+
+=head2 run {...}
+
+Run a block of code unconditionally; all rules are allowed inside a C<run>
+block, as well as user code.  You can think of the {...} as an anonymous 
+subroutine.
+
+=head2 set $arg => $val
+
+Adds an argument to what we're passing to our template, overriding 
+any value the user sent or we've already set.
+
+=head2 default $arg => $val
+
+Adds an argument to what we're passing to our template,
+but only if it is not defined currently.
+
+=head2 del $arg
+
+Deletes an argument we were passing to our template.
+
+=head2 show $component
+
+Display the presentation component.  If not specified, use the
+request path as the default page.
+
+=head2 dispatch $path
+
+Dispatch again using $path as the request path, preserving args.
+
+=head2 next_rule
+
+Break out from the current C<run> block and go on the next rule.
+
+=head2 last_rule
+
+Break out from the current C<run> block and stop running rules in this stage.
+
+=head2 abort $code
+
+Abort the request; this skips straight to the cleanup stage.
+
+If C<$code> is specified, it's used as the HTTP status code.
+
+=head2 redirect $uri
+
+Redirect to another URI.
+
+=head2 tangent $uri
+
+Take a continuation here, and tangent to another URI.
+
+=head2 plugin
+
+See L</Plugins and rule ordering>, above.
+
+=cut
+
+our @EXPORT = qw<
+    under run when set del default
+
+    before on after
+
+    show dispatch abort redirect tangent
+
+    GET POST PUT HEAD DELETE OPTIONS
+
+    plugin
+
+    get next_rule last_rule
+
+    already_run
+
+    $Dispatcher
+>;
+
+our $Dispatcher;
+
+sub request       { Jifty->web->request }
+sub _ret (@);
+sub under ($$@)   { _ret @_ }    # partial match at beginning of path component
+sub before ($$@)  { _ret @_ }    # exact match on the path component
+sub on ($$@)      { _ret @_ }    # exact match on the path component
+sub after ($$@)   { _ret @_ }    # exact match on the path component
+sub when (&@)     { _ret @_ }    # exact match on the path component
+sub run (&@)      { _ret @_ }    # execute a block of code
+sub show (;$@)    { _ret @_ }    # render a page
+sub dispatch ($@) { _ret @_ }    # run dispatch again with another URI
+sub redirect ($@) { _ret @_ }    # web redirect
+sub tangent ($@)  { _ret @_ }    # web tangent
+sub abort (;$@)   { _ret @_ }    # abort request
+sub default ($$@) { _ret @_ }    # set parameter if it's not yet set
+sub set ($$@)     { _ret @_ }    # set parameter
+sub del ($@)      { _ret @_ }    # remove parameter
+sub get ($) { request->argument( $_[0] ) }
+
+sub _qualify ($@);
+sub GET ($)     { _qualify method => @_ }
+sub POST ($)    { _qualify method => @_ }
+sub PUT ($)     { _qualify method => @_ }
+sub HEAD ($)    { _qualify method => @_ }
+sub DELETE ($)  { _qualify method => @_ }
+sub OPTIONS ($) { _qualify method => @_ }
+
+sub plugin ($) { return { plugin => @_ } }
+
+our $CURRENT_STAGE;
+
+=head2 import
+
+Jifty::Dispatcher is an L<Exporter>, that is, part of its role is to
+blast a bunch of symbols into another package. In this case, that other
+package is the dispatcher for your application.
+
+You never call import directly. Just:
+
+    use Jifty::Dispatcher -base;
+
+in C<MyApp::Dispatcher>
+
+=cut
+
+sub import {
+    my $class = shift;
+    my $pkg   = caller;
+    my @args  = grep { !/^-[Bb]ase/ } @_;
+
+    no strict 'refs';
+    no warnings 'once';
+    for (qw(RULES_RUN RULES_SETUP RULES_CLEANUP RULES_DEFERRED)) {
+        @{ $pkg . '::' . $_ } = ();
+    }
+    if ( @args != @_ ) {
+
+        # User said "-base", let's push ourselves into their @ISA.
+        push @{ $pkg . '::ISA' }, $class;
+    }
+
+    $class->export_to_level( 1, @args );
+}
+
+###################################################
+# Magically figure out the arity based on caller info.
+sub _ret (@) {
+    my $pkg   = caller(1);
+    my $sub   = ( caller(1) )[3];
+    my $proto = prototype($sub);
+    my $op    = $sub;
+
+    $proto =~ tr/@;//d;
+    if ( my $idx = rindex( $op, '::' ) ) {
+        $op = substr( $op, $idx + 2 );
+    }
+
+    if ($Dispatcher) {
+
+        # We are under an operation -- carry the rule forward
+        foreach my $rule ( [ $op => splice( @_, 0, length($proto) ) ], @_ ) {
+            $Dispatcher->_handle_rule($rule);
+        }
+    } elsif (wantarray) {
+        ( [ $op => splice( @_, 0, length($proto) ) ], @_ );
+    } elsif ( defined wantarray ) {
+        [ [ $op => splice( @_, 0, length($proto) ) ], @_ ];
+    } else {
+        _push_rule($pkg, [ $op => splice( @_, 0, length($proto) ) ] );
+    }
+}
+
+sub _push_rule($$) {
+    my($pkg, $rule) = @_;
+    my $op = $rule->[0];
+    my $ruleset;
+    if ( ($op eq "before" or $op eq "after") and ref $rule->[1] and ref $rule->[1] eq 'HASH' and $rule->[1]{plugin} ) {
+        $ruleset = 'RULES_DEFERRED';
+    } elsif ( $op eq 'before' ) {
+        $ruleset = 'RULES_SETUP';
+    } elsif ( $op eq 'after' ) {
+        $ruleset = 'RULES_CLEANUP';
+    } else {
+        $ruleset = 'RULES_RUN';
+    }
+    no strict 'refs';
+    # XXX TODO, need to spec stage here.
+    push @{ $pkg . '::' . $ruleset }, $rule;
+}
+
+sub _qualify ($@) {
+    my $key = shift;
+    my $op  = ( caller(1) )[3];
+    $op =~ s/.*:://;
+    return { $key => $op, '' => $_[0] };
+}
+
+=head2 rules STAGE
+
+Returns an array of all the rules for the stage STAGE.
+
+Valid values for STAGE are
+
+=over
+
+=item SETUP
+
+=item RUN
+
+=item CLEANUP
+
+=back
+
+=cut
+
+sub rules {
+    my $self  = shift;
+    my $stage = shift;
+    my $pkg   = ref($self) || $self;
+    no strict 'refs';
+    @{ $pkg . '::RULES_' . $stage };
+}
+
+=head2 new
+
+Creates a new Jifty::Dispatcher object. You probably don't ever want
+to do this. (Jifty.pm does it for you)
+
+=cut
+
+sub new {
+    my $self = shift;
+    return $self if ref($self);
+
+    bless(
+        {   cwd  => '',
+            path => '',
+            rule => undef,
+            @_,
+        } => $self
+    );
+}
+
+=head2 handle_request
+
+Actually do what your dispatcher does. For now, the right thing
+to do is to put the following two lines first:
+
+    require MyApp::Dispatcher;
+    MyApp::Dispatcher->handle_request;
+
+
+=cut
+
+sub handle_request {
+    my $self = shift;
+
+    local $Dispatcher = $self->new();
+
+    # XXX TODO: refactor this out somehow?
+    # We don't want the previous mason request hanging aroudn once we start dispatching
+    no warnings 'once';
+    local $HTML::Mason::Commands::m = undef;
+    # Mason introduces a DIE handler that generates a mason exception
+    # which in turn generates a backtrace. That's fine when you only
+    # do it once per request. But it's really, really painful when you
+    # do it often, as is the case with fragments
+    local $SIG{__DIE__} = 'DEFAULT';
+
+    eval {
+        $Dispatcher->_do_dispatch( Jifty->web->request->path);
+    };
+    if ( my $err = $@ ) {
+        $self->log->warn(ref($err) . " " ."'$err'") if ( $err !~ /^ABORT/ );
+    }
+}
+
+=head2 _handle_stage NAME, EXTRA_RULES
+
+Handles the all rules in the stage named C<NAME>.  Additionally, any
+other arguments passed after the stage C<NAME> are added to the end of
+the rules for that stage.
+
+This is the unit which calling L</last_rule> skips to the end of.
+
+=cut
+
+sub _handle_stage {
+    my ($self, $stage, @rules) = @_;
+
+    # Set the current stage so that rules can make smarter choices;
+    local $CURRENT_STAGE = $stage;
+
+    eval { $self->_handle_rules( [ $self->rules($stage), @rules ] ); };
+    if ( my $err = $@ ) {
+        $self->log->warn( ref($err) . " " . "'$err'" )
+            if ( $err !~ /^(LAST RULE|ABORT)/ );
+        return $err =~ /^ABORT/ ? 0 : 1;
+    }
+    return 1;
+}
+
+=head2 _handle_rules RULESET
+
+When handed an arrayref or array of rules (RULESET), walks through the 
+rules in order, executing as it goes.
+
+
+=cut
+
+sub _handle_rules ($) {
+    my ( $self, $rules ) = @_;
+
+    my @rules;
+    {
+        local $@;
+        eval { @rules = @$rules };
+        @rules = $rules if $@;
+    }
+RULE: foreach my $rule (@rules) {
+        $self->_handle_rule($rule);
+    }
+}
+
+=head2 _handle_rule RULE
+
+When handed a single rule in the form of a coderef, C<_handle_rule>, 
+calls C<_do_run> on that rule and returns the result. When handed a 
+rule that turns out to be an array of subrules, recursively calls
+itself and evaluates the subrules in order.
+
+=cut
+
+sub _handle_rule {
+    my ( $self, $rule ) = @_;
+    my ( $op,   @args );
+
+    # Handle the case where $rule is an array reference.
+    if (ref($rule) eq 'ARRAY') {
+        ( $op, @args ) = @$rule;
+    } else {
+        ( $op, @args ) = ( run => $rule );
+    }
+
+    # Handle the case where $op is an array.
+    my $sub_rules;
+    if (ref($op) eq 'ARRAY' ) {
+         $sub_rules = [ @$op, @args ];
+    }
+
+    if ($sub_rules) {
+        for my $sub_rule (@$sub_rules) {
+            $self->_handle_rule($sub_rule);
+        }
+    }
+
+    # Now we know op is a scalar.
+    local $self->{rule} = $op;
+    my $meth = "_do_$op";
+    $self->$meth(@args);
+
+}
+
+no warnings 'exiting';
+
+sub next_rule { next RULE }
+sub last_rule { die "LAST RULE" }
+
+=head2 _do_under
+
+This method is called by the dispatcher internally. You shouldn't need to.
+
+=cut
+
+sub _do_under {
+    my ( $self, $cond, $rules ) = @_;
+    if ( my $regex = $self->_match($cond) ) {
+
+        # match again to establish $1 $2 etc in the dynamic scope
+        $self->{path} =~ $regex;
+
+        # enter the matched directory
+        local $self->{cwd} = substr( $self->{path}, 0, $+[0] );
+        chop $self->{cwd} if substr( $self->{cwd}, -1 ) eq '/';
+
+        $self->_handle_rules($rules);
+    }
+}
+
+=head2 _do_when
+
+This method is called by the dispatcher internally. You shouldn't need to.
+
+=cut
+
+sub _do_when {
+    my ( $self, $code, $rules ) = @_;
+    if ( $code->() ) {
+        $self->_handle_rules($rules);
+    }
+}
+
+=head2 _do_before
+
+This method is called by the dispatcher internally. You shouldn't need to.
+
+=cut
+
+sub _do_before {
+    my ( $self, $cond, $rules ) = @_;
+    if ( my $regex = $self->_match($cond) ) {
+
+        $self->log->debug("Matched 'before' rule $regex for ".$self->{'path'});
+        # match again to establish $1 $2 etc in the dynamic scope
+        $self->{path} =~ $regex;
+        $self->_handle_rules($rules);
+    }
+
+}
+
+=head2 _do_on
+
+This method is called by the dispatcher internally. You shouldn't need to.
+
+=cut
+
+sub _do_on {
+    my ( $self, $cond, $rules ) = @_;
+    if ( my $regex = $self->_match($cond) ) {
+
+        $self->log->debug("Matched 'on' rule $regex for ".$self->{'path'});
+        # match again to establish $1 $2 etc in the dynamic scope
+        $self->{path} =~ $regex;
+        $self->_handle_rules($rules);
+    }
+}
+
+=head2 _do_after
+
+This method is called by the dispatcher internally. You shouldn't need to.
+
+=cut
+
+sub _do_after {
+    my ( $self, $cond, $rules ) = @_;
+    if ( my $regex = $self->_match($cond) ) {
+        $self->log->debug("Matched 'after' rule $regex for ".$self->{'path'});
+        # match again to establish $1 $2 etc in the dynamic scope
+        $self->{path} =~ $regex;
+        $self->_handle_rules($rules);
+    }
+}
+
+=head2 already_run
+
+Returns true if the code block has run once already in this request.
+This can be useful for 'after' rules to ensure that they only run
+once, even if there is a sub-dispatch which would cause it to run more
+than once.  The idiom is:
+
+    after '/some/path/*' => run {
+        return if already_run;
+        # ...
+    };
+
+=cut
+
+sub already_run {
+    my $id = $Dispatcher->{call_rule};
+    return 1 if get "__seen_$id";
+    set "__seen_$id" => 1;
+    return 0;
+}
+
+sub _do_run {
+    my ( $self, $code ) = @_;
+
+    # Keep track of the coderef being run, so we can know about
+    # already_run
+    local $self->{call_rule} = $code;
+
+    # establish void context and make a call
+    ( $self->can($code) || $code )->();
+
+    # XXX maybe call with all the $1..$x as @_ too? or is it too gonzo?
+    # $code->(map { substr($PATH, $-[$_], ($+[$_]-$-[$_])) } 1..$#-));
+
+    return;
+}
+
+=head2 _do_redirect PATH
+
+This method is called by the dispatcher internally. You shouldn't need to.
+
+Redirect the user to the URL provided in the mandatory PATH argument.
+
+=cut
+
+sub _do_redirect {
+    my ( $self, $path ) = @_;
+    $self->log->debug("Redirecting to $path");
+    Jifty->web->redirect($path);
+}
+
+=head2 _do_tangent PATH
+
+This method is called by the dispatcher internally. You shouldn't need to.
+
+Take a tangent to the URL provided in the mandatory PATH argument.
+(See L<Jifty::Manual::Continuation> for more about tangents.)
+
+=cut
+
+sub _do_tangent {
+    my ( $self, $path ) = @_;
+    $self->log->debug("Taking a tangent to $path");
+    Jifty->web->tangent(url => $path);
+}
+
+=head2 _do_abort 
+
+This method is called by the dispatcher internally. You shouldn't need to.
+
+Don't display any page. just stop.
+
+=cut
+
+sub _do_abort {
+    my $self = shift;
+    $self->log->debug("Aborting processing");
+    if (@_) {
+        # This is the status code
+        my $status = shift;
+        my $apache = Jifty->handler->apache;
+        $apache->header_out(Status => $status);
+        $apache->send_http_header;
+
+        require HTTP::Status;
+        print STDOUT $status, ' ' , HTTP::Status::status_message($status);
+    }
+    $self->_abort;
+}
+
+sub _abort { die "ABORT" }
+
+=head2 _do_show [PATH]
+
+This method is called by the dispatcher internally. You shouldn't need to.
+
+Render a template. If the scalar argument "PATH" is given, render that component.
+Otherwise, just render whatever we were going to anyway.
+
+=cut
+
+sub _do_show {
+    my $self = shift;
+    my $path;
+
+    # Fix up the path
+    $path = shift if (@_);
+    $path ||= $self->{path};
+
+    unless ($CURRENT_STAGE eq 'RUN') {
+        die "You can't call a 'show' rule in a 'before' or 'after' block in the dispatcher.  Not showing path $path";
+    }
+
+    $self->log->debug("Showing path $path");
+
+    # If we've got a working directory (from an "under" rule) and we have
+    # a relative path, prepend the working directory
+    $path = "$self->{cwd}/$path" unless $path =~ m{^/};
+
+    # When we're requesting a directory, go looking for the index.html
+    if ( $self->template_exists( $path . "/index.html" ) ) {
+        $path .= "/index.html";
+    }
+
+    my $abs_template_path = Jifty::Util->absolute_path(
+        Jifty->config->framework('Web')->{'TemplateRoot'} . $path );
+    my $abs_root_path = Jifty::Util->absolute_path(
+        Jifty->config->framework('Web')->{'TemplateRoot'} );
+
+    if ( $abs_template_path !~ /^\Q$abs_root_path\E/ ) {
+        request->path('/__jifty/errors/500');
+    } else {
+        # Set the request path
+        request->path($path);
+    }
+    $self->render_template( request->path );
+
+    last_rule;
+}
+
+sub _do_set {
+    my ( $self, $key, $value ) = @_;
+    $self->log->debug("Setting argument $key to ".($value||''));
+    request->argument($key, $value);
+}
+
+sub _do_del {
+    my ( $self, $key ) = @_;
+    $self->log->debug("Deleting argument $key");
+    request->delete($key);
+}
+
+sub _do_default {
+    my ( $self, $key, $value ) = @_;
+    $self->log->debug("Setting argument default $key to ".($value||''));
+    request->argument($key, $value)
+        unless defined request->argument($key);
+}
+
+=head2 _do_dispatch [PATH]
+
+First, this routine runs all the C<before> dispatcher rules, then it runs
+Jifty->web->handle_request(), then it runs all the main C<on> rules,
+evaluating each one in turn.  If it gets through all the rules without
+running an C<abort>, C<redirect> or C<show> directive, it C<shows>
+the template originally requested.
+
+Once it's done with that, it runs all the cleanup rules defined with C<after>.
+
+=cut
+
+sub _do_dispatch {
+    my $self = shift;
+
+    # Requests should always start with a leading /
+    $self->{path} = "/".shift;
+    $self->{cwd}  = '';
+
+    # Normalize the path.
+    $self->{path} =~ s{/+}{/}g;
+
+    $self->log->debug("Dispatching request to ".$self->{path});
+
+    # Setup -- we we don't abort out of setup, then run the
+    # actions and then the RUN stage.
+    if ($self->_handle_stage('SETUP')) {
+        # Run actions
+        Jifty->web->handle_request();
+
+        # Run, and show the page
+        $self->_handle_stage('RUN' => 'show');
+    }
+
+    # Cleanup
+    $self->_handle_stage('CLEANUP');
+
+    # Out to the next dispatcher's cleanup
+    $self->_abort;
+}
+
+=head2 _match CONDITION
+
+Returns the regular expression matched if the current request fits
+the condition defined by CONDITION. 
+
+C<CONDITION> can be a regular expression, a "simple string" with shell
+wildcard characters (C<*>, C<?>, C<#>, C<[]>, C<{}>) to match against,
+or an arrayref or hashref of those. It should even be nestable.
+
+Arrayref conditions represents alternatives: the match succeeds as soon
+as the first match is found.
+
+Hashref conditions are conjunctions: each non-empty hash key triggers a
+separate C<_match_$keyname> call on the dispatcher object. For example, a
+C<method> key would call C<_match_method> with its value to be matched against.
+After each subcondition is tried (in lexographical order) and succeeded,
+the value associated with the C<''> key is matched again as the condition.
+
+=cut
+
+sub _match {
+    my ( $self, $cond ) = @_;
+
+    # Handle the case where $cond is an array.
+    if ( ref($cond) eq 'ARRAY' ) {
+        local $@;
+        my $rv = eval {
+            for my $sub_cond (@$cond)
+            {
+                return ( $self->_match($sub_cond) or next );
+            }
+        };
+        if ( my $err = $@ ) {
+            warn "$self _match failed: $err";
+        } else {
+            return $rv;
+        }
+    }
+
+    # Handle the case where $cond is a hash.
+    elsif ( ref($cond) eq 'HASH' ) {
+        local $@;
+        my $rv = eval {
+            for my $key ( sort keys %$cond )
+            {
+                next if $key eq '';
+                my $meth = "_match_$key";
+                $self->$meth( $cond->{$key} ) or return;
+            }
+
+            # All precondition passed, get original condition literal
+            return $self->_match( $cond->{''} ) if $cond->{''};
+
+            # Or, if we don't have a literal, we win.
+            return 1;
+        };
+        if ( my $err = $@ ) {
+            warn "$self _match failed: $err";
+        } else {
+            return $rv;
+        }
+    }
+
+    # Now we know $cond is a scalar, match against it.
+    else {
+        my $regex = $self->_compile_condition($cond) or return;
+        $self->{path} =~ $regex or return;
+        return $regex;
+    }
+}
+
+=head2 _match_method METHOD
+
+Takes an HTTP method. Returns true if the current request
+came in with that method.
+
+=cut
+
+sub _match_method {
+    my ( $self, $method ) = @_;
+    $self->log->debug("Matching URL $ENV{REQUEST_METHOD} against ".$method);
+    lc( $ENV{REQUEST_METHOD} ) eq lc($method);
+}
+
+sub _match_plugin {
+    my ( $self, $plugin ) = @_;
+    warn "Deferred check shouldn't happen";
+    return 0;
+}
+
+=head2 _compile_condition CONDITION
+
+Takes a condition defined as a simple string and return it as a regex
+condition.
+
+=cut
+
+sub _compile_condition {
+    my ( $self, $cond ) = @_;
+
+    # Previously compiled (eg. a qr{} -- return it verbatim)
+    return $cond if ref $cond;
+
+    # Escape and normalize
+    $cond = quotemeta($cond);
+    $cond =~ s{(?:\\\/)+}{/}g;
+    $cond =~ s{/$}{};
+
+    my $has_capture = ( $cond =~ / \\ [*?#] /x);
+    if ($has_capture or $cond =~ / \\ [[{] /x) {
+        $cond = $self->_compile_glob($cond);
+    }
+
+    if ( $cond =~ m{^/} ) {
+
+        # '/foo' => qr{^/foo}
+        $cond = "\\A$cond";
+    } elsif ( length($cond) ) {
+
+        # 'foo' => qr{^$cwd/foo}
+        $cond = "(?<=\\A$self->{cwd}/)$cond";
+    } else {
+
+        # empty path -- just match $cwd itself
+        $cond = "(?<=\\A$self->{cwd})";
+    }
+
+    if ( $Dispatcher->{rule} eq 'on' ) {
+
+        # "on" anchors on complete match only
+        $cond .= '/?\\z';
+    } else {
+
+        # "in" anchors on prefix match in directory boundary
+        $cond .= '(?=/|\\z)';
+    }
+
+    # Make all metachars into capturing submatches
+    if (!$has_capture) {
+        $cond = "($cond)";
+    }
+
+    return qr{$cond};
+}
+
+=head2 _compile_glob METAEXPRESSION
+
+Private function.
+
+Turns a metaexpression containing C<*>, C<?> and C<#> into a capturing regex pattern.
+
+Also supports the non-capturing C<[]>,and C<{}> notation.
+
+The rules are:
+
+=over 4
+
+=item *
+
+A C<*> between two C</> characters, or between a C</> and end of string,
+should match one or more non-slash characters:
+
+    /foo/*/bar
+    /foo/*/
+    /foo/*
+    /*
+
+=item *
+
+All other C<*> can match zero or more non-slash characters: 
+
+    /*bar
+    /foo*bar
+    *
+
+=item *
+
+Two stars (C<**>) can match zero or more characters, including slash:
+
+    /**/bar
+    /foo/**
+    **
+
+=item *
+
+Consecutive C<?> marks are captured together:
+
+    /foo???bar      # One capture for ???
+    /foo??*         # Two captures, one for ?? and one for *
+
+=item *
+
+The C<#> character captures one or more digit characters.
+
+=item *
+
+Brackets such as C<[a-z]> denote character classes; they are not captured.
+
+=item *
+
+Braces such as C<{xxx,yyy}]> denote alternations; they are not captured.
+
+=back
+
+=cut
+
+sub _compile_glob {
+    my ( $self, $glob ) = @_;
+    $glob =~ s{
+        # Stars between two slashes, or between a slash and end-of-string,
+        # should at match one or more non-slash characters.
+        (?<= /)      # lookbehind for slash
+        \\ \*        # star
+        (?= / | \z)  # lookahead for slash or end-of-string
+    }{([^/]+)}gx;
+    $glob =~ s{
+        # Two stars can match zero or more characters, including slash.
+        \\ \* \\ \*
+    }{(.*)}gx;
+    $glob =~ s{
+        # All other stars can match zero or more non-slash character.
+        \\ \*
+    }{([^/]*)}gx;
+    $glob =~ s{
+        # The number-sign character matches one or more digits.
+        \\ \#
+    }{(\\d+)}gx;
+    $glob =~ s{
+        # Consecutive question marks are captured as one unit;
+        # we do this by capturing them and then repeat the result pattern
+        # for that many times.  The divide-by-two takes care of the
+        # extra backslashes.
+        ( (?: \\ \? )+ )
+    }{([^/]{${ \( length($1)/2 ) }})}gx;
+    $glob =~ s{
+        # Brackets denote character classes
+        (
+            \\ \[           # opening
+            (?:             # one or more characters:
+                \\ \\ \\ \] # ...escaped closing bracket
+            |
+                \\ [^\]]    # ...escaped (but not the closing bracket)
+            |
+                [^\\]       # ...normal
+            )+
+            \\ \]           # closing
+        )
+    }{$self->_unescape($1)}egx;
+    $glob =~ s{
+        # Braces denote alternations
+        \\ \{ (         # opening (not part of expression)
+            (?:             # zero or more characters:
+                \\ \\ \\ \} # ...escaped closing brace
+            |
+                \\ [^\}]    # ...escaped (but not the closing brace)
+            |
+                [^\\]       # ...normal
+            )+
+        ) \\ \}         # closing (not part of expression)
+    }{'(?:'.join('|', split(/\\,/, $1, -1)).')'}egx;
+    $glob;
+}
+
+sub _unescape {
+    my $self = shift;
+    my $text = shift;
+    $text =~ s{\\(.)}{$1}g;
+    return $text;
+}
+
+=head2 template_exists PATH
+
+Returns true if PATH is a valid template inside your template root.
+
+=cut
+
+sub template_exists {
+    my $self = shift;
+    my $template = shift;
+
+    return  Jifty->handler->mason->interp->comp_exists( $template);
+}
+
+
+=head2 render_template PATH
+
+Use our templating system to render a template. If there's an error, do the right thing.
+
+
+=cut
+
+sub render_template {
+    my $self = shift;
+    my $template = shift;
+
+    $self->log->debug( "Handling template " . $template );
+    eval { Jifty->handler->mason->handle_comp( $template ); };
+    my $err = $@;
+
+    # Handle parse errors
+    if ( $err and not eval { $err->isa('HTML::Mason::Exception::Abort') } ) {
+
+        # Save the request away, and redirect to an error page
+        Jifty->web->response->error($err);
+        my $c = Jifty::Continuation->new(
+            request  => Jifty->web->request->top_request,
+            response => Jifty->web->response,
+            parent   => Jifty->web->request->continuation,
+        );
+
+        warn "$err";
+
+        # Redirect with a continuation
+        Jifty->web->_redirect(
+            "/__jifty/error/mason_internal_error?J:C=" . $c->id );
+    }
+    elsif ($err) {
+        die $err;
+    }
+
+}
+
+
+=head2 import_plugins
+
+Imports rules from L<Jifty/plugins> into the main dispatcher's space.
+
+=cut
+
+sub import_plugins {
+    my $self = shift;
+
+    # Find the deferred rules
+    my @deferred;
+    push @deferred, $_->dispatcher->rules('DEFERRED') for Jifty->plugins;
+    push @deferred, $self->rules('DEFERRED');
+
+    # XXX TODO: Examine @deferred and find rles that cannot fire
+    # because they match no plugins; they should become un-deferred in
+    # the appropriate group.  This is so 'before plugin qr/Auth/' runs
+    # even if we have no auth plugin
+
+    for my $stage (qw/SETUP RUN CLEANUP/) {
+        my @groups;
+        push @groups, {name => ref $_,  rules => [$_->dispatcher->rules($stage)]} for Jifty->plugins;
+        push @groups, {name => 'Jifty', rules => [$self->rules($stage)]};
+
+        my @left;
+        my @rules;
+        for (@groups) {
+            my $name        = $_->{name};
+            my @group_rules = @{$_->{rules}};
+
+            # XXX TODO: 'after' rules should possibly be placed after
+            # the *last* thing they could match
+            push @rules, $self->_match_deferred(\@deferred, before => $name, $stage);
+            push @rules, @group_rules;
+            push @rules, $self->_match_deferred(\@deferred, after => $name, $stage);
+        }
+
+        no strict 'refs';
+        @{ $self . "::RULES_$stage" } = @rules;
+    }
+    if (@deferred) {
+        warn "Leftover unmatched deferred rules: ".Jifty::YAML::Dump(\@deferred);
+    }
+}
+
+sub _match_deferred {
+    my $self = shift;
+    my ($deferred, $time, $name, $stage) = @_;
+    my %stages = (SETUP => "before", RUN => "on", CLEANUP => "after");
+    $stage = $stages{$stage};
+
+    my @matches;
+    for my $op (@{$deferred}) {
+        # Only care if we're on the correct side of the correct plugin
+        next unless $op->[0] eq $time;
+
+        # Regex or string match, appropriately
+        next unless (
+            ref $op->[1]{plugin}
+            ? ( $name =~ $op->[1]{plugin} )
+            : ( $op->[1]{plugin} eq $name ) );
+
+        # Find the list of subrules
+        my @subrules = ref $op->[2] eq "ARRAY" ? @{$op->[2]} : ($op->[2]);
+
+        # Only toplevel rules make sense (before, after, on)
+        warn "Invalid subrule ".$_->[0] for grep {$_->[0] !~ /^(before|on|after)$/} @subrules;
+        @subrules = grep {$_->[0] =~ /^(before|on|after)$/} @subrules;
+
+        # Only match if the stage matches
+        push @matches, grep {$_->[0] eq $stage} @subrules;
+        @subrules = grep {$_->[0] ne $stage} @subrules;
+
+        $op->[2] = [@subrules];
+    }
+
+    # Clean out any completely matched rules
+    @$deferred = grep {@{$_->[2]}} @$deferred;
+
+    return @matches;
+}
+
+=head2 dump_rules
+
+Dump all defined rules in debug log. It will be called by Jifty on startup.
+
+=cut
+
+sub dump_rules {
+    my $self = shift;
+
+    no strict 'refs';
+    foreach my $stage ( qw/SETUP RUN CLEANUP/ ) {
+
+        my $log = '';
+        foreach my $r ( @{ $self . '::RULES_' . $stage } ) {
+            $log .= _unroll_dumpable_rules( 0,$r );
+        }
+
+        Jifty->log->debug( "Rules in stage $stage:\n", $log) if ($log);
+    }
+};
+
+=head2 _unroll_dumpable_rules LEVEL,RULE
+
+Walk all rules defined in dispatcher starting at rule
+C<RULE> and indentation level C<LEVEL>
+
+=cut
+
+sub _unroll_dumpable_rules {
+    my ($level, $rule) = @_;
+    my $log =
+        # indentation
+        ( "    " x $level ) .
+        # op
+        ( $rule->[0] || "undef op" ) . ' ' .
+        # arguments
+        (
+            ! defined( $rule->[1] )   ? ""                                          :
+            ref $rule->[1] eq 'ARRAY' ? "'" . join("','", @{ $rule->[1] }) . "'" :
+            ref $rule->[1] eq 'HASH'  ? $rule->[1]->{method} . " '" . $rule->[1]->{""} ."'" :
+            ref $rule->[1] eq 'CODE'  ? '{...}' :
+                                        "'" . $rule->[1] . "'"
+        ) .
+        "\n";
+
+    if (ref $rule->[2] eq 'ARRAY') {
+        $level++;
+        foreach my $sr ( @{ $rule->[2] } ) {
+            $log .= _unroll_dumpable_rules( $level, $sr );
+        }
+    }
+
+    return $log;
+}
+
+1;

Added: jifty/branches/schema-plugins/lib/Jifty/Event.pm
==============================================================================
--- (empty file)
+++ jifty/branches/schema-plugins/lib/Jifty/Event.pm	Mon Jan 29 21:05:02 2007
@@ -0,0 +1,143 @@
+use warnings;
+use strict;
+
+package Jifty::Event;
+
+use Storable 'nfreeze';
+use Digest::MD5 qw(md5_hex);
+use vars qw/%PUBLISHER/;
+
+=head1 NAME
+
+Jifty::Event
+
+=head1 DESCRIPTION
+
+An event object from the Jifty::PubSub stream.
+
+=head1 METHODS
+
+=head2 new($payload)
+
+Constructor.  Takes any kind of payload and blesses a scalar reference to it
+into an Event object.
+
+=cut
+
+sub new {
+    my $class   = shift;
+    my $payload = shift;
+    bless \$payload, $class;
+}
+
+=head2 publish()
+
+Inserts the event into the pubsub stream.  If Jifty is configured into
+synchronous republishing, then this method runs a C<republish> on itself
+with all current subscriptions implicitly.  If not, it's simply inserted
+into its main channel for asynchronous republishing later.  
+
+=cut
+
+sub publish {
+    my $self  = shift;
+    my $class = ref($self) || $self;
+
+    return undef unless (Jifty->config->framework('PubSub')->{'Enable'});
+
+    # Always publish to the main stream (needed for async & debugging)
+    # if ($ASYNC || $DEBUGGING) {
+    #    ($PUBLISHER{$class} ||= Jifty->bus->new_publisher($class))->msg($$self);
+    #    return;
+    # }
+
+    # Synchronized auto-republishing
+    # TODO - Prioritize current-user subscriptions first?
+    my $subscriptions = Jifty->bus->modify("$class-subscriptions") || {};
+    while (my ($channel, $queries) = each %$subscriptions) {
+        if ($self->filter(@$queries)) {
+            ($PUBLISHER{$channel} ||= Jifty->bus->new_publisher($channel))->msg($$self);
+        }
+    }
+}
+
+=head2 filter(@query)
+
+Takes multiple class-specific queries, which are evaluated in order by calling L</match>.
+
+=cut
+
+sub filter {
+    my $self = shift;
+    $self->match($_) or return 0 for @_;
+    return 1;
+}
+
+=head2 republish(@query)
+
+Run C<filter> with the queries; if they all succeed, the event is republished
+into that query-specific channel.
+
+=cut
+
+sub republish {
+    my $self = shift;
+    $self->filter(@_) or return;
+
+    my $channel = $self->encode_queries(@_);
+    ($PUBLISHER{$channel} ||= Jifty->bus->new_publisher($channel))->msg($$self);
+}
+
+
+=head2 encode_queries(@query)
+
+Encode queries into some sort of canonical md5 encoding.
+
+=cut
+
+sub encode_queries {
+    my $self    = shift;
+    my $class   = ref($self) || $self;
+    return $class unless @_;
+
+    local $Storable::canonical = 1;
+    return $class . '-' . md5_hex(join('', sort map { Storable::nfreeze($_) } @_));
+}
+
+
+=head2 match($query)
+
+Takes a class-specific query and returns whether it matches.
+
+You almost always want to override this; the default implementation
+simply always return true;
+
+=cut
+
+sub match {
+    1;
+}
+
+=head2 render_arguments()
+
+A list of additional things to push into the C<%ARGS> of the region that
+is about to render this event; see L<Jifty::Subs::Render> for more information.
+
+=cut
+
+sub render_arguments {
+    ();
+}
+
+=head2 data()
+
+This event's payload as a scalar value.
+
+=cut
+
+sub data {
+    ${$_[0]}
+}
+
+
+1;

Added: jifty/branches/schema-plugins/lib/Jifty/Event/Model.pm
==============================================================================
--- (empty file)
+++ jifty/branches/schema-plugins/lib/Jifty/Event/Model.pm	Mon Jan 29 21:05:02 2007
@@ -0,0 +1,52 @@
+package Jifty::Event::Model;
+
+use warnings;
+use strict;
+use Carp;
+use base qw/Jifty::Event/;
+
+
+
+=head1 NAME
+
+Jifty::Event::Model
+
+=head1 DESCRIPTION
+
+Objects in this class represent changes to Jifty::Record classes (any action on a model class)
+as Jifty::Events.
+
+As yet, this functionality is unused.
+
+
+=cut
+
+=head2 new
+
+creates a new L<Jifty::Event::Model> object.  If C<PubSub> is enabled for your application, 
+checks to make sure that this event has the following (underdocumented) parameters:
+
+ record_id record_class action_class action_arguments timestamp result as_hash_before as_hash_after current_user_id
+
+=cut
+
+
+sub new {
+    my $class = shift;
+    my $self = $class->SUPER::new(@_);
+    $self->_check() if (Jifty->config->framework('PubSub')->{'Enable'});
+    return $self;
+}
+
+
+sub _check {
+    my $self = shift;
+    for (qw(record_id record_class action_class
+        action_arguments timestamp result as_hash_before
+        as_hash_after current_user_id)) {
+        Carp::confess("$self missing required parameter $_ ")
+            unless ( defined $$self->{$_} );
+        };
+}
+
+1;

Added: jifty/branches/schema-plugins/lib/Jifty/Everything.pm
==============================================================================
--- (empty file)
+++ jifty/branches/schema-plugins/lib/Jifty/Everything.pm	Mon Jan 29 21:05:02 2007
@@ -0,0 +1,85 @@
+use warnings;
+use strict;
+
+package Jifty::Everything;
+
+=head1 NAME
+
+Jifty::Everything - Load all of the important Jifty modules at once.
+
+=cut
+
+use Cwd ();
+BEGIN {
+    # Cwd::cwd() insists doing `pwd`, which is a few hundres of shell
+    # outs just in the BEGIN time for Module::Pluggable to load things.
+    if ($^O ne 'MSWin32') {
+        require POSIX;
+        *Cwd::cwd = *POSIX::getcwd;
+    }
+}
+
+use Jifty ();
+use Jifty::I18N ();
+use Jifty::Dispatcher ();
+use Jifty::Object ();
+use Jifty::Config ();
+use Jifty::Handle ();
+use Jifty::ClassLoader ();
+use Jifty::Util ();
+use Jifty::API ();
+use Jifty::DateTime ();
+use Jifty::Record ();
+use Jifty::Collection ();
+use Jifty::Action ();
+use Jifty::Action::Record ();
+use Jifty::Action::Record::Create ();
+use Jifty::Action::Record::Update ();
+use Jifty::Action::Record::Delete ();
+
+
+use Jifty::Continuation ();
+
+use Jifty::LetMe ();
+
+use Jifty::Logger ();
+use Jifty::Handler ();
+use Jifty::View::Static::Handler ();
+use Jifty::View::Mason::Handler ();
+
+use Jifty::Model::Metadata ();
+use Jifty::Model::Session ();
+use Jifty::Model::SessionCollection ();
+
+
+use Jifty::Request ();
+use Jifty::Request::Mapper ();
+use Jifty::Result ();
+use Jifty::Response ();
+use Jifty::CurrentUser ();
+
+# We can _not_ load Server.pm unless we're in a Server context because
+# HTTP::Server::Simple::Mason bastardizes HTML::Mason::FakeApache::send_http_header
+# with hook::lexwrap
+#use Jifty::Server;
+
+use Jifty::Web ();
+use Jifty::Web::Session ();
+use Jifty::Web::PageRegion ();
+use Jifty::Web::Form ();
+use Jifty::Web::Form::Clickable ();
+use Jifty::Web::Form::Element ();
+use Jifty::Web::Form::Link ();
+use Jifty::Web::Form::Field ();
+use Jifty::Web::Menu ();
+
+use Jifty::Subs ();
+use Jifty::Subs::Render ();
+
+use Jifty::Module::Pluggable;
+Jifty::Module::Pluggable->import(search_path => ['Jifty::Web::Form::Field'],
+                          require     => 1,
+                          except      => qr/\.#/);
+__PACKAGE__->plugins;
+
+1;

Added: jifty/branches/schema-plugins/lib/Jifty/Filter/DateTime.pm
==============================================================================
--- (empty file)
+++ jifty/branches/schema-plugins/lib/Jifty/Filter/DateTime.pm	Mon Jan 29 21:05:02 2007
@@ -0,0 +1,63 @@
+use warnings;
+use strict;
+
+=head1 NAME
+
+Jifty::Filter::DateTime -- A Jifty::DBI filter to work with
+                          Jifty::DateTime objects
+
+=head1 DESCRIPTION
+
+Jifty::Filter::DateTime promotes DateTime objects to Jifty::DateTime
+objects on load. This has the side effect of setting their time zone
+based on the record's current user's preferred time zone, when
+available.
+
+This is intended to be combined with C<Jifty::DBI::Filter::Date> or
+C<Jifty::DBI::Filter::DateTime>, e.g.
+
+    column created =>
+      type is 'timestamp',
+      filters are qw( Jifty::Filter::DateTime Jifty::DBI::Filter::DateTime),
+      label is 'Created',
+      is immutable;
+
+=cut
+
+package Jifty::Filter::DateTime;
+use base qw(Jifty::DBI::Filter);
+
+
+=head2 decode
+
+If the value is a DateTime, replace it with a Jifty::DateTime
+representing the same time, setting the time zone in the process.
+
+=cut
+
+
+sub decode {
+    my $self = shift;
+    my $value_ref = $self->value_ref;
+
+    return unless ref($$value_ref) && $$value_ref->isa('DateTime');
+
+    # XXX There has to be a better way to do this
+    my %args;
+    for (qw(year month day hour minute second nanosecond formatter)) {
+        $args{$_} = $$value_ref->$_ if(defined($$value_ref->$_));
+    }
+
+    my $dt = Jifty::DateTime->new(%args);
+
+    $$value_ref = $dt;
+}
+
+=head1 SEE ALSO
+
+L<Jifty::DBI::Filter::Date>, L<Jifty::DBI::Filter::DateTime>,
+L<Jifty::DateTime>
+
+=cut
+
+1;

Added: jifty/branches/schema-plugins/lib/Jifty/Handle.pm
==============================================================================
--- (empty file)
+++ jifty/branches/schema-plugins/lib/Jifty/Handle.pm	Mon Jan 29 21:05:02 2007
@@ -0,0 +1,217 @@
+use warnings;
+use strict;
+
+package Jifty::Handle;
+
+=head1 NAME
+
+Jifty::Handle -- A database handle class for Jifty
+
+=head1 DESCRIPTION
+
+A wrapper around Jifty::DBI::Handle which is aware of versions in the
+database
+
+=cut
+
+use Jifty::Util;
+our @ISA;
+
+=head1 METHODS
+
+=head2 new PARAMHASH
+
+This class method instantiates a new L<Jifty::Handle> object. This
+object deals with database handles for the system.  After it is
+created, it will be a subclass of L<Jifty::DBI::Handle>.
+
+=cut
+
+# Setup database handle based on config data
+sub new {
+    my $class = shift;
+
+    my $driver = Jifty->config->framework('Database')->{'Driver'};
+    if ($driver eq 'Oracle') {
+        $ENV{'NLS_LANG'} = "AMERICAN_AMERICA.AL32UTF8";
+        $ENV{'NLS_NCHAR'} = "AL32UTF8";
+    }
+   
+    # We do this to avoid Jifty::DBI::Handle's magic reblessing, because
+    # it breaks subclass methods.
+    my $driver_class  = "Jifty::DBI::Handle::".  $driver;
+    Jifty::Util->require($driver_class);
+
+    unshift @ISA, $driver_class;
+    return $class->SUPER::new();
+}
+
+=head2 canonical_database_name
+
+Returns the canonical name of the application's database (the actual name that will
+be given to the database driver).  This name is a lower-case version of the C<Database>
+argument in the C<Database> section of the framework config.
+
+For SQLite databases (where the database name is actually a filename), this also converts
+a relative path into an absolute path based at the application root.
+
+=cut
+
+sub canonical_database_name {
+    my $self_or_class = shift;
+    my $db_config = Jifty->config->framework('Database');
+
+    # XXX TODO consider canonicalizing to all-lowercase, once there are no
+    # legacy databases
+    my $db = $db_config->{'Database'};
+
+    if ($db_config->{'Driver'} =~ /SQLite/) {
+        $db = Jifty::Util->absolute_path($db);
+    } 
+
+    return $db;
+} 
+
+=head2 connect ARGS
+
+Like L<Jifty::DBI>'s connect method but pulls the name of the database
+from the current L<Jifty::Config>.
+
+=cut
+
+sub connect {
+    my $self = shift;
+    my %args = (@_);
+    my %db_config =  (%{Jifty->config->framework('Database')}, Database => $self->canonical_database_name);
+
+    my %lc_db_config;
+    # Skip the non-dsn keys, but not anything else
+    for (grep {!/^checkschema|version|recordbaseclass$/i} keys %db_config) {
+        $lc_db_config{lc($_)} = $db_config{$_};
+    }
+    $self->SUPER::connect( %lc_db_config , %args);
+    $self->{db_config} = { %lc_db_config , %args };
+    $self->dbh->{LongReadLen} = Jifty->config->framework('MaxAttachmentSize') || '10000000';
+}
+
+
+=head2 check_schema_version
+
+Make sure that we have a recent enough database schema.  If we don't,
+then error out.
+
+=cut
+
+sub check_schema_version {
+    require Jifty::Model::Metadata;
+
+    # Application db version check
+    {
+        my $dbv  = Jifty::Model::Metadata->load("application_db_version");
+        my $appv = Jifty->config->framework('Database')->{'Version'};
+
+        if ( not defined $dbv ) {
+            # First layer of backwards compatibility -- it used to be in _db_version
+            my @v;
+            eval {
+                local $SIG{__WARN__} = sub { };
+                @v = Jifty->handle->fetch_result(
+                    "SELECT major, minor, rev FROM _db_version");
+            };
+            $dbv = join( ".", @v ) if @v == 3;
+        }
+        if ( not defined $dbv ) {
+            # It was also called the 'key' column, not the data_key column
+            eval {
+                local $SIG{__WARN__} = sub { };
+                $dbv = Jifty->handle->fetch_result(
+                    "SELECT value FROM _jifty_metadata WHERE key = 'application_db_version'");
+            } or undef($dbv);
+        }
+
+        die
+            "Application schema has no version in the database; perhaps you need to run this:\n"
+            . "\t bin/jifty schema --setup\n"
+            unless defined $dbv;
+
+        die
+            "Application schema version in database ($dbv) doesn't match application schema version ($appv)\n"
+            . "Please run `bin/jifty schema --setup` to upgrade the database.\n"
+            unless version->new($appv) == version->new($dbv);
+    }
+
+    # Jifty db version check
+    {
+
+        # If we got here, the application had a version (somehow) so
+        # this is an upgrade.  If $dbv is undef, it's because it's
+        # from before when the _jifty_metadata table existed.
+        my $dbv
+            = version->new( Jifty::Model::Metadata->load("jifty_db_version")
+                || '0.60426' );
+        my $appv = version->new($Jifty::VERSION);
+        die
+            "Internal jifty schema version in database ($dbv) doesn't match running jifty version ($appv)\n"
+            . "Please run `bin/jifty schema --setup` to upgrade the database.\n"
+            unless $appv == $dbv;
+    }
+
+}
+
+
+=head2 create_database MODE
+
+C<MODE> is either "print" or "execute".
+
+This method either prints the commands necessary to create the database
+or actually creates it, depending on the value of MODE.
+
+=cut
+
+sub create_database {
+    my $self = shift;
+    my $mode = shift || 'execute';
+    my $database = $self->canonical_database_name;
+    my $driver   = Jifty->config->framework('Database')->{'Driver'};
+    my $query = "CREATE DATABASE $database;\n";
+    if ( $mode eq 'print') {
+        print $query;
+    } elsif ( $driver !~ /SQLite/ ) {
+        $self->simple_query($query);
+    }
+}
+
+=head2 drop_database MODE
+
+C<MODE> is either "print" or "execute".
+
+This method either prints the commands necessary to drop the database
+or actually drops it, depending on the value of MODE.
+
+=cut
+
+sub drop_database {
+    my $self = shift;
+    my $mode = shift || 'execute';
+    my $database = $self->canonical_database_name;
+    my $driver   = Jifty->config->framework('Database')->{'Driver'};
+    if ( $mode eq 'print' ) {
+        print "DROP DATABASE $database;\n";
+    } elsif ( $driver =~ /SQLite/ ) {
+
+        # Win32 complains when you try to unlink open DB
+        $self->disconnect if $^O eq 'MSWin32';
+        unlink($database);
+    } else {
+        $self->simple_query("DROP DATABASE $database");
+    }
+}
+
+
+=head1 AUTHOR
+
+Various folks at BestPractical Solutions, LLC.
+
+=cut
+
+1;

Added: jifty/branches/schema-plugins/lib/Jifty/Handler.pm
==============================================================================
--- (empty file)
+++ jifty/branches/schema-plugins/lib/Jifty/Handler.pm	Mon Jan 29 21:05:02 2007
@@ -0,0 +1,237 @@
+use strict;
+use warnings;
+
+package Jifty::Handler;
+
+=head1 NAME
+
+Jifty::Handler - Methods related to the Mason handler
+
+=head1 SYNOPSIS
+
+  use Jifty;
+  Jifty->new();
+
+  my $handler = Jifty::Handler->handle_request( cgi => $cgi );
+
+  # after each request is handled
+  Jifty::Handler->cleanup_request;
+
+=head1 DESCRIPTION
+
+L<Jifty::Handler> provides methods required to deal with Mason CGI
+handlers.  
+
+=cut
+
+use base qw/Class::Accessor::Fast/;
+use Module::Refresh ();
+
+BEGIN {
+    # Creating a new CGI object breaks FastCGI in all sorts of painful
+    # ways.  So wrap the call and preempt it if we already have one
+    use CGI ();
+
+    # If this file gets reloaded using Module::Refresh, don't do this
+    # magic again, or we'll get infinite recursion
+    unless (CGI->can('__jifty_real_new')) {
+        *CGI::__jifty_real_new = \&CGI::new;
+
+        no warnings qw(redefine);
+        *CGI::new = sub {
+            return Jifty->handler->cgi if Jifty->handler->cgi;
+            CGI::__jifty_real_new(@_);	
+        }
+    }
+};
+
+
+
+__PACKAGE__->mk_accessors(qw(mason dispatcher static_handler cgi apache stash));
+
+=head2 new
+
+Create a new Jifty::Handler object. Generally, Jifty.pm does this only once at startup.
+
+=cut
+
+sub new {
+    my $class = shift;
+    my $self  = {};
+    bless $self, $class;
+
+    $self->create_cache_directories();
+#    wrap 'CGI::new', pre => sub {
+#        $_[-1] = Jifty->handler->cgi if Jifty->handler->cgi;
+#    };
+
+    $self->dispatcher( Jifty->app_class( "Dispatcher" ) );
+    Jifty::Util->require( $self->dispatcher );
+    $self->dispatcher->import_plugins;
+    $self->dispatcher->dump_rules;
+    
+    $self->mason( Jifty::View::Mason::Handler->new( $self->mason_config ) );
+
+    $self->static_handler(Jifty::View::Static::Handler->new());
+
+    return $self;
+}
+
+
+=head2 create_cache_directories
+
+Attempts to create our app's mason cache directory.
+
+=cut
+
+sub create_cache_directories {
+    my $self = shift;
+
+    for ( Jifty->config->framework('Web')->{'DataDir'} ) {
+        Jifty::Util->make_path( Jifty::Util->absolute_path($_) );
+    }
+}
+
+
+=head2 mason_config
+
+Returns our Mason config.  We use the component root specified in the
+C<Web/TemplateRoot> framework configuration variable (or C<html> by
+default).  Additionally, we set up a C<jifty> component root, as
+specified by the C<Web/DefaultTemplateRoot> configuration.  All
+interpolations are HTML-escaped by default, and we use the fatal error
+mode.
+
+=cut
+
+sub mason_config {
+    my %config = (
+        static_source => 1,
+        use_object_files => 1,
+        preprocess => sub {
+            # Force UTF-8 semantics on all our components by
+            # prepending this block to all components as Mason
+            # components defaults to parse the text as Latin-1
+            ${$_[0]} =~ s!^!<\%INIT>use utf8;</\%INIT>\n!;
+        },
+        data_dir =>  Jifty::Util->absolute_path( Jifty->config->framework('Web')->{'DataDir'} ),
+        allow_globals => [
+            qw[ $JiftyWeb ],
+            @{Jifty->config->framework('Web')->{'Globals'} || []},
+        ],
+        comp_root     => [ 
+                          [application =>  Jifty::Util->absolute_path( Jifty->config->framework('Web')->{'TemplateRoot'} )],
+                          [jifty => Jifty->config->framework('Web')->{'DefaultTemplateRoot'}],
+                         ],
+        %{ Jifty->config->framework('Web')->{'MasonConfig'} },
+    );
+
+    for my $plugin (Jifty->plugins) {
+        my $comp_root = $plugin->template_root;
+        next unless $comp_root;
+        push @{ $config{comp_root} }, [ ref($plugin)."-".Jifty->web->serial => $comp_root ];
+    }
+
+    # In developer mode, we want halos, refreshing and all that other good stuff. 
+    if (Jifty->config->framework('DevelMode') ) {
+        push @{$config{'plugins'}}, 'Jifty::Mason::Halo';
+        $config{static_source}    = 0;
+        $config{use_object_files} = 0;
+    }
+    return (%config);
+        
+}
+
+=head2 cgi
+
+Returns the L<CGI> object for the current request, or C<undef> if
+there is none.
+
+=head2 apache
+
+Returns the L<HTML::Mason::FakeApache> or L<Apache> object for the
+current request, ot C<undef> if there is none.
+
+=head2 handle_request
+
+When your server processs (be it Jifty-internal, FastCGI or anything
+else) wants to handle a request coming in from the outside world, you
+should call C<handle_request>.
+
+=over
+
+=item cgi
+
+A L<CGI> object that your server has already set up and loaded with
+your request's data.
+
+=back
+
+=cut
+
+
+sub handle_request {
+    my $self = shift;
+    my %args = (
+        cgi => undef,
+        @_
+    );
+
+    if ( Jifty->config->framework('DevelMode') ) {
+        Module::Refresh->refresh;
+        Jifty::I18N->refresh;
+    }
+
+    Jifty::I18N->get_language_handle;
+
+    $self->cgi( $args{cgi} );
+    $self->apache( HTML::Mason::FakeApache->new( cgi => $self->cgi ) );
+
+    # Build a new stash for the life of this request
+    $self->stash({});
+    local $HTML::Mason::Commands::JiftyWeb = Jifty::Web->new();
+
+    Jifty->web->request( Jifty::Request->new()->fill( $self->cgi ) );
+    Jifty->web->response( Jifty::Response->new );
+    Jifty->api->reset;
+    $_->new_request for Jifty->plugins;
+
+    Jifty->log->debug( "Received request for " . Jifty->web->request->path );
+    my $sent_response = 0;
+    $sent_response
+        = $self->static_handler->handle_request( Jifty->web->request->path )
+        if ( Jifty->config->framework('Web')->{'ServeStaticFiles'} );
+
+    Jifty->web->setup_session unless $sent_response;
+
+    # Return from the continuation if need be
+    Jifty->web->request->return_from_continuation;
+
+    unless ($sent_response) {
+        Jifty->web->session->set_cookie;
+        $self->dispatcher->handle_request()
+    }
+
+    $self->cleanup_request();
+
+}
+
+=head2 cleanup_request
+
+Dispatchers should call this at the end of each request, as a class method.
+It flushes the session to disk, as well as flushing L<Jifty::DBI>'s cache. 
+
+=cut
+
+sub cleanup_request {
+    my $self = shift;
+    # Clean out the cache. the performance impact should be marginal.
+    # Consistency is improved, too.
+    Jifty->web->session->unload();
+    Jifty::Record->flush_cache if Jifty::Record->can('flush_cache');
+    $self->cgi(undef);
+    $self->apache(undef);
+    $self->stash(undef);
+}
+
+1;

Added: jifty/branches/schema-plugins/lib/Jifty/I18N.pm
==============================================================================
--- (empty file)
+++ jifty/branches/schema-plugins/lib/Jifty/I18N.pm	Mon Jan 29 21:05:02 2007
@@ -0,0 +1,208 @@
+use strict;
+use warnings;
+
+package Jifty::I18N;
+use base 'Locale::Maketext';
+use Locale::Maketext::Lexicon ();
+use Email::MIME::ContentType;
+use Encode::Guess qw(iso-8859-1);
+use File::ShareDir ':ALL';
+
+=head1 NAME
+
+Jifty::I18N - Internationalization framework for Jifty
+
+=head1 METHODS
+
+=head2 C<_>
+
+This module exports the C<loc> method, which it inherits from
+L<Locale::Maketext::Simple>. Jifty aliases this method to C<_()> for 
+your convenience.
+
+=cut
+
+=head2 new
+
+Set up Jifty's internationalization for your application.  This pulls
+in Jifty's PO files, your PO files and then exports the _ function into
+the wider world.
+
+=cut
+
+my $DynamicLH;
+
+sub new {
+    my $class = shift;
+    my $self  = {};
+    bless $self, $class;
+
+    my @import = (
+        'Gettext',Jifty->config->framework('L10N')->{'PoDir'}. '/*.po',
+        'Gettext',Jifty->config->framework('L10N')->{'DefaultPoDir'}. '/*.po'
+        );
+
+    foreach my $plugin (Jifty->plugins) {
+        local $@;
+        my $dir = eval { module_dir(ref($plugin)); };
+        next unless $dir;
+        push @import, 'Gettext';
+        push @import, $dir . '/po/*.po';
+    };
+
+    Locale::Maketext::Lexicon->import(
+        {   '*' => \@import,
+            _decode => 1,
+            _auto   => 1,
+            _style  => 'gettext',
+        }
+    );
+
+    # Allow hard-coded languages in the config file
+    my $lang = Jifty->config->framework('L10N')->{'Lang'};
+    $lang = [defined $lang ? $lang : ()] unless ref($lang) eq 'ARRAY';
+
+    my $lh = $class->get_handle(@$lang);
+    $DynamicLH = \$lh unless @$lang; 
+    $self->init;
+
+    my $loc_method = sub {
+        # Retain compatibility with people using "-e _" etc.
+        return \*_ unless @_;
+
+        # When $_[0] is undef, return undef.  When it is '', return ''.
+        no warnings 'uninitialized';
+        return $_[0] unless (length $_[0]);
+
+        local $@;
+        # Force stringification to stop Locale::Maketext from choking on
+        # things like DateTime objects.
+        my @stringified_args = map {"$_"} @_;
+        my $result = eval { $lh->maketext(@stringified_args) };
+        if ($@) {
+            # Sometimes Locale::Maketext fails to localize a string and throws
+            # an exception instead.  In that case, we just return the input.
+            return join(' ', @stringified_args);
+        }
+        return $result;
+    };
+
+    {
+        no strict 'refs';
+        no warnings 'redefine';
+        *_ = $loc_method;
+    }
+    return $self;
+}
+
+=head2 get_language_handle
+
+Get the lanauge language for this request.
+
+=cut
+
+sub get_language_handle {
+    my $self = shift;
+    $$DynamicLH = $self->get_handle() if $DynamicLH;
+}
+
+=head2 refresh
+
+Used by L<Jifty::Handler> in DevelMode to reload F<.po> files whenever they
+are modified on disk.
+
+=cut
+
+my $last_modified = '';
+sub refresh {
+    my $modified = join(
+        ',',
+        sort map { $_ => -M $_ } map { glob("$_/*.po") } (
+            Jifty->config->framework('L10N')->{'PoDir'},
+            Jifty->config->framework('L10N')->{'DefaultPoDir'}
+        )
+    );
+    if ($modified ne $last_modified) {
+        Jifty::I18N->new;
+        $last_modified = $modified;
+    }
+}
+
+
+
+=head2 promote_encoding STRING [CONTENT-TYPE]
+
+Return STRING promoted to our best-guess of an appropriate
+encoding. STRING should B<not> have the UTF-8 flag set when passed in.
+
+Optionally, you can pass a MIME content-type string as a second
+argument. If it contains a charset= parameter, we will use that
+encoding. Failing that, we use Encode::Guess to guess between UTF-8
+and iso-latin-1. If that fails, and the string validates as UTF-8, we
+assume that. Finally, we fall back on returning the string as is.
+
+=cut
+
+# XXX TODO This possibly needs to be more clever and/or configurable
+
+sub promote_encoding {
+    my $class = shift;
+    my $string = shift;
+    my $content_type = shift;
+
+    $content_type = Email::MIME::ContentType::parse_content_type($content_type) if $content_type;
+    my $charset = $content_type->{attributes}->{charset} if $content_type;
+
+    # XXX TODO Is this the right thing? Maybe we should just return
+    # the string as-is.
+    Encode::_utf8_off($string);
+
+    if($charset) {
+        $string = Encode::decode($charset, $string);
+    } else {
+        my $encoding = Encode::Guess->guess($string);
+        if(!ref($encoding)) {
+            local $@;
+            eval {
+                # Try utf8
+                $string = Encode::decode_utf8($string, 1);
+            };
+            if($@) {
+                warn "Unknown encoding -- none specified, couldn't guess, not valid UTF-8";
+            }
+        } else {
+            $string = $encoding->decode($string) if $encoding;
+        }
+    }
+
+    return $string;
+}
+
+=head2 maybe_decode_utf8 STRING
+
+Attempt to decode STRING as UTF-8. If STRING is not valid UTF-8, or
+already contains wide characters, return it undecoded.
+
+N.B: In an ideal world, we wouldn't need this function, since we would
+know whether any given piece of input is UTF-8. However, the world is
+not ideal.
+
+=cut
+
+sub maybe_decode_utf8 {
+    my $class = shift;
+    my $string = shift;
+
+    local $@;
+    eval {
+        $string =  Encode::decode_utf8($string);
+    };
+    Carp::carp "Couldn't decode UTF-8: $@" if $@;
+    return $string;
+}
+
+package Jifty::I18N::en;
+use base 'Locale::Maketext';
+our %Lexicon = ( _fallback => 1, _AUTO => 1 );
+
+1;

Added: jifty/branches/schema-plugins/lib/Jifty/JSON.pm
==============================================================================
--- (empty file)
+++ jifty/branches/schema-plugins/lib/Jifty/JSON.pm	Mon Jan 29 21:05:02 2007
@@ -0,0 +1,110 @@
+use warnings;
+use strict;
+
+package Jifty::JSON;
+
+=head1 NAME
+
+Jifty::JSON -- Wrapper around L<JSON>
+
+=head1 DESCRIPTION
+
+Provides a wrapper around the L<JSON> library.
+
+The JSON specification at L<http://www.json.org/> states that only
+double-quotes are possible for specifying strings.  However, for the purposes
+of embedding Javascript-compatible objects in XHTML attributes (which use
+double-quotes), we sometimes want to provide strings in single quotes.
+This provides a version of L<JSON/objToJson> which allows
+single-quoted string output.
+
+If the faster L<JSON::Syck> is available, it is preferred over the pure-perl
+L<JSON>, as it provides native support for single-quoted strings.
+
+=head1 METHODS
+
+=cut
+
+BEGIN {
+    local $@;
+    no strict 'refs';
+    no warnings 'once';
+    if (eval { require JSON::Syck; JSON::Syck->VERSION(0.05) }) {
+        *jsonToObj = *_jsonToObj_syck;
+        *objToJson = *_objToJson_syck;
+        $JSON::Syck::ImplicitUnicode = 1;
+    }
+    else {
+        require JSON;
+        *jsonToObj = *_jsonToObj_pp;
+        *objToJson = *_objToJson_pp;
+        $JSON::UTF8 = 1;
+    }
+}
+
+=head2 jsonToObj JSON, [ARGUMENTS]
+
+For completeness, C<Jifty::JSON> provides a C<jsonToObj>.  It is
+identical to L<JSON/jsonToObj>.
+
+=cut
+
+sub _jsonToObj_syck {
+    local $JSON::Syck::SingleQuote = 0;
+    JSON::Syck::Load($_[0]);
+}
+
+sub _jsonToObj_pp {
+    return JSON::jsonToObj(@_);
+}
+
+=head2 objToJson OBJECT, [ARGUMENTS]
+
+This method is identical to L<JSON/objToJson>, except it has an
+additional possible option.  The C<singlequote> option, if set to a
+true value in the C<ARGUMENTS> hashref, overrides L<JSON::Converter>'s
+string output method to output single quotes as delimters instead of
+double quotes.
+
+=cut
+
+sub _objToJson_syck {
+    my ($obj, $args) = @_;
+
+    local $JSON::Syck::SingleQuote = $args->{singlequote};
+    local $JSON::Syck::ImplicitUnicode = 1;
+    JSON::Syck::Dump($obj);
+}
+
+# We should escape double-quotes somehow, so that we can guarantee
+# that double-quotes *never* appear in the JSON string that is
+# returned.
+sub _objToJson_pp {
+    my ($obj, $args) = @_;
+
+    # Unless we're asking for single-quoting, just do what JSON.pm
+    # does
+    return JSON::Converter::objToJson($obj)
+      unless delete $args->{singlequote};
+
+    # Otherwise, insert our own stringify sub
+    no warnings 'redefine';
+    my %esc = (
+        "\n" => '\n',
+        "\r" => '\r',
+        "\t" => '\t',
+        "\f" => '\f',
+        "\b" => '\b',
+        "'"  => '\\\'',
+        "\\" => '\\\\',
+    );
+    local *JSON::Converter::_stringfy = sub {
+        my $arg = shift;
+        $arg =~ s/([\\\n'\r\t\f\b])/$esc{$1}/eg;
+        $arg =~ s/([\x00-\x07\x0b\x0e-\x1f])/'\\u00' . unpack('H2',$1)/eg;
+        return "'" . $arg ."'";
+    };
+    return JSON::objToJson($obj, $args);
+}
+
+1;

Added: jifty/branches/schema-plugins/lib/Jifty/LetMe.pm
==============================================================================
--- (empty file)
+++ jifty/branches/schema-plugins/lib/Jifty/LetMe.pm	Mon Jan 29 21:05:02 2007
@@ -0,0 +1,308 @@
+use warnings;
+use strict;
+
+package Jifty::LetMe;
+use Digest::MD5 ();
+use Math::BigInt::Calc;
+use String::Koremutake ();
+
+use base qw/Jifty::Object Class::Accessor::Fast/;
+
+__PACKAGE__->mk_accessors ( qw/checksum_provided email path args until user/);
+
+=head1 NAME
+
+Jifty::LetMe - A way to expose single-link URLs to your applications
+
+=head2 new
+
+Create a new "LetMe" authentication object; it takes no parameters.
+It calls L</_init> to do any initialization.
+
+A LetMe is a way to provide a one-time-use URL for a particular purpose.
+All LetMe objects give you a way to validate someone's identity and to
+allow them a very small set of possible actions or page-access permissions.
+
+For example, you can put a LetMe URL in an email to a new user,
+so that when they click on the URL you know that their email address
+is valid.
+
+=cut
+
+sub new {
+    my $class = shift;
+    my $self = {};
+    bless $self, $class;
+    $self->args({});
+    $self->_init(@_);
+    return $self;
+
+}
+
+=head2 _init @_
+
+Called with whatever L</new> was called with.  By default, does nothing.
+
+=cut
+
+sub _init { return shift }
+
+=head2 user
+
+Contains an app-specific "user" object.
+
+=cut
+
+=head2 validated_current_user
+
+If the user has presented a valid token, returns an (app-specific
+subclass of the) L<Jifty::CurrentUser> object for the user who has the
+email address in $self->email.  If no user has that email address,
+returns undef.
+
+=cut
+
+sub validated_current_user {
+    my $self = shift;
+    return undef unless ( $self->validate );
+    return $self->_user_from_email($self->email);
+
+}
+
+
+=head2 _user_from_email ADDRESS
+
+Returns an (app-specific subclass of the) L<Jifty::CurrentUser> object
+for the user who has the email address I<ADDRESS>.
+
+=cut
+
+sub _user_from_email {
+    my $self = shift;
+    my $email = shift;
+    my $currentuser_object_class = Jifty->app_class("CurrentUser");
+    return $currentuser_object_class->new( email => $email );
+}
+
+sub _generate_digest {
+    my $self = shift;
+
+    # get user's generic secret
+    my $user;
+    return '' unless ( $user = $self->_user_from_email($self->email) );
+    return '' unless ($user->auth_token);
+
+
+
+    # build an md5sum of the email token and until and our secret
+    my $digest = Digest::MD5->new();
+    $digest->add( $user->auth_token );
+    $digest->add( $self->path );
+    my %args = %{$self->args};
+    $digest->add( Encode::encode_utf8($_), Encode::encode_utf8($args{$_})) for sort keys %args;
+    $digest->add( $self->until ) if ($self->until);
+    return $digest->hexdigest();
+}
+
+
+
+=head2 generate_checksum
+
+Returns an auth checksum for the current combination of
+
+    user
+    path
+    arguments
+    until
+
+=cut
+
+sub generate_checksum {
+    my $self = shift;
+
+    return substr( $self->_generate_digest, 0, 16 );
+}
+
+=head2 generate_koremutake_checksum
+
+Generate a slightly more pronouncable version of the checksum using
+L<String::Koremutake>.  Due to hex -> integer limitations, this is
+imporecise and may vary depending on the platform it is used on; as
+such, it is deprecated.
+
+=cut
+
+sub generate_koremutake_checksum {
+    my $self = shift;
+
+    # Only take the first 16 characters. We're really just trying to
+    # get something reasonably short, memorable and unguessable. Also,
+    # don't use Math::BigInt->new directly for simple computation,
+    # because it insists exporting overload to us, which makes
+    # devel::cover and devel::dprof very sad.  This is deprecated in
+    # favor of generate_checksum, which returns a straight hex digest.
+    my $integer_digest = Math::BigInt::Calc->_str(
+        Math::BigInt::Calc->_from_hex(
+            substr( $self->_generate_digest, 0, 16 )
+        )
+    );
+
+    # koremutake it.  This loses precision, since most perls can't
+    # deal with 64 bits with precision.  Thus, $integer_digest ends up
+    # being rounded, possibly in unpredicatable ways.
+    my $k = String::Koremutake->new;
+    return( $k->integer_to_koremutake($integer_digest));
+
+}
+
+=head2 from_token PATH
+
+Parse a string of the form 
+
+mylongusername at example.com/update_task/23/until/20050101/bekidrikufryvagygefuba
+
+into 
+
+      email => mylongusername at example.com,
+      token => 'update_task/23'
+      until => 20050101,
+      checksum_provided => bekidrikufryvagygefuba
+
+=cut
+
+sub from_token {
+    my $self = shift;
+    my $token = shift;
+
+    my @atoms = split('/',$token);
+
+    $self->email( Jifty::I18N->maybe_decode_utf8(URI::Escape::uri_unescape( shift @atoms )) );
+    $self->path( shift @atoms );
+    $self->checksum_provided( pop @atoms );
+
+    # If they don't even have the right number of items in the path, then we know that it's not valid
+    return undef unless (scalar @atoms % 2 == 0); 
+
+    my %args = map { Jifty::I18N->maybe_decode_utf8(URI::Escape::uri_unescape($_)) } @atoms;
+    $self->until( delete $args{until} ) if $args{until};
+
+    $self->args(\%args);
+}
+
+
+=head2 as_token
+
+Returns the "letme" token for this set of credentials. This should round
+trip cleanly with from_token
+
+=cut
+
+sub as_token {
+    my $self = shift;
+    $self->_generate_token( email => $self->email );
+}
+
+=head2 as_encoded_token
+
+A variant of as_token that encodes the user's email address suitably
+for passing in a URL
+
+=cut
+
+sub as_encoded_token {
+    my $self = shift;
+    $self->_generate_token( email => URI::Escape::uri_escape_utf8($self->email) );
+}
+
+sub _generate_token {
+    my $self = shift;
+    my %args = (email => undef, @_);
+    return join ('/', 
+        $args{'email'},
+        $self->path,
+        (map {URI::Escape::uri_escape_utf8($_)} %{$self->args}),
+        (defined $self->until ? ( 'until', $self->until ) : () ), #?
+        $self->generate_checksum  
+        );
+
+}
+
+
+=head2 as_url
+
+Returns the fully qualified URL for this LetMe. It's composed of
+Jifty->web->url, L</base_path> and L</as_encoded_token>
+
+=cut
+
+sub as_url {
+    my $self = shift;
+    return Jifty->web->url(path => $self->base_path . $self->as_encoded_token);
+
+}
+
+
+=head2 base_path
+
+By default, all "LetMe" actions live at URLs under '/let' inside your
+application.  Override this subroutine to change that.
+
+By default, it returns '/let/'
+
+=cut
+
+sub base_path {
+    return '/let/';
+
+}
+
+
+=head2 validate
+
+Returns true if the credentials the user presented validate ok.
+Returns false otherwise.
+
+=cut
+
+sub validate {
+    my $self = shift;
+
+    # email must exist
+
+    unless ($self->_user_from_email($self->email)) {
+        return undef;
+    }
+
+    unless ($self->path) {
+        return undef;
+    }
+    unless ($self->checksum_provided) {
+        return undef;
+    }
+
+
+    unless ($self->_correct_checksum_provided) {
+        return undef;
+    }
+
+    return 1;
+}
+
+
+=head2 _correct_checksum_provided
+
+Returns true if the checksum the user provided is correct. Doesn't
+actually do much input checking. You want to call "validate"
+
+=cut
+
+sub _correct_checksum_provided {
+    my $self = shift;
+    return undef
+        unless ( $self->checksum_provided eq $self->generate_checksum )
+        or
+        ( $self->checksum_provided eq $self->generate_koremutake_checksum );
+
+}
+
+1;

Added: jifty/branches/schema-plugins/lib/Jifty/Logger.pm
==============================================================================
--- (empty file)
+++ jifty/branches/schema-plugins/lib/Jifty/Logger.pm	Mon Jan 29 21:05:02 2007
@@ -0,0 +1,174 @@
+use warnings;
+use strict;
+
+package Jifty::Logger;
+
+=head1 NAME
+
+Jifty::Logger -- A master class for Jifty's logging framwork
+
+=head1 DESCRIPTION
+
+Jifty uses the Log4perl module to log error messages. In Jifty
+programs there's two ways you can get something logged:
+
+Firstly, Jifty::Logger captures all standard warnings that Perl
+emmits.  So in addtion to everying output from perl via the 
+warnings pragmas, you can also log messages like so:
+
+    warn("The WHAM is overheating!");
+
+This doesn't give you much control however.  The second way
+allows you to specify the level that you want logging to
+occur at:
+
+    Jifty->log->debug("Checking the WHAM");
+    Jifty->log->info("Potential WHAM problem detected");
+    Jifty->log->warn("The WHAM is overheating");
+    Jifty->log->error("PANIC!");
+    Jifty->log->fatal("Someone call Eddie Murphy!");
+
+=head2 Configuring Log4perl
+
+Unless you specify otherwise in the configuration file, Jifty will
+supply a default Log4perl configuration.
+
+The default log configuration that logs all messages to the screen
+(i.e. to STDERR, be that directly to the terminal or to fastcgi's
+log file.)  It will log all messages of equal or higher priority
+to he LogLevel configuration option.
+
+    --- 
+    framework: 
+      LogLevel: DEBUG
+
+You can tell Jifty to use an entirely different Logging
+configuration by specifying the filename of a standard Log4perl
+config file in the LogConfig config option (see L<Log::Log4perl> for
+the format of this config file.)
+
+    --- 
+    framework: 
+      LogConfig: etc/log4perl.conf
+
+Note that specifying your own config file prevents the LogLevel
+config option from having any effect.
+
+You can tell Log4perl to check that file perodically for changes.
+This costs you a little in application performance, but allows
+you to change the logging level of a running application.  You
+need to set LogReload to the frequency, in seconds, that the
+file should be checked.
+
+    --- 
+    framework: 
+      LogConfig: etc/log4perl.conf
+      LogReload: 10
+
+(This is implemented with Log4perl's init_and_watch functionality)
+
+=cut
+
+use Log::Log4perl;
+use Carp;
+
+use base qw/Jifty::Object/;
+
+=head1 METHODS
+
+=head2 new COMPONENT
+
+This class method instantiates a new C<Jifty::Logger> object. This
+object deals with logging for the system.
+
+Takes an optional name for this Jifty's logging "component" - See
+L<Log::Log4perl> for some detail about what that is.  It sets up a "warn"
+handler which logs warnings to the specified component.
+
+=cut
+
+sub new {
+    my $class     = shift;
+    my $component = shift;
+
+    my $self = {};
+    bless $self, $class;
+
+    $component = '' unless defined $component;
+
+    # configure Log::Log4perl unless we've done it already
+    if (not Log::Log4perl->initialized) {
+       $class->_initialize_log4perl;
+    }
+    
+    # create a log4perl object that answers to this component name
+    my $logger = Log::Log4perl->get_logger($component);
+    
+    # whenever Perl wants to warn something out capture it with a signal
+    # handler and pass it to log4perl
+    my $previous_warning_handler = $SIG{__WARN__};
+    $SIG{__WARN__} = sub {
+
+        # This caller_depth line tells Log4perl to report
+        # the error as coming from on step further up the
+        # caller chain (ie, where the warning originated)
+        # instead of from the $logger->warn line.
+        local $Log::Log4perl::caller_depth = $Log::Log4perl::caller_depth + 1;
+
+        # If the logger has been taken apart by global destruction,
+        # don't try to use it to log warnings
+        if (Log::Log4perl->initialized) {
+            # @_ often has read-only scalars, so we need to break
+            # the aliasing so we can remove trailing newlines
+            my @lines = map {"$_"} @_;
+            $logger->warn(map {chomp; $_} @lines);
+            carp (map {chomp; $_} @lines);
+        }
+        elsif ($previous_warning_handler) {
+            # Fallback to the old handler
+            goto &$previous_warning_handler;
+        }
+        else {
+            # Now handler - just carp about it for now
+            local $SIG{__WARN__};
+            carp(@_);
+        }
+    };
+
+    return $self;
+}
+
+sub _initialize_log4perl {
+    my $class = shift;
+  
+    my $log_config
+        = Jifty::Util->absolute_path( Jifty->config->framework('LogConfig') );
+
+    if ( defined Jifty->config->framework('LogReload') ) {
+        Log::Log4perl->init_and_watch( $log_config,
+            Jifty->config->framework('LogReload') );
+    } elsif ( -f $log_config and -r $log_config ) {
+        Log::Log4perl->init($log_config);
+    } else {
+        my $log_level = uc Jifty->config->framework('LogLevel');
+        my %default = (
+            'log4perl.rootLogger'        => "$log_level,Screen",
+            '#log4perl.logger.SchemaTool' => "$log_level,Screen",
+            'log4perl.appender.Screen'   => 'Log::Log4perl::Appender::Screen',
+            'log4perl.appender.Screen.stderr' => 1,
+            'log4perl.appender.Screen.layout' =>
+                'Log::Log4perl::Layout::SimpleLayout'
+        );
+        Log::Log4perl->init( \%default );
+  }
+}
+
+=head1 AUTHOR
+
+Various folks at Best Practical Solutions, LLC.
+
+Mark Fowler <mark at twoshortplanks.com> fiddled a bit.
+
+=cut
+
+1;

Added: jifty/branches/schema-plugins/lib/Jifty/Manual/AccessControl.pod
==============================================================================
--- (empty file)
+++ jifty/branches/schema-plugins/lib/Jifty/Manual/AccessControl.pod	Mon Jan 29 21:05:02 2007
@@ -0,0 +1,149 @@
+=head1 NAME
+
+Jifty::Manual::AccessControl - Using Jifty's default ACL system
+
+=head1 DESCRIPTION
+
+
+Out of the box Jifty-based applications have an ACL system.  The system 
+automatically validates ACLs on L<Jifty::Record> objects by calling the method
+C<current_user_can> before any create, read, update, or delete operation.
+In all cases, the arguments passed to the CRUD operation are passed as 
+extra arguments to C<current_user_can>.
+
+On C<create()>, we reject the operation if C<current_user_can('create')>
+returns FALSE.
+
+On C<_value()> or C<I<somefieldname>>, we reject the operation
+if C<current_user_can('read')> returns false.
+
+On C<_set()> or C<I<set_somefieldname>>, we reject the operation
+if C<current_user_can('write')> returns false.
+
+
+On C<delete()>, we reject the operation  if C<current_user_can('delete')>
+returns false.
+
+Out of the box, C<current_user_can> returns 1. When you want to actually 
+check ACLs, you'll need to override C<current_user_can()> in your
+C<Jifty::Record> subclass.
+
+It's likely that at some point, you'll decide you want to ask other
+questions on certain types of operations.  Say, you only want to let
+administrators update the C<paid_account> field. In that case, you'd override
+C<check_update_rights()> to look for the C<admin> right rather than the 
+C<update> right, if the C<FIELD> is C<paid_account>.
+
+=head1 ENABLING ACCESS CONTROL USING THE LOGIN PLUGIN
+
+To painlessly enable the AccessControl subsystem, the
+C<Login> plugin may get enabled. This is done in the
+F<etc/config.yml> configuration file.
+
+    Plugins:
+      - Login: {}
+
+Then, create an C<App::Model::User> class that derives from
+C<Jifty::Plugin::Login::Model::User>, for example:
+
+    use strict;
+    use warnings;
+
+    package App::Model::User;
+    use base 'Jifty::Plugin::Login::Model::User';
+
+    # Your model-specific methods go here.
+
+    1;
+
+Next, create the table in your database using the F<jifty> executable
+like C<./bin/jifty schema --setup>.
+
+=head2 Expanding the Model
+
+The model that manages C<User> Records is not limited to the plugin's
+definition. It can be expanded by providing an additional schema
+definition. Every column here will be added to the plugin's
+columns. Simply add a schema definition block like this:
+
+    use Jifty::DBI::Schema;
+    use App::Record schema {
+        column 'extra_column_name';
+
+        # more columns if necessary
+    };
+
+The full syntax for defining a schema can be found in
+L<Jifty::Manual::Models> or in L<Jifty::DBI::Schema>.
+
+Defining a method C<_init> in your C<App::CurrentUser> class gives you
+a chance to add more data to the C<CurrentUser> object. This method
+will automatically get called after the Plugin's C<_init> is done.
+
+=head2 Templates defined by the C<Login> plugin
+
+To avoid the need for repetitive work, the C<Login> plugin already
+defines a couple of usable templates:
+
+=over 4
+
+=item F</login>
+
+provides a login screen with a signup option. After
+successful login, the current continuation is called. If no
+continuation exists, the template sitting at the base URL (F</>) is called.
+
+=item F</logout>
+
+logs out the current user.
+
+=item F</signup>
+
+allows a user to sign up himself/herself. By default
+a confirmation mail is sent out that has to get followed by
+the user.
+
+=item F</chgpasswd>
+
+allows a user to change his/her password.
+
+=item F</passwordreminder>
+
+after entering his/her mail address, the user will receive a mail that
+contains a link to F</let/reset_lost_password>.
+
+=item F</let/confirm_email>
+
+is called in the mail and results in accepting the user.
+
+=item F</let/reset_lost_password>
+
+enabled by the passwordreminder template, this template allows a user
+to reenter a password for future use.
+
+=back
+
+=head2 Doing checks at other places in your code
+
+If you need to check more than Model-based record operations you will
+have to do some coding on your own. C<< Jifty->web->current_user >> provides a
+C<App::CurrentUser> object that can get queried about the current user.
+This object provides some convenience methods:
+
+=over 4
+
+=item C<username>
+
+returns the name of the current user or C<undef> if not logged in.
+
+=item C<id>
+
+returns the id of the current user or C<undef> if not logged in.
+
+=back
+
+=head1 SEE ALSO
+
+L<Jifty::CurrentUser>, L<Jifty::Record>, L<Jifty::RightsFrom>
+
+=cut

Added: jifty/branches/schema-plugins/lib/Jifty/Manual/Actions.pod
==============================================================================
--- (empty file)
+++ jifty/branches/schema-plugins/lib/Jifty/Manual/Actions.pod	Mon Jan 29 21:05:02 2007
@@ -0,0 +1,386 @@
+=head1 NAME
+
+Jifty::Manual::Actions - Doing Stuff With Jifty
+
+=head1 DESCRIPTION
+
+C<Jifty::Action> abstracts around the idea of declaring named
+(L<"parameters"|Jifty::Manual::Glossary/parameter>) at compile time.
+At runtime, the action collects user input as
+(L<"arguments"|Jifty::Manual::Glossary/argument>), does something with them,
+and returns some result to the user.  If this sounds incredibly
+general, that's because it is -- actions do nearly B<everything> in Jifty.
+
+C<Jifty::Action> will also generate HTML for you from its parameters --
+no more manually writing C<< <input> >> tags and extracting GET and
+POST arguments by hand and dispatching them where they belong --
+C<Jifty::Action> does it all for you.
+
+=head1 WRITING ACTIONS
+
+Jifty provides some actions for you out of the box -- see
+L<Jifty::Manual::ObjectModel> and L<Jifty::Action::Record> for
+autogenerated actions, as well as L<Jifty::Action::Redirect>, but any
+non-trivial application will want to define actions of its own. This
+is how you do it.
+
+Every action is a subclass of Jifty::Action, as well as typically
+I<AppName>::Action. Actions usually live in the I<AppName>::Action::
+namespace; while that's just a convention, it will make your life easier
+if you follow it.
+
+This, the simplest possible action, is:
+
+    use warnings;
+    use strict;
+
+    package MyApp::Action::DoNothing;
+    use base qw/MyApp::Action Jifty::Action/;
+
+    1;
+
+(Instead of copying-and-pasting that, or typing it in, though, you
+could just run:
+
+    jifty action --name DoNothing
+
+in your application's directory, and Jifty would create a skeleton for
+you. )
+
+However, if you want to actually do something with your actions, you
+need to define two things: their L<parameters|/parameters>, and a
+L</take_action> method.
+
+=head2 parameters
+
+Every C<Jifty::Action> subclass should define a C<schema>, which contains
+some C<param> declarations that describes what arguments it takes.
+Supposing we were writing an action to post a blog article, we might start
+out with parameters like thus:
+
+    use Jifty::Param::Schema;
+    use Jifty::Action schema {
+
+    param 'title';
+    param 'category';
+    param 'body';
+
+    };
+
+However, we've only scratched the surface of the power the
+C<param> API offers.  Parameters can have types, labels,
+validators, canonicalizers, and even more. To start with, let's add
+some types and labels:
+
+    use Jifty::Param::Schema;
+    use Jifty::Action schema {
+
+    param title =>
+        label is 'Title',
+        max_length is 50,
+        is mandatory;
+
+    param category => 
+        label is 'Category',
+        max_length is 30;
+
+    param body =>
+        label is 'Entry',
+        render as 'Textarea';
+
+    };
+
+Now, we can ask the action to render form fields, and it will know how
+to display them. But, we can do even better. Let's improve the look of
+that C<category> field, by making it a combobox (a combination
+dropdown/text field), with some default values available:
+
+    # ...
+    param category => 
+        label is 'Category',
+        render as 'Combobox',
+        available are qw( Personal Work Block );
+    # ...
+
+But a static list is lame. What we really want is a C<Category> model,
+and to keep track of all the categories users have entered:
+
+    # ...
+    param categories => 
+        label is 'Category',
+        render as 'Select',
+        available are defer {
+            my $categories = MyBlog::Model::CategoryCollection->new;
+            $categories->unlimit;
+            [{
+                display_from => 'name',
+                value_from   => 'name',
+                collection   => $categories,
+            }];
+        }
+    ...
+
+Now, Jifty will populate the combobox with the result of calling C<name>
+on each element in C<$categories>. Alternatively, if you set
+C<< value_from => 'id' >>, Jifty would automatically return the C<id> of
+the category, for easy database reference. We don't do this with the
+combobox, however, since a combobox displays the selected value in its
+text field.
+
+See L<Jifty::Action> and L<Jifty::Web::Form::Field> for more fields
+you can set in the C<param> declaration, and see L<Jifty::Param::Schema>
+for more about the syntax.
+
+=head2 validation
+
+C<Jifty::Action> can automatically validate arguments for you, as
+appropriate. If an argument has C<valid_values>, then C<Jifty::Action>
+will automatically verify if the given value matches one of
+them. However, you can also write your own validators. Just write a
+C<< sub validate_<parameter> >>, and it will be called as appropriate:
+
+    use Regexp::Common 'profanity_us';
+
+    sub validate_body {
+       my $self = shift;
+       my $body = shift;
+       if ( $body =~ /$RE{profanity}/i) {
+           return $self->validation_error(
+               body => 'Would you speak like that in front of your mother? *cough*'
+           );
+       }
+       return $self->validation_ok('body');
+    }
+
+You can also do validation in the model -- see
+L<Jifty::Action::Record> 
+
+=head2 canonicalization
+
+If, instead of failing, you want to automatically modify
+invalid content to be valid, you want a
+L<canonicalizer|Jifty::Manual::Glossary/canonicalize>, not a
+validator.
+
+    use Regexp::Common 'profanity_us';
+
+    sub canonicalize_body {
+       my $self = shift;
+       my $body = shift;
+       $body =~ s/$RE{profanity}/**expletives**/gi;
+       return $body;
+    }
+
+A L<canonicalizer|Jifty::Manual::Glossary/canonicalize> can also 
+change other parts of the action.  This lets you update the display
+dynamically in an L<AJAX|Jifty::Manual::Glossary/ajax>-enabled browser
+based on what the user has entered.  For example, we can let a user
+use magic syntax to provide tags for their blog post by surrounding the 
+tags with square brackets.  You can also let the user know you're
+doing something magical by using C<canonicalization_note> which 
+will display a message to the user.
+
+    use Jifty::Param::Schema;
+    use Jifty::Action schema {
+        param title =>
+            label is 'Title',
+            hints is "You can provide tags like this [tag1 tag2]",
+            ajax canonicalizes;
+
+        param tags =>
+            label is 'Tags';
+    };
+
+    sub canonicalize_title {
+        my $self = shift;
+        my $value = shift;
+
+        if ($value =~ s/\[(.*?)\]//) {
+            # this clobbers, may want to merge
+            $self->argument_value( tags => $1 );
+            $self->canonicalization_note(
+                title => 'Removed tags from your title'
+            );
+        }
+
+        return $value;
+    }
+
+
+If you set C<ajax validates> or C<ajax canonicalizes>
+for an argument, then Jifty will automatically validate or
+canonicalize it in an L<AJAX|Jifty::Manual::Glossary/ajax>-enabled
+browser when the user stops typing and puts the focus out of
+the corresponding form field.
+
+=head2 take_action
+
+Once an action has arguments, it needs to do something with them. An
+action does so in its C<take_action> sub, which will be called when an
+action is submitted, and only if its arguments
+L<validate|/validation>. 
+
+Inside C<sub take_action>, subclasses can access their arguments via
+C<< $self->argument_value('foo') >>. If you need to check whether you've
+been passed an argument or not (as opposed to being passed a true
+argument or not), use C<< $self->has_argument('foo') >>.
+
+Once an action has done its task, it needs to inform the caller
+whether or not it has succeeded, possibly with some status message. To
+this end, every C<Jifty::Action> has a C<Jifty::Result> associated
+with. C<Jifty::Result> carries both a failure/sucess code, and a
+textual message describing the result of running the action.
+
+Thus, if your action failed for some reason, you would, in
+C<take_action>, write code like:
+
+    $self->result->error('Couldn't write blog post');
+    return;
+
+If, however, the action completed successfully, you might write:
+
+    $self->result->message('Posted to your blog');
+
+Actions will default to successful with an empty message if you don't
+do anything with the result object. Additionally, if you need to return more semantic
+information than a simple message, you can set arbitrary content on
+the result, using $self->result->content, e.g:
+
+    $self->result->content( id => $new_post->id);
+
+This information can be then used elsewhere to, for example,
+automatically redirect you to a view page for that new blog post. The
+view page template may have the following piece of code in it:
+
+    <%args>
+    $id => undef
+    </%args>
+    <%init>
+    my $result = Jifty->web->response->result('post_blog');
+    $id = $result->content('id') if $result and !defined $id;
+    # load the record by $id and other stuff go here...
+   </%init>
+
+where C<'post_blog'> is the moniker for your post page action object.
+In fact, that's exactly how actions "return" values to other components 
+in your application.
+
+Mutiple action "return values" are possible and arbitrary data structures
+can be passed too:
+
+    $self->result->content( keys   => $keys );
+    $self->result->content( result => $collection);
+
+It should also be mentioned that the response object is "per request". That is,
+it usually can't live up to another user request. Therefore, when paging mechanism 
+is applied to your view page, for example, you have to either pass some data 
+to the link constructor or explicitly tell Jifty to preserve states for you.
+
+See L</monikers>, the Jifty Pony site's source, and L<Jifty::Request::Mapper> for some 
+more information.
+
+=head1 USING ACTIONS
+
+At their simplest, you can create and run actions yourself, e.g.:
+
+    Jifty->web->new_action(
+        class     => 'PostBlogEntry',
+        arguments => {
+            title    => 'A boring blog entry',
+            category => 'Jifty',
+            body     => 'This blog entry is lame.'
+        }
+    )->run;
+
+Note that C<< Jifty->web->new_action >>, and all similar methods
+(e.g. L<Jifty::Request::add_action|Jifty::Request/add_action>,
+L<Jifty::Web::Form::add_action|Jifty::Web::Form/new_action>), will
+automatically qualify the C<class> with either C<Jifty::Action::> or
+C<I<AppName>::Action::> as necessary (I've told you putting actions in
+I<AppName::Action::> would make your life easier!)
+
+In practice, you'll rarely provide actions with arguments
+yourself. Instead, you'll create an action with no or partial
+arguments, often in the L<dispatcher|Jifty::Dispatcher>, or a Mason
+component's C<< <%init%> >> block (See L</constructor arguments> for
+details about passing arguments to actions on creation).
+
+    my $create = Jifty->web->new_action(
+        class   => 'PostBlogEntry',
+        moniker => 'post_blog'
+    );
+
+Having created the action, you will, in one of your Mason components,
+output a form where the user can fill in the action's arguments:
+
+    <% Jifty->web->form->start %>
+    <div class="post-metadata">
+      <% $create->form_field('title') %>
+      <% $create->form_field('category') %>
+    </div>
+      <% $create->form_field('body') %>
+    <% Jifty->web->form->submit(label => "Post") %>
+    %# or <% Jifty->web->form->link(label => "Post", submit => $create) %>
+    %# or <% $action->button(label => "Post"); %>
+    <% Jifty->web->form->end %>
+
+C<form_field> will render the field, along with the C<label> as an
+HTML C<< <input> >> tag that Jifty knows how to interpret to feed back
+to your action as an argument when the form is submitted. If you need
+to change the appearance of the field, Jifty outputs classes on the
+fields, as well as providing some semantic C<< <div> >>s you can style
+using CSS. (See L<Jifty::Manual::UsingCSSandJS> for some more details.)
+
+See L<Jifty::Web::Form/submit>, L<Jifty::Web/link> and
+L<Jifty::Action/button> for details on the different ways to generate
+a submit button.
+
+Additionally, instead of C<form_field>, you can use C<hidden> to
+generate a C<hidden> input, which will not be viewable or editable in
+a web browser. (Note that a knowledgeable user I<can> still submit a
+form with a different value for that hidden input; If this concerns
+you, make sure you have appropriate
+L<ACLs|Jifty::Manual::AccessControl> in place. If it still worries
+you, you probably want a L<continuation|Jifty::Continuation> here.)
+
+=head2 monikers
+
+You probably noticed the C<< moniker => 'post_blog' >>. Every action you
+create in Jifty has an associated
+L<moniker|Jifty::Manual::Glossary>. A C<moniker> is simply a unique
+identifier for the action (unique per request, which in practice
+typically means per HTML page). Since actions are constantly being
+serialized (over HTTP, or Javascript AJAX calls, and so on), and
+unpacked, we need a way refer to specific actions other than just
+object identity, e.g. to extract its arguments or results in the
+L<dispatcher|Jifty::Dispatcher> or a template. Monikers give us that. Given a
+moniker, you can pull information about the associated action out of a
+L<request|Jifty::Request> or L<response|Jifty::Response>.
+
+If a moniker is unspecified, it will be autogenerated.
+
+(XXX TODO Note about action registration here)
+
+=head2 Argument Folding
+
+If you write out more than one C<form_field> for a given argument in
+the same form, and more than one is filled in, Jifty will C<fold> the
+arguments into an array before filling them in to the action. This
+provides a way to do, e.g. a C<BulkEdit> action that applies some set
+of changes to many records at once.
+
+(XXX TODO Note about C<constructor> parameters)
+
+=head1 ACTIONS AS WEB SERVICES
+
+Your actions are also automatically published as web services.
+Clients can POST requsets, usually using the YAML or JSON request
+format.  See C<bin/service> for a trivial generic webservice client.
+
+(XXX TODO More about webservices)
+
+=head1 SEE ALSO
+
+L<Jifty::Action>, L<Jifty::Manual::Tutorial>
+
+=cut

Added: jifty/branches/schema-plugins/lib/Jifty/Manual/Continuations.pod
==============================================================================
--- (empty file)
+++ jifty/branches/schema-plugins/lib/Jifty/Manual/Continuations.pod	Mon Jan 29 21:05:02 2007
@@ -0,0 +1,250 @@
+=head1 NAME
+
+Jifty::Manual::Continuations - There And Back Again
+
+=head1 DESCRIPTION
+
+Continuations are a powerful concept in computer science -- in a
+nutshell, they allow you to store away the state of of the interpreter
+at any given point.  More importantly, they allow you to return to
+that state at any later time, by calling the continuation with, and
+evaluation of that interpreter state will resume.  They're a concept
+that first arose in LISP, but has implementations these days in Ruby,
+Scheme, Haskell, Smalltalk, to name a few.
+
+Thus, continuations allow you to preserve context, and return to it
+later.  This is amazingly useful in web programming, which is limited
+to C<HTTP>, which is an inherently stateless protocol.  By passing
+around continuations, we can keep track of the context that got us to
+the current page.
+
+While we can't construct I<full continuations> at the interpreter level
+-- because Perl doesn't support them -- we can implement them at the
+level of HTTP requests.  In technical terms, because they capture the
+control stack up from the beginning of a user's session, they are
+called I<delimited continuations>.
+
+Continuations are more useful than session because sessions store
+information across browser windows; sessions may also break in the
+presence of the back button, as the information displayed on the
+screen, and the information stored in the session may differ.  Since
+continuations are immutable, and a new one is produced every time a
+change is made, the information displayed in the browser cannot get
+out of sync with the information contained in any associated
+continuation.
+
+=head1 USING CONTINUATIONS
+
+=head2 As simple links in templates
+
+The simplest form of continuation use is in a template, using
+L<Jifty::Web/tangent>, as follows:
+
+    <% Jifty->web->tangent( url   => "/someplace",
+                            label => "Go someplace") %>
+
+This will create a link, which, when clicked, will store the current
+request into a continuation, and jump to the url C</someplace>.  In the
+C</someplace> template, you can display information, and possibly have
+the user navigate between multiple pages before returning to the previous page:
+
+    <% Jifty->web->return( label => "Back to whence you came" ) %>
+
+Because this C<return> does not carry a result value, you can think of
+it as a form of C<gosub>.  In comparison, ordinary hyperlinks are akin to
+C<goto> staements.
+
+Sometimes, it may be possible for the user to get to a location
+without having a continuation set.  In that case, clicking on the
+"Back to whence you came" link will appear to do nothing -- which may
+be slightly confusing to the user.  To remedy this, Jifty provides a
+way to specify a default location to return to:
+
+    <% Jifty->web->return( to => "/default", label => "Go back" ) %>
+
+=head2 Using return values
+
+All of the above examples generate links, which means that they don't
+interact at all with actions.  However, continuations can also be
+useful in creating complex multi-page actions.
+
+Continuations are saved -- and the browser is redirected to the new
+URL -- just after all actions have been checked for validation but
+before any of them are run.  This means that the new request has
+access to the full validation state of its parent's actions.
+
+When a continuation is called, it first checks that all actions in the
+request were successful; if any failed, then the continuation is
+B<not> called.  If the request's actions were all successful, it
+merges together the L<Jifty::Result>s of current L<Jifty::Response>
+with those in the L<Jifty::Response> stored in the continuation.  In
+doing so, parameters are mapped using L<Jifty::Request::Mapper>.  This
+makes it possible to return values from continuations into arbitrary
+places.  For example:
+
+    % my $action = Jifty->web->new_action(class => 'AddTwoNumbers');
+    <% Jifty->web->form->start %>
+    <% $action->form_field( 'first_number' ) %>
+    <% $action->form_field( 'second_number',
+           default_value => {
+               request_argument => "number",
+           }
+       ) %>
+    <% Jifty->web->tangent(
+            url    => '/pagetwo',
+            label  => 'Enter a second number',
+            submit => $action
+       ) %>
+    <% Jifty->web->form->end %>
+
+..and in C</pagetwo>:
+
+    <% Jifty->web->form->start %>
+    <input type="text" name="number" />
+    %# We use as_button to tell Jifty that we want a button, not a link
+    <% Jifty->web->return( label => 'Pick', as_button => 1 ) %>
+    <% Jifty->web->form->end %>
+
+..and assuming that C<AddTwoNumbers>'s C<take_action> resembles:
+
+    sub take_action {
+        my $self = shift;
+        my $one = $self->argument_value("first_number");
+        my $two = $self->argument_value("second_number");
+        $self->result->message("Got " . ($one + $two));
+    }
+
+The first page renders the entry box for the first number; the second
+input is hidden because Jifty notices that it is based on a mapped
+value: i.e., its default is set to C<< {request_argument => "number"} >>
+instead of a plain scalar value.
+
+Pressing the button validates the action but does not complete
+running it.  At this point, the C<second_number> argument to the
+C<AddTwoNumbers> action has no real value -- however, it knows that it
+will, at the earliest possible opportunity, fill in its value from the
+C<number> request parameter.
+
+Jifty tangents to C</pagetwo>, where we enter and submit a C<number>
+argument.  Control then returns to the original page, where the request
+mapper maps the C<number> value into the C<second_number> argument of the
+C<AddTwoNumbers> action, which then runs because it has received all
+arguments it requires.
+
+Note that in the example above, the C<number> argument is a plain request 
+argument, not part of another action.  More complex mappings are possible,
+including grabbing the results of or arguments to actions.  This would make
+it possible, for instance, to use an action on the second page to validate the
+number before returning.  This is slightly different from placing a validator
+on the C<AddTwoNumbers> action, as that validator only gets called I<after>
+control has already returned to the first page.
+
+=head2 As dispatcher rules
+
+The L<Jifty::Web/tangent> function is context-aware -- if it is called
+in void context, it immediately saves the continuation and redirects to
+the new url.  This is particularly useful, say, for authentication
+protection in C<before> blocks:
+
+    before '/protected' => sub {
+        # shorthand for: Jifty->web->tangent( url => '/login' )
+        tangent('/login') unless Jifty->web->current_user->id;
+    };
+
+And in the C</login> template:
+
+    % my $action = Jifty->web->new_action(class   => 'Login',
+    %                                     moniker => 'loginbox' );
+    <% Jifty->web->form->start %>
+    <% $action->form_field('username') %>
+    <% $action->form_field('password') %>
+    <% Jifty->web->return( to     => "/protected",
+                           label  => 'Login',
+                           submit =>  $action) %>
+    <% Jifty->web->form->end %>
+
+This establishes a button, which, if the C<Login> action is
+successful, calls the stored continuation, or, lacking one, redirects
+to C</protected>.
+
+As currently impelented, these redirect-from-dispatcher tangents works
+exactly like rendered-as-links tangents, in that when they return,
+I<all> rules in the dispatcher are still executed from the start.
+Therefore the C<unless> guard in the C<before '/protected'> rule above
+is neccessary to prevent recursion.
+
+=head1 GORY DETAILS
+
+Jifty's continuations are implemented in L<Jifty::Continuation>, which
+is very little more than a place to store a L<Jifty::Request> and its
+associated L<Jifty::Response>.
+
+The following diagram diagrams the stages of continuation handling,
+and their interaction with the dispatcher.  For clarity, the page
+region handling code is included, but page regions do not currently
+interact with continuation processing.
+
+                                /--------------\
+          +---------------------v-+            |
+          |........Request........|            |
+          +-|-------------------|-+            |
+            |                   |  RETURN  +---|---------------------+
+    /----\  |                   \----------> Replace request with    |
+    |  +-|--|-+ +==============+           | request in continuation |
+    |  |.v..v.---> SETUP rules |           +-------------------------+
+    |  |......| +==============+
+    |  |..D...|
+    |  |..I...| +~~~~~~~~~~~~~~~~~~~+      +-------------------------+
+    |  |..S...---> Validate actions |      | Store current request   |
+    |  |..P...| +~~~~~|~~~~~~~~~|~~~+ SAVE | and response, redirect  |
+    |  |..A...|       |         \----------> to new scope and URL    |
+    |  |..T...|       |                    +-------------------------+
+    |  |..C...| +~~~~~v~~~~~~~~~~~~~+
+    |  |..E...| |  Run actions      |      +-------------------------+
+    |  |..R...| +~~~~~~~~~~~~~~~|~~~+ CALL | Merge results into the  |
+    |  |......|                 \----------> continuation's results; |
+    |  |......|                            | redirect to return URL  |
+    |  |......| +==============+           +-------------------------+
+    |  |......---> RUN rules   |
+    |  |......| +=====|========+
+    |  |......|       |
+    |  |......|    +--v---------------+
+    |  |......|    | Show templates   |
+    |  |......|    +-------|----------+
+    |  |......|            |
+    |  |......|    +-------v----------+
+    |  |......|    | Show page region ---------------------\
+    |  |......|    +------------------+                    |
+    |  |......|                                            |
+    |  |......| +==============+                           |
+    |  |......---> AFTER rules |                           |
+    |  +------+ +==============+                           |
+    |                                                      |
+    \------------------------------------------------------/
+
+As shown in the diagram above, there are three different operations
+that continuations use.  The first is C<SAVE>, which is triggered by
+the query parameter L<J:CREATE>.  Continuations are saved after
+validating actions; the continuation itself is attached to the user's
+session object.
+
+The current saved continuation is automatically preserved across
+requests.  When the time comes to call the continuation, the C<CALL>
+operation is performed; this is usually triggered by the presence of
+the L<J:CALL> query parameter.  This causes the stored request to be
+query-mapped using L<Jifty::Request::Mapper>, but using the B<current>
+request and response (I<not> the continuation!) as the sources for mapping
+values.  Then, the result objects are merged, with results from the
+stored response taking precedence.  This new mapped request and new
+merged response are formed into a new continuation.
+
+In order to ensure that the browser's URL matches the URL of the
+request in the continuation, Jifty then does a redirect to the URL of
+the request stored in the continuation, starting the last continuation
+operation, the C<RETURN>.  When Jifty detects the C<RETURN> operation,
+most often by the presence of C<J:RETURN>, it loads the continuation
+and reads the stored request and response into the current request and
+response.
+
+=cut
+

Added: jifty/branches/schema-plugins/lib/Jifty/Manual/Cookbook.pod
==============================================================================
--- (empty file)
+++ jifty/branches/schema-plugins/lib/Jifty/Manual/Cookbook.pod	Mon Jan 29 21:05:02 2007
@@ -0,0 +1,323 @@
+=head1 NAME
+
+Jifty::Manual::Cookbook
+
+=head1 DESCRIPTION
+
+This document aims to provide solutions to common questions of "How do
+I do I<x> with Jifty?" While the solutions here certainly aren't the
+only way to do things, they're generally the solutions the developers
+of Jifty use, and ones that work pretty well.
+
+=head1 HOW DO I ...
+
+=head2 Create an LDAP autocomplete field
+
+You need an action in your application. Then run
+
+  jifty action --name LdapSearch
+
+in C<lib/myApp/Action/LdapSearch.pm> add the C<search> field
+
+  use Jifty::Action schema {
+    param search =>
+        autocompleter is \&ldap_search;
+  }
+
+we need L<Net::LDAP> and an accessor to our LDAP value.
+
+  use Net::LDAP;
+
+  __PACKAGE__->mk_accessors(qw(LDAP));
+
+and we can write our C<ldap_search> fonction. 
+Search need at least 3 characters and return an array of C<DisplayName (login)>
+
+  sub ldap_search {
+    my $self = shift;
+    my $search = shift;
+    my @res;
+    if (length $search > 2) {
+         if (! $self->LDAP() ) {
+            $self->LDAP( Net::LDAP->new('ldap.myorg.org');
+            $self->LDAP()->bind( );
+        }
+
+        $self->LDAP()->search(
+          base    => 'ou=people,dc=myorg,dc=org',
+          filter => '(cn='.$filter.')',
+          attrs   =>  ['uid','cn','givenname','displayname'],
+          sizelimit => 10
+          );
+
+        foreach my $entr ( $result->sorted('cn') ) {
+            push @res, $entr->get_value('displayname').' ('.$entr->get_value('uid').')';
+        }
+    }
+    return @res;
+  }
+
+=head2 Add Atom/RSS Feeds ?
+
+You could generate atom/rss feeds for virtually any model in your application.
+For instance, suppose there's a "Post" model (like a blog entry), you could use
+L<XML::Feed> to do this:
+
+    # In '/feed' template
+    <%args>
+    $type
+    </%args>
+    <%init>
+    use XML::Feed;
+    my $posts = MyApp::Model::PostCollection->new();
+    $posts->unlimit();
+
+    my $feed = XML::Feed->new( $type );
+    $feed->title( Jifty->config->framework('ApplicationName') . " Feed" );
+    $feed->link( Jifty->web->url );
+    $feed->description( $feed->title );
+
+    while( my $post = $posts->next ) {
+        my $feed_entry = XML::Feed::Entry->new($type);
+        $feed_entry->title($post->title);
+        $feed_entry->author($post->author->username);
+        $feed_entry->link( Jifty->web->url . "/posts/" . $post->id );
+        $feed_entry->issued( $post->created_on );
+        $feed_entry->summary( $post->body );
+        $feed->add_entry( $feed_entry );
+    }
+    </%init>
+    <% $feed->as_xml |n %>
+
+And add this in F<MyApp/Dispatcher.pm> to make URI look prettier:
+
+    on qr{^/feed/(atom|rss|rss2)}, run {
+        set type => $1;
+        show('/feed');
+    };
+
+And of course, you need to put these in your HTML header template
+(conventionally that's C</_elements/header>):
+
+    <link rel="alternate" type="application/atom+xml" title="Atom" href="/feed/atom" />
+    <link rel="alternate" type="application/rss+xml" title="RSS" href="/feed/rss" />
+
+=head2 Use date or time objects with the database?
+
+On your columns, specify either
+
+    filters are 'Jifty::DBI::Filter::DateTime'
+
+for a timestamp (date and time), or
+
+    filters are 'Jifty::DBI::Filter::Date'
+
+for just a date. Jifty will then automatically translate to and from
+DateTime objects for you when you access the column on your
+model. Additionally, if you add:
+
+    filters are qw(Jifty::Filter::DateTime Jifty::DBI::Filter::Date)
+
+Jifty will inspect the model's
+L<current_user|Jifty::Manual::AccessControl> for a C<time_zone>
+method, and, if it exists, set the retrieved DateTime object's time
+zone appropriately. All dates are stored in UTC in the database, to
+ensure consistency.
+
+=head2 How do I emulate 'created_on' field like Rails ?
+
+In Rails, if you have a field named 'created_on', it's automatically
+set to the creation time of the record. How can I emulate this
+behaviour in Jifty ?
+
+The trick here is to use L<Scalar::Defer>. And declare your column
+like this:
+
+    column created_on =>
+        type is 'timestamp',
+        label is 'Created On',
+        default is defer { DateTime->now },
+        filters are 'Jifty::DBI::Filter::DateTime';
+
+This approach is not really accurate, if you render this field in a
+form, then the defer value is evaluated by the time of rendering,
+which might be way eariler then the creation of record. However, it is
+the easiest one.
+
+If you're using the newly recommeded C<JIfty::DBI::Record schema {}>
+to declare schemas, you might find this trick not working at the moment.
+Please override model's C<before_create> method instead:
+
+    sub before_create {
+        my ($self, $attr) = @_;
+        $attr->{'created_on'} = DateTime->now;
+    };
+
+=head2 Limit access to pages to logged-in users
+
+The best place to do this is probably in your application's
+L<Dispatcher|Jifty::Dispatcher>. If, for example, you wanted to limit
+access to C</secret> to logged-in users, you could write:
+
+    before qr'^/secret' => run {
+        unless(Jifty->web->current_user->id) {
+            Jifty->web->tangent('/login');
+        }
+    };
+
+Then, in your login form component, you would write something like:
+
+    <% Jifty->web->return(to => '/', submit => $login_action) $>
+
+The combination of the C<tangent> and C<return> will cause the user to
+be returned to wherever they came from. See L<Jifty::Continuation> for
+more information.
+
+If you want model-level access control, Jifty provides a ready-built
+ACL system for its models; See L<Jifty::Manual::AccessControl> for
+details.
+
+Finally, you can also allow or deny specific actions in the
+dispatcher, to limit who is able to perform what actions -- see
+L<Jifty::API>.
+
+=head2 Run my Jifty app as fascgi in Apache/Lighttpd ?
+
+Jifty provides a really simple way to run the application as a fastcgi
+server. The complete instructions and examples are in C<'jifty help
+fastcgi'> for both Apache servers and Lighttpd servers. (Please C<cd> to
+your app dir before running this command.)
+
+You'll have to install C<CGI::Fast> and C<FCGI> module for this.
+
+=head2 Take actions based on data in URLs
+
+You can add actions to the request based on data in URLs, or anything
+else, using
+L<Jifty::Request::add_action|Jifty::Request/add_action>. For example,
+suppose you wanted to make the path C</logout> log the user out, and
+redirect them to the home page. You could write:
+
+    before '/logout' => {
+        Jifty->web->request->add_action( class => 'Logout' );
+        Jifty->web->request->add_action( class     => 'Redirect',
+                                         arguments => { url => '/' });
+    };
+
+=head2 Pass HTML form input directly to components
+
+Sometimes you don't want to take an action based on input from HTML
+forms, but just want to change how the page is displayed, or do
+something similarly transient.
+
+C<Jifty::Action> is great, but it doesn't have to be the answer to
+everything. For cases like this, it's fine to use typical HTML C<<
+<input>s >>. Their values will be accessible as request arguments, so
+you can fetch them with C<get> in the dispatcher, and they will be
+passed as arguments to top-level Mason components that list them in
+C<< <%args> >>. And don't worry about namespace conflicts with Jifty's
+auto-generated argument fields -- Jifty prefixes all its C<name>s with
+C<J:> so there won't be a problem.
+
+=head2 Perform database migration
+
+Edit etc/config.yaml and change Database->Version to a proper value
+(say, 0.0.2). Then run
+
+    jifty schema --setup
+
+Jifty would inspect the current database and perform proper actions.
+You could give a C<--print> option to see the actual SQL statements:
+
+    jifty schema --setup --print
+
+
+=head2 Use different table names than the ones Jifty automatically creates
+
+In YourApp::Record, define a C<_guess_table_name> sub that doesn't
+pluralise or pluralises differently.
+
+
+=head2 How do I perform ajax canonicalization on a given field ?
+
+Asking user to input something in a form is really common in a web
+app. For some certain form fields you want them to have a certain
+normalized/canonicalized form in the database, and you could do an ajax
+canonicalization in Jifty very easily. Let's say your User model needs a
+canonicalized C<username> field to make sure those names are in
+lowercase.  All you have to do is to define a method named
+C<canonicalize_username> in your Model class, like this:
+
+    package MyApp::Model::User;
+    use base qw(MyApp::Record);
+
+    sub canonicalize_username {
+        my $class = shift;
+        my $value = shift;
+        return lc($value);
+    }
+
+If the form is generated by a C<Jifty::Action::Record>-based action
+(all those autogenerated CRUD actions), then this is all you need to
+do. And that is probably 90% of the case.  C<Jifty::Action::Record>
+would check if there is a method named like C<canonicalize_fieldname>
+when it is rendering form fields. If found, related javascript code is
+generated. You do not have to modify any code in your view. Jifty does
+it for you.
+
+The ajax canonicalization happens when the input focus leaves that
+field. You would see the effect a bit later than the value in the
+field is changed.
+
+Of course, you can apply the same trick to your own Action classes.
+
+=head2 Get the "Edit" links to work in the "Page info" tool
+
+If you click on "Page info", follow an "Edit" link for a fragment,
+and you get an error message saying something like
+
+	You got to a page that we don't think exists...
+
+then you need to ensure that the C<Jifty::Plugin::EditInPlace> has
+been installed correctly. It should be in the F<Jifty/Plugin> directory
+installed with the rest of the Jifty modules.
+
+	perl -MJifty::Util -e 'print Jifty::Util->jifty_root'
+
+will tell you where to look. If it's not there you will need to install
+it manually. If you still have your build files from installing Jifty
+you can find the module in the F<plugins> directory.
+
+Once you have the modules in place, or if they were already present
+you simply need to enable the plugin in your project config file. Edit 
+F<etc/config.yml> and find the "Plugins:" section. It will probably look
+like this
+
+	  Plugins: []
+
+Change it to 
+
+	  Plugins: 
+	    - EditInPlace: {}
+
+Take care the indentation is significant. Use spaces, not tabs.
+Once you have done that you can restart your Jifty application and the
+edit links should then function correctly.
+
+=head2 Use iepngfix.htc to add PNG support in IE5.5+
+
+Jifty has included iepngfix.htc by Angus Turnbull. The HTC file will
+automatically add PNG support to IMG elements and also supports any
+element with a "background-image" CSS property.
+
+If you want to use this fix, please include this one line in your CSS
+file, whit tag names to which you want the script applied:
+
+    img, div { behavior: url(/static/js/iepngfix.htc) }
+
+Alternatively, you can specify that this will apply to all tags like so:
+
+    * { behavior: url(/static/js/iepngfix.htc) }
+
+Check details from Angus himself. ( http://www.twinhelix.com/ )
+

Added: jifty/branches/schema-plugins/lib/Jifty/Manual/FAQ.pod
==============================================================================
--- (empty file)
+++ jifty/branches/schema-plugins/lib/Jifty/Manual/FAQ.pod	Mon Jan 29 21:05:02 2007
@@ -0,0 +1,26 @@
+=head1 NAME
+
+Jifty::Manual::FAQ - Frequently Answered Questions
+
+=head1 General
+
+=head2  I need to make a web based program, is jifty mature enough?
+
+We built hiveminder.com with it.
+
+=head2 What databases does Jifty support?
+
+Jifty uses Jifty::DBI as its ORM, which uses DBI to connect to the
+underlying database.  SQLite is the default, but Postgres, MySQL, and
+maybe others work great.
+
+=head2 Does Jifty run on Windows?
+
+Yes.  There have been some hiccups in the dependencies, but those are
+being resolved.
+
+=head2 Where is the subversion repository?
+
+  http://svn.jifty.org/svn/jifty.org/jifty/trunk
+
+=cut

Added: jifty/branches/schema-plugins/lib/Jifty/Manual/Glossary.pod
==============================================================================
--- (empty file)
+++ jifty/branches/schema-plugins/lib/Jifty/Manual/Glossary.pod	Mon Jan 29 21:05:02 2007
@@ -0,0 +1,144 @@
+=head1 NAME
+
+Jifty::Manual::Glossary
+
+=head1 GLOSSARY
+
+We use words.  This is what they mean.
+
+=over 4
+
+=item action
+
+An B<action> is a specifically designed RPC call that can do something to the
+system, with any number of declared L</parameter>s.  At runtime, an action
+can take L</argument>s, which it L</canonicalize>s, L</validate>s, and then
+uses to do something useful.  Each action has a L</result>.  See
+L<Jifty::Action> and L<Jifty::Manual::Actions>.
+
+=item active
+
+For an L</action> to run, it needs to be B<active>.  Most of the time, all
+actions submitted are active, but it is possible to specify only a specific
+action as active; any non-active actions are ignored.  See L<Jifty::Request>.
+
+=item AJAX
+
+An acronym standing for B<Asynchronous Javascript And XML>.  Though technically
+incorrect, it is the buzzword that describes doing asynchronous requests to the
+server while the user waits.  This can lead to very "dynamic" pages, as the
+browser does not need to refresh the entire page to update a small section of
+the screen.  In Jifty, the sections of the screen are called L</region>s.  See
+L<Jifty::Web::PageRegion>.
+
+=item argument
+
+An B<argument> is a user-supplied input to fill in a L</parameter> in an
+L</action>.  See L<Jifty::Action>.
+
+=item canonicalize
+
+To turn an L</argument> into a more standard form.  For instance, a
+canonicalizer could translate a user-typed date into a date object or a
+SQL-formatted date string.  See L<Jifty::Action>.
+
+=item constructor
+
+A property of a L</parameter>; the action B<must> have an argument value for
+this paramater in order to be constructed.  This is different from
+L</mandatory>, in that the user can leave mandatory fields empty.  For
+instance, the C<id> of a L<Jifty::Action::Record::Update> is a constructor.
+See L<Jifty::Action>.
+
+=item continuation
+
+A concept stolen from Lisp, Scheme, Smalltalk, and Perl 6.  The continuation of
+any particular piece of code is the deferred operations that care about the
+return value at that point.  In the context of Jifty, a continuation is a
+deferred L</request> that may pull L</argument>s and the like from the
+L</result>s of the current request.  Continuations can be arbitrarily nested,
+so they are often useful to keep track of tangents that the user went on.  See
+L<Jifty::Continuation>.
+
+=item form field
+
+A widget which the browser renders.  These are generally useful to ask the user
+for a value for an L</argument> to an L</action>.  See
+L<Jifty::Web::Form::Field>.
+
+=item fragment
+
+A section of HTML (at present, a Mason component) contained in a L</region>.
+Fragments are a kind of standalone Mason component which the browser can request
+individually.  Because of this, they can only take strings and scalars as
+arguments, not references or objects!
+
+=item element
+
+A Mason component used by one or more other pages, which is not a whole page of
+itself. As opposed to L<fragments|/fragment> C<elements> are strictly internal,
+and never visible to the outside world by themselves. Elements typically live
+under a path beginning with or containing '/_elements'. This, and the whole idea
+of an element is strictly convention, but Jifty contains elements for things
+like page headers, menus, and showing keybindings out of the box to make your
+life easier.
+
+=item mandatory
+
+A property of a L</parameter>; the user must enter a value for the action to
+validate.  This is the simplest level of L<validation|/validate>.
+
+=item moniker
+
+Every instance of a L<Jifty::Action> has a B<moniker>.  A moniker is
+an arbitrary-length nonempty string containing no semicolons.
+Monikers serve as identifiers for actions, to associate arguments with
+actions and to access specific actions "by name".  Monikers need not
+be globally unique, but they must be unique within a single request.
+Monikers have no semantic meaning. See L<Jifty::Action/monikers>
+
+=item parameter
+
+A B<parameter> is a named parameter to an L</action>.  Jifty generally renders
+these on the screen as L</form field>s.  See L<Jifty::Param> and
+L<Jifty::Param::Schema>.
+
+=item region
+
+An area of the page which JavaScript can replace.  The content in the region is
+a L</fragment>.  Think of the region as the box and the fragment as the content
+in the box.  See L<Jifty::PageRegion>.
+
+=item request
+
+A single query which lists L</action>s to run, together with a page or list of
+L</fragment>s to return.  This most often comes from the browser as query
+parameters, but may come from other sources as a L<JSON> or L<YAML> POST
+request.  The answer to a request is a L</response>.  See L<Jifty::Request>.
+
+=item response
+
+The answer to a L</request>, it contains a L</result> for every action that
+ran.  See L<Jifty::Response>.
+
+=item result
+
+The answer to a L</action>, it contains information about if the action was a
+success or failure, and further detail about why or how.  It can also contain
+arbitrary "content".  See L<Jifty::Result>.
+
+=item sticky
+
+A property of L</form field>s.  If a field is "sticky," values that the user
+entered appear there again when the page is rendered again, avoiding making the
+user type them again.  Most L</action>s have form fields which are sticky on
+failure, so the user can update the information and try again.
+
+=item validate
+
+To check that the provided value of an L</argument> is a possible value for it
+to have.  See L<Jifty::Web::Form::Field>.
+
+=back
+
+=cut

Added: jifty/branches/schema-plugins/lib/Jifty/Manual/Models.pod
==============================================================================
--- (empty file)
+++ jifty/branches/schema-plugins/lib/Jifty/Manual/Models.pod	Mon Jan 29 21:05:02 2007
@@ -0,0 +1,356 @@
+=head1 NAME
+
+Jifty::Manual::Models - Managing your datastore
+
+=head1 DESCRIPTION
+
+The idea behing a model is to give the user a database-independent way
+of defining how the data looks alike and how different parts of the
+data relate to each other. In database terms, you might think of a
+schema definition.
+
+Besides the pure definition of a model, creation, updating and lookup
+of data is also possible in a comfortable way.
+
+=head2 Creating a model
+
+Every model consists of two classes: I<AppName>::Model::I<ModelName>
+and I<AppName>::Model::I<ModelName>::Schema. Behind the scenes, a
+class named I<AppName>::Model::I<ModelName>Collection is created by
+L<Jifty::ClassLoader>.
+
+A simple model to store just one line of text might look like this:
+
+    use strict;
+    use warnings;
+
+    package MyApp::Model::TextLine;
+    use Jifty::DBI::Schema;
+
+    use MyApp::Record schema {
+        column 'textline';
+    };
+
+    # Your model-specific methods go here.
+
+    1;
+
+To create the database schema for a model inside an application you
+could simply run:
+
+    jifty model --name TextLine
+
+from inside your application's directory and Jifty will create exactly
+this class structure for you (minus the I<column> line, to be
+precise).
+
+=head3 Schema definition language
+
+Creating a model has important side effects:
+
+=over 2
+
+=item * correctly type your data inside the data-store
+
+=item * let Jifty create (and update) your database schema for you
+
+=item * tell Jifty the behaviour in terms of form display
+
+=item * allow to work with multiple records (referred to as Collections) without effort
+
+=back
+
+To get all these things done, Jifty allows to describe the schema
+definition in a simply comprehendable but powerful syntax that looks
+more like written text than a programming language. The schema
+definition is made inside the C<MyApp::Model::XXX::Schema> package and
+every single column to get created starts with the word C<column>
+followed by the column's name.
+
+A simple definition could look like this:
+
+    column name =>
+        type is 'text',
+        label is 'Name',
+        render as 'Text',
+        since '0.0.1';
+
+The following BNF shows the full syntax supported (omitting
+non-terminals that are self-explanatory to perl-developers):
+
+    schema_definition ::= column_definition+
+
+    column_definition ::= 'column' string_columnname '=>'
+                          column_info [ ',' column_info ]+ ';'
+
+    column_info ::= 'type' 'is' string
+       | 'label' 'is' string
+       | 'render_as' string
+       | 'render' 'as' string
+       | 'hints' 'is' string
+       | 'refers_to' class_name 'by' string_columnname
+       | 'default' 'is' string
+       | 'literal' 'is' string
+       | 'validator' 'is' subroutine_reference
+       | 'immutable'
+       | 'unreadable'
+       | 'length' 'is' number
+       | 'mandatory'
+       | 'not_null'
+       | 'distinct'
+       | 'virtual'
+       | 'sort_order' 'is' number
+       | 'input_filters' 'are' string_classname
+       | 'output_filters' 'are' string_classname
+       | 'filters' 'are' string_classname
+       | 'since' string_version_number
+       | 'valid_values' 'are' array_of_valid_values
+       | 'valid' 'are' array_of_valid_values
+       | 'hints' 'are' string
+
+    * 'is', 'by', 'on', 'as' and 'are' are fill-words that may get omitted.
+
+For a full description of all parameter's meaning, look at
+L<Jifty::DBI::Schema>.
+
+=head3 Versioning
+
+Every time you run the jifty utility with C<schema> as an argument,
+Jifty will keep track on what it has done for you. To get that done,
+the version-number being stored in your application's config file
+C<etc/config.yml> under the key named C<framework/Database/Verson> is
+matched agains your schema definition.
+
+To force an update of your schema, simple create a new version number
+in your config file and modify your schema definition by using exactly
+this version number for every modified entry. After running
+
+    jifty schema --setup
+
+your database structure will be in sync to your schema definition.
+See L<Jifty::Manual::Upgrading> for more information on model upgrading.
+
+=head2 Testing a model
+
+After having created a schema, you might use the B<ADMINISTRATION>
+Menu entry in Jifty's web view (i.e. the "pony") to browse through
+your models and add, edit or delete records in your database.
+
+=head2 The classes behind a model
+
+=over 2
+
+=item * MyApp::Model::Xxx
+
+This is the model-class you created to access individual records of your desired
+type. You will directly deal with objects of this class.
+
+=item * MyApp::Record
+
+All records of C<MyApp::Model::Xxx> will have this class as their base
+class. Usually, this class will be automatically created by
+L<Jifty::ClassLoader> for you. But, if you want to automatically
+enable all your records to do something, you will have a chance to do
+so by manually creating this class.
+
+=item * L<Jifty::Record>
+
+This is the super-class of C<MyApp::Record>. Inside this class, loading
+of records as well as the checking of user capabilities is done before
+going one level down to the database layer.
+
+=item * L<Jifty::DBI::Record>
+
+This is the lowest-level class that the database stack provides. It
+directly deals with the underlying database.
+
+=item * App::Model::XxxCollection
+
+As the name applies, a collection is a set of typically more than one
+record. Every collection of this class conists of multiple
+C<App::Model::Xxx> objects that can get retrieved from your data-store
+without explicit SQL statements, ordered by any criteria you give,
+paged in the fashion you like,
+and iterated sequentially or accessed at random order.
+
+=item * App::Collection
+
+Every collection of your schemata will have this class as its
+base. Usually this class is autocreated by L<Jifty::ClassLoader>. If
+you intend to create new features for all of your collection this will
+be your chance to do.
+
+=item * L<Jifty::Collection>
+
+This is the base class of an C<App::Collection>, managing user
+capabilities on records it will keep track of.
+
+=item * L<Jifty::DBI::Collection>
+
+This is the lowest-level base class that directly manages the access to
+the underlying database.
+
+=back
+
+=head2 Working with a single record
+
+Working with a single record means working with objects of classes like
+C<MyApp::Model::Xxx>. The typical creation and usage of a single
+record is:
+
+    # create an object to allow data access
+    my $object = new MyApp::Model::Xxx;
+
+    # either create a representation in the DB
+    $object->create(column => 'value', ...);
+
+    # or load the data from DB somehow
+    $object->load($id); # by a matching ID
+    $object->load_by_cols(column => 'value', other_column => 'secondvalue');
+
+    # try to load and if failed, create a record
+    $object->load_or_create(column => 'value');
+
+    # get the record's ID in the database
+    # results in 'undef' if record is not valid (which usually means not found)
+    my $id = $object->id;
+
+    # delete the record from the database
+    $object->delete;
+
+To access data stored in different columns of a record you may use
+some of the automagically created methods on the object:
+
+    # read some column named 'colname'
+    my $value = $object->colname;
+
+    # write some value to a column named 'colname'
+    $object->set_colname($value);
+
+    # get all columns in a single hash (not a reference!)
+    my %record = $object->as_hash;
+
+Especially, when writing to a record, you need not worry about how to
+write back the data to the database, the object will manage this step
+on its own.
+
+=head2 Working with multiple records
+
+Working with more than one record of the same object-class brings
+collections into the game. Usually, a collection you deal with is of a
+type that conforms to your model name, C<MyApp::Model::XxxCollection>
+and usually holds records of class C<MyApp::Model::Xxx>. You typically
+use a collection like this:
+
+    # create a collection object
+    my $collection = new MyApp::Model::XxxCollection;
+
+    # get all items of the model into the collection
+    $collection->unlimit;
+
+    # or restrict items to match some condition
+    $collection->limit(column => 'colname', operator => '=', value => 42);
+
+    # bring the items into some sorting order
+    $collection->order_by(column => 'colname');
+
+    # if neccesarry, directly jump to some record from the set
+    $collection->goto_first_item;
+
+    $collection->goto_item(42);
+
+    # iterate through the result set
+    while (my $record = $collection->next) {
+          # do something with $record
+    }
+
+    # directly access the first or last item
+    # be careful: this will set the current position also!
+    my $first = $collection->first;
+    my $last  = $collection->last;
+
+    # get back an array-ref containing all items
+    my $records = $collection->items_array_ref;
+
+=head3 Some options provided by C<limit>
+
+In order to construct more complex restrictions the C<limit> method
+may get called more than once, specifying one single condition with
+each call.
+
+Every use of C<limit> constructs either a I<clause> or a I<subclause>.
+A subclause is built either if the C<subclause> attribute is used or a
+column is used repeatedly.
+
+Every clause is built up by combining its subclauses (if
+any) using the C<entry_aggregator> operator (whose default is I<OR>)
+as a combining operator. Clauses are then I<AND>ed together to yield
+the final restriction that is finally used to retrieve the records in
+question.
+
+The C<operator> (whose default is '=') can be any legal SQL operator
+like C<=>, C<< <= >>, C<< >= >>, C<< != >>, C<LIKE>, C<IS>, C<IS
+NOT> as well as some convenience operators that silently use C<LIKE>
+with properly set wildcards (C<MATCHES>, C<STARTSWITH> or
+C<ENDSWITH>).
+
+    # combining restrictions with "AND"
+    # note that "AND" is implicit here unless a column name is repeated
+    $collection->limit(column => 'col1', value => '...');
+    $collection->limit(column => 'col2', value => '...');
+
+    # combining restrictions with "OR"
+    # note that the 'subclause' has the same value
+    $collection->limit(column => 'col1', value => '...',
+                       entry_aggregator => 'OR', # is already default
+                       subclause => 'some_id');
+    $collection->limit(column => 'col2', value => '...',
+                       entry_aggregator => 'OR', # is already default
+                       subclause => 'some_id');
+
+For debugging purposes, you might want to examine the SQL statement
+generated behind the scene:
+
+    warn $collection->build_select_query;
+
+See L<Jifty::DBI::Collection> about more ways or ordering and limiting
+collections.
+
+=head2 Action - Model relationship
+
+When writing templates you often simply access some record from a
+model and want to operate on this very record by modifying it or you
+might want to add a new record of some type. To do this, our faithful
+L<Jifty::ClassLoader> will create classes named
+C<MyApp::Action::CreateXxx>, C<MyApp::Action::UpdateXxx> or
+C<MyApp::Action::DeleteXxx> for you. This enables you to write a
+template to operate on a single record like this:
+
+    <%init>
+    my $id = some_value_obtained_somehow;
+    my $record = new MyApp::Model::Xxx;
+    $record->load($id);
+
+    my $action = Jifty->web->new_action(class   => 'UpdateXxx',
+                                        moniker => 'mymoniker',
+                                        record  => $record);
+    </%init>
+    ...
+    <% $action->form_field('colname') %>
+    ...
+    <% Jifty->web->link(label  => 'Update',
+                        submit => $action,
+                        ... ) %>
+
+The elegant thing around here is that you could write the class name
+of your action-class simply as C<UpdateXxx> instead of the full
+package name C<MyApp::Action::UpdateXxx> and there is no need to write
+a repeating update procedure for every record class that comes along.
+DRY - don't repeat yourself :-)
+
+=head1 SEE ALSO
+
+L<Jifty::Record>, L<Jifty::DBI::Record>, L<Jifty::Collection>, L<Jifty::DBI::Collection>, L<Jifty::Manual::Actions>, L<Jifty::Manual::Tutorial>
+
+
+=cut

Added: jifty/branches/schema-plugins/lib/Jifty/Manual/ObjectModel.pod
==============================================================================
--- (empty file)
+++ jifty/branches/schema-plugins/lib/Jifty/Manual/ObjectModel.pod	Mon Jan 29 21:05:02 2007
@@ -0,0 +1,198 @@
+=head1 NAME
+
+Jifty::Manual::ObjectModel -- An overview of the Jifty object model
+
+=head1 OVERVIEW
+
+Jifty applications are generally built in a similar way. There's no reason
+you I<need> to use the model we've built, but we find it a reasonably
+ok way to do things.
+
+This document should serve as a roadmap to the Jifty class library, as 
+well as an introduction to the way Jifty applications are put together.
+
+We start with the classes in I<your> application and move on to the bits
+of Jifty itself.
+
+If you create a brand new application, let's call it C<MyWeblog>, and
+create one model class called C<MyWeblog::Post>, you'll end up with the
+following files and directories:
+
+    MyWeblog/
+        etc/
+            config.yml
+        lib/
+            MyWeblog/
+                Model/
+                    Post.pm
+                Action/
+        bin/
+            jifty
+    
+        web/
+            templates/
+            static/
+
+        t/
+            #some test files.
+
+At least that's the scaffolding Jifty creates for you. Behind the
+scenes, Jifty is actually doing a lot more. Rather than create a bunch
+of little "stub" classes and libraries for you, Jifty generates them
+on the fly. It's always possible to I<actually> create these libraries
+when you need to customize the default behavior, but we work really
+hard to make sure you don't need to.
+
+Right now, Jifty is autocreating libraries, static web pages and web
+templates.
+
+We're not 100% satisfied with how Jifty autocreates web templates and
+static pages and are working to redesign that.
+
+The library you I<see> when creating a Jifty app is:
+
+=over
+
+=item MyWeblog::Model::Post
+
+C<MyWeblog::Model::Post> describes the schema and business logic of your
+post class. It uses two namespaces, C<MyWeblog::Model::Post::Schema>
+that has actual column definitions and C<MyWeblog::Model::Post> that
+contains the (optional) business logic, access control and so on.
+
+=back
+
+That's it. But if you look carefully at C<MyWeblog::Model::Post>, you'll see
+the line:
+
+    use base qw/MyWeblog::Record/;
+
+How can that possibly work? There is no C<MyWeblog::Record> class in your
+application. And Jifty, while it tries to be a comprehensive framework,
+draws the line somewhat short of including application-specific base
+classes for every application you might possibly contrive.
+
+The answer lies in L<Jifty::ClassLoader>, a utility module Jifty uses
+to create the boring stuff for you when you need it.
+
+It'd certainly be possible for Jifty to create every class you might need
+as a file on disk when you first create your application (and indeed
+we may decide to do so if enough people yell at us), but when the stub
+classes we'd provide are just little shims that inherit from or call
+to the Jifty core, it doesn't make much sense to create them before you
+need them.  You could build a Jifty application without these shims by
+having your model classes inherit directly from Jifty::Record, but then
+you'll run into trouble the second you want to add application-specific
+code and have to go back and retrofit each and every one of your classes
+to use your new base class. It's a little thing, but one that can save
+you a bunch of pain and suffering later on.
+
+C<MyWeblog::Record> is the first autogenerated class you'll run into but
+probably not the last. A full list of everything Jifty provides for your
+new application follows:
+
+You get one each of the these:
+
+=over
+
+=item MyWeblog::Record
+
+This class is, as discussed above, a thin wrapper around
+L<Jifty::Record>. You might choose to create your own C<MyWeblog::Record>
+if you want to build in custom access control by overriding
+L<Jifty::Record/current_user_can> or want to implement methods that
+every model class should have access to.
+
+=item MyWeblog::Collection
+
+We haven't talked much about collections yet, but as their name implies,
+collections are bundles of L<Jifty::Record> objects that match some set
+of criteria. It's relatively uncommon that you'll want to override this,
+but if you want the rope, it's here.
+
+=item MyWeblog::Notification 
+
+C<MyWeblog::Notification> is an app-specific implementation of the
+L<Jifty::Notification> email driver. You might want to override this
+class if you want to set an application-specific header or footer for
+all outgoing email.
+
+=item MyWeblog::Dispatcher
+
+C<MyWeblog::Dispatcher> is an application-specific "dispatcher" class that
+allows you to write code that runs when a client makes a request to the server
+I<before> Jifty runs I<actions> or renders I<templates>.  See L<Jifty::Dispatcher>
+for more information about the dispatcher.
+
+=item MyWeblog::CurrentUser
+
+Most every web application that grows past a personal hack eventually
+starts to provide personalization, require access control or otherwise
+want to know who's currently in the driver's seat. The "current user"
+for an application is a first-class object in Jifty. To get user-based
+authentication working out of the box, you'll have to override the
+default C<MyWeblog::CurrentUser>. (Out of the box, it treats everyone
+as the same user.) We're working to generalize the authentication system
+we've used in a few Jifty apps so far to the point where it feels "right"
+as a core Jifty component, but we're not quite there just yet.
+
+Most of what you'll need to override in C<MyWeblog::CurrentUser> is
+the C<_init> function, which needs to load up an application-specific
+model class that represents one of your users into its C<user_object>
+accessor.  To make all this work, you'll also need an
+application-specific C<MyWeblog::Action::Login> and likely also a
+passel of user-management code.
+
+(And yes, this is the topic of a future generalization and a future
+tutorial. At that point, a bunch of this documentation will be extracted
+to L<Jifty::CurrentUser>.)
+
+=back
+
+But wait! There's more!  You also get one each of these for your default
+model class:
+
+=over
+
+=item MyWeblog::Model::PostCollection
+
+It's no fun having a weblog that only shows you one post at a time,
+is it?  Jifty provides you with default L<Jifty::Collection> classes
+for every L<Jifty::Record> subclass in your model.  You get all the
+standard C<limit>, C<order_by>, C<columns>, paging support and so-on out
+of the box, but sometimes when you're going to be getting collections
+matching certain criteria often, it makes sense to actually create your
+own subclass and start dropping methods in.
+
+=item MyWeblog::Action::CreatePost, MyWeblog::Action::UpdatePost,
+MyWeblog::Action::DeletePost
+
+One of Jifty's strengths is that it makes it easy to build applications by
+tying application-specific controller functions to your model classes and
+intuiting what parameters they take by having a look inside the models.
+
+For each class in your model, Jifty creates three
+actions, C<Create>,C<Update> and C<Delete>.  They're named,
+perhaps a bit unadventureously, C<MyWeblog::Action::CreatePost>,
+C<MyWeblog::Action::UpdatePost>, C<MyWeblog::Action::DeletePost>
+and inherit directly from L<Jifty::Action::Record::Create>,
+L<Jifty::Action::Record::Update> and L<Jifty::Action::Record::Delete>,
+respectively. Sometimes, it makes sense to override these default actions
+when you want to change the behaviour of one or more of the actions.
+One common use is to add or remove AJAX validation or autocompletion
+for an argument or to change an argument's default value for webforms.
+This, isn't, however the place to start inserting business logic or
+access control. That belongs in your model class, which these wrappers
+will hand things off to. By putting logic in your actions, you make your
+model classes less useful and run into trouble when you want to start
+scripting your model outside a web environment.
+
+=back
+
+There's no reason you need to stick with these default
+"implementations" if they're not meeting your needs. Just create your
+own classes and Jifty will use your real classes instead.
+
+=cut
+
+1;

Added: jifty/branches/schema-plugins/lib/Jifty/Manual/PageRegions.pod
==============================================================================
--- (empty file)
+++ jifty/branches/schema-plugins/lib/Jifty/Manual/PageRegions.pod	Mon Jan 29 21:05:02 2007
@@ -0,0 +1,171 @@
+
+=head1 NAME
+
+Jifty::Manual::PageRegions - Using page regions
+
+=head1 DESCRIPTION
+
+Page regions are a way of doing the new trend of automatic in-page
+replacement with JavaScript -- while at the same time providing the
+same user experience for non-JavaScript enabled browsers.  Sections
+are chunked into nestable "page regions", which can be refreshed
+independently.
+
+=head1 USING PAGE REGIONS
+
+=head2 Constructing Page Regions
+
+From inside any template, a region may get constructed via something like
+this:
+
+    <% Jifty->web->region( name     => 'regionname',
+                           path     => '/path/of/component',
+                           defaults => { argname => 'some value', ... },
+                         ) %>
+
+This call will pass all arguments to the C<new> constructor of
+L<Jifty::Web::PageRegion>. The most often used parameters are:
+
+=over
+
+=item name
+
+The mandatory region's name given here is used to embed the region's
+content into a C<< <div> >> tag which is marked with a fully qualified
+name for that region. The qualified name represents the nesting
+structure of regions inside a page and is automatically built inside.
+The qualified name for a given L<Jifty::Web::PageRegion> object can
+be obtained by calling C<< Jifty->web->qualified_region >>.
+
+=item path (optional)
+
+If a path is given, the component's rendered result under this path is
+embedded inside the region. If no path is given, C</__jifty/empty>
+will be used resulting in an empty region inside.
+
+=item defaults (optional)
+
+Every argument given here (as a hash-ref) will be transported to the
+component that displays the region inside. The values are accessible
+by building a C<< <%args> >> block in the component (Mason template)
+specifying the arguments.
+
+=back
+
+=head2 Using Page Regions
+
+Given a template with regions, any region can influence itself or any
+other region it knows about. Doing this is typically done with
+JavaScript handlers like C<onclick>. The examples below will
+demonstrate some typical scenarios:
+
+    %# replace this region with some other component
+    <% Jifty->web->link( label   => 'click me',
+                         onclick => {
+                             replace_with => '/new/path/component',
+                             args         => { argname => 'some value' },
+                                    },
+                       ) %>
+
+    %# insert a new region in front of a given region
+    %# use an HTML-entity as the link-text and a CSS class
+    <% Jifty->web->link( label        => '%#9997;',
+                         escape_label => 0,
+                         class        => 'blue_button',
+                         onclick => {
+                             region  => 'regionname',
+                             prepend => '/new/path/component',
+                             args    => { argname => 'some value' },
+                                    },
+                       ) %>
+
+    %# insert a new region after a given CSS selector inside $region
+    <% Jifty->web->link( label   => 'add something',
+                         onclick => {
+                             element => $region->parent->get_element('div.list'),
+                             append  => '/new/path/component',
+                             args    => { argname => 'some value' },
+                                    },
+                       ) %>
+
+    %# a button to replace the current region with empty content
+    <% Jifty->web->link( label   => 'clear',
+                         onclick => {
+                             refresh_self => 1,
+                             toggle       => 1,
+                                    },
+                         as_button => 1,
+                       ) %>
+
+    %# a button to delete some region with JavaScript confirmation alert
+    <% Jifty->web->link( label   => 'delete',
+                         onclick => {
+                             delete  => 'regionname',
+                             confirm => 'really delete this?',
+                                    },
+                         as_button => 1,
+                       ) %>
+
+    %# refresh the parent region which holds the current one
+    <% $search->button(
+        label   => 'Search!',
+        onclick => {
+            submit  => $search_action,
+            refresh => Jifty->web->current_region->parent,
+            args    => { page => 1 }
+                   }
+      ) %>
+
+=head1 GORY DETAILS
+
+There is a bit of complication involved in making sure that the
+server-side Perl implementation of page regions, and, more importantly,
+how they preserve state, interacts with the client-side JavaScript
+implementation.  What follows is an attempt to describe the process.
+
+Regions, when they are created, have a default path and a default set
+of arguments.  These are "defaults" because they can be overridden by
+the browser -- this is what enables the browser to say "...and that
+region has this other path, in reality."  The same is true for
+arguments; for example, a paging widget could have a default C<page>
+argument of 1, but could be actually being rendered with a C<page> of
+2.
+
+These overrides are kept track of using state variables.  When a
+region is entered, it peers at the current state variables, and
+overrides the default path and arguments before rendering the region.
+
+When a L<Jifty::Web::Form::Clickable> object with an C<onclick> is
+L<generated|Jifty::Web::Form::Clickable/generate>, it examines the
+C<onclick> and determines how to emulate it without JavaScript.  It
+determines which actions need to be run, as well as how to manipulate
+the future state variables to change the display of the appropriate
+regions.  It encodes all of this in the button or link; since the
+JavaScript usually returns false, the fallback mode is never seen by
+the browser.
+
+When a region is output, it is output with a tiny "region wrapper",
+which serves two purposes: to inform the JavaScript of the existance
+of the page region and its default path and variables, and to create a
+unique C<< <div> >> for the fragment to reside in.  The browser reads
+the JavaScript and creates, on the client-side, a model of the nested
+PageRegions.  This allows the JavaScript to model the state variable
+changes correctly.
+
+When the JavaScript C<Update> function is called, it is passed a list of
+fragments that needs to be updated, as well as a list of actions that
+need to be run.  As it does so, it builds up an up-to-date list of
+state variables, to more closely imitate the state of a non-javascript
+enabled client.  It constructs a JSON request based on that
+information, and passes it off to the XML web-service endpoint on the
+server.
+
+When the request comes back, it parses the XML.  For each fragment
+that was requested, it finds the correct bit of the response, and
+replaces the content of the DOM with the response.  As it does so, it
+re-updates the client-side view of the fragments with the server's
+information -- this is particularly key for dealing with parameters
+which were mapped by the request mapper.  Finally, it displays
+any messages and errors from actions.
+
+=cut

Added: jifty/branches/schema-plugins/lib/Jifty/Manual/RequestHandling.pod
==============================================================================
--- (empty file)
+++ jifty/branches/schema-plugins/lib/Jifty/Manual/RequestHandling.pod	Mon Jan 29 21:05:02 2007
@@ -0,0 +1,124 @@
+=head1 NAME
+
+Jifty::Manual::RequestHandling - Jifty's request handling process
+
+=head1 DESCRIPTION
+
+This document outlines some of Jifty's inside in order to help you to understand
+what happens during the request processing phase.
+
+=head1 THE HANDLER
+
+As soon as a http request (whatever the method might be, like GET,
+POST, PUT, ...) arrives at Jifty's border, the request is forwarded to
+a handler. By default, C<< Jifty->handler >> points to a L<Jifty::Handler>
+object that is responsible for handling an incoming request. The
+handler receives a L<CGI> object on which it operates.
+
+=head2 The major steps in the request handling process are:
+
+=over
+
+=item refresh eventually modified modules in develop mode
+
+This allows a perl developer to change perl modules being used in a
+Jifty application without the need to restart the server which would
+otherwise become necessary. This is never done on a live environment.
+
+=item build a stash
+
+The stash is a storage area that can be reached by simply accessing
+C<< Jifty->handler->stash->{some_key} >>. The stash will start fresh with
+every request and lives for the entire lifetime of a request. Using
+the stash, transporting data between otherwise unconnected modules
+will become possible.
+
+=item construct a request and response object
+
+Using the L<CGI> object, a L<Jifty::Request> object is constructed and
+its data is populated with the CGI's data. The request can be reached
+later using C<< Jifty->web->request >>. The request holds information
+about all actions involved, all page fragments, contains state
+variables and arguments (usually GET/POST parameters).
+
+Also, an empty L<Jifty::Response> object is constructed that contains
+one or more L<Jifty::Result> objects, each of which holds one
+L<Jifty::Action>'s result. The response object can be retrieved with
+the C<< Jifty->web->response >> method.
+
+=item setup plugins
+
+For every registered L<Jifty::Plugin>, some kind of per-request
+initialization is performed allowing the actions provided by each
+plugin to run.
+
+=item handle static content
+
+If the requested URI points to some existing static content being
+housed in a C<static> directory, this content is handled.
+
+=item setup the session
+
+Based on a cookie that is sent with every http response, the current
+user is assigned a unique session. The session is stored in a
+L<Jifty::Web::Session> object and can be accessed using the
+C<< Jifty->web->session >> method.
+
+=item return from a continuation if requested
+
+If there is an open continuation on the stack (e.g. from a
+C<< Jifty->web->tangent >> link) and the return has been requested
+(e.g. by a C<< Jifty->web->return >> link), the return will execute at
+this stage.
+
+=item handle dynamic request unless already served
+
+First, the user is given a cookie containing the session-id. Then, the
+request is forwarded to C<< Jifty->handler->dispatcher >>, a
+L<Jifty::Dispatcher> object to handle the request. The dispatcher
+works through the following steps:
+
+=over 4
+
+=item setup
+
+In this stage, all rules in the dispatcher that are marked with the
+word C<before> are run.
+
+=item run the actions involved
+
+Every L<Jifty::Action> that is registered in a form or involved in a
+link or button is run in this stage.
+
+=item run dispatching rules
+
+This stage is responsible for working through all rules marked by
+words like C<under>, C<on>, C<when> and so on. This is a point where
+based on the URI or parameters the template to get displayed may still
+be modified, data get retrieved, additional actions run or the template's
+parameters get adjusted.
+
+=item show the page
+
+Here, the template displaying the page is run.
+
+=item cleanup
+
+This final stage of the dispatcher will run all rules marked with the
+word C<after>.
+
+=back
+
+=item cleanup several things
+
+Finally, the eventually modified session-record is flushed and some
+internally allocated structures get deallocated.
+
+=back
+
+=head1 SEE ALSO
+
+L<Jifty::Handler>, L<Jifty::Dispatcher>, L<Jifty::Request>, L<Jifty::Response>
+
+=cut
+

Added: jifty/branches/schema-plugins/lib/Jifty/Manual/Style.pod
==============================================================================
--- (empty file)
+++ jifty/branches/schema-plugins/lib/Jifty/Manual/Style.pod	Mon Jan 29 21:05:02 2007
@@ -0,0 +1,72 @@
+=head1 NAME
+
+Jifty::Manual::Style - Jifty coding style guide
+
+
+=head3 Default style
+
+When in doubt, default to whatever Damian Conway's I<Perl Best
+Practices> says.
+
+
+=head3 Private documentation
+
+When documenting a private method, or providing documentation which is
+not useful to the user of the module (and is presumably useful to the
+developer), wrap it in =begin/end private.  This way it does not show
+up in perldoc where a user would see it and yet is still available and
+well formatted (that is, not just a lump comment) when looking at the
+code.
+
+  =begin private
+
+  =head2 import_extra
+
+  Called by L<Test::More>'s C<import> code when L<Jifty::Test> is first
+  C<use>'d, it calls L</setup>, and asks Test::More to export its
+  symbols to the namespace that C<use>'d this one.
+
+  =end private
+
+  sub import_extra {
+        ...
+  }
+
+
+=head3 Test temp files
+
+Files created by tests should be declared as such using
+Jifty::Test->test_file() so they are cleaned up on a successful test
+run.
+
+
+=head3 Use Shell::Command
+
+Shell::Command has a number of functions which work like common shell
+file commands such as touch, cp and mv.  They are battle tested and
+cross-platform.  Use them instead of coding your own.
+
+For example, instead of this:
+
+    open my $file, ">foo";
+    close $file;
+
+Do this:
+
+    use Shell::Command;
+    touch $file;
+
+
+=head3 Case insensitive matching
+
+To check if a string equals another string case insensitively, do this
+
+    lc $foo eq lc $bar;
+    lc $foo eq 'bar';
+
+not this:
+
+    $foo =~ /^\Q$bar\E/i;
+    $foo =~ /^bar$/i;
+
+=cut

Added: jifty/branches/schema-plugins/lib/Jifty/Manual/Tutorial.pod
==============================================================================
--- (empty file)
+++ jifty/branches/schema-plugins/lib/Jifty/Manual/Tutorial.pod	Mon Jan 29 21:05:02 2007
@@ -0,0 +1,497 @@
+=head1 NAME
+
+Jifty::Manual::Tutorial - Zero to Jifty in a Jiffy
+
+=head1 DESCRIPTION
+
+This tutorial should give you everything you need to 
+build your first application with Jifty.
+
+=cut
+
+=head1 HOW TO
+
+=head2 The requirements
+
+Here's what you need to have installed -- at least when we write it.
+
+=head2 Installing Jifty
+
+No bones about it. We believe pretty strongly in the DRY (Don't Repeat
+Yourself) principle. That's one of the big reasons we love Perl and
+CPAN. Jifty makes use of lots of amazing code from CPAN.  At last count,
+it directly depended on 60 packages from CPAN.  Most of these libraries
+are cross-platform pure-Perl packages and should run great out of the
+box on any platform you can get Perl onto.
+
+We've gone to lengths to make sure you don't spend your day
+downloading library after library by bundling everything we can inside
+the Jifty package.  The Jifty installer is capable of determining what
+modules your system needs, and downloading and installing them all in
+one go.  Don't worry, it will ask you first before it makes any changes.
+
+On most systems you can Perl's bundled CPAN module to download
+and install Jifty:
+
+  # perl -MCPAN -e'install Jifty'       # Unix-like systems
+  # perl -MCPAN -e"install Jifty"       # Win32 systems
+
+If you've downloaded a C<.tar.gz> of Jifty, you can do a
+manual install:
+
+  # tar xzvf jifty-<version>.tgz
+  # cd jifty-<version>
+  # perl Makefile.PL
+  # make
+  # make test
+  # make install
+
+If the tests don't pass, we want to hear about it. Please join us
+on C<jifty-devel at lists.jifty.org> and report the failure. (See 
+L</GETTING HELP> below for info on how to join the list.)
+
+=head2 Setting up the Scaffolding
+
+Once you have Jifty happily installed, you're ready to 
+create your first application. 
+
+Jifty is intentionally a bit minimalist. All you I<really>
+need to make an application go is a copy of the F<jifty> commandline
+tool (inside your new application's F<bin/> directory.  
+
+Of course, it's often helpful to have a bit more structure around to
+help guide your work. Jifty comes with tools to build that structure for
+you.
+
+Change directory to some place it will be safe to create a new
+Jifty application. (Jifty will create a subdirectory for you).
+
+  # jifty app --name MyWeblog
+  Can't guess application root from current path (/tmp) or bin path (/usr/bin)
+  Creating new application MyWeblog
+  Creating directory lib
+  Creating directory lib/MyWeblog
+  Creating directory bin
+  Creating directory etc
+  Creating directory doc
+  Creating directory log
+  Creating directory var
+  Creating directory var/mason
+  Creating directory share
+  Creating directory share/po
+  Creating directory share/web
+  Creating directory share/web/templates
+  Creating directory share/web/static
+  Creating directory lib/MyWeblog/Model
+  Creating directory lib/MyWeblog/Action
+  Creating directory t
+  Creating configuration file MyWeblog/etc/config.yml
+
+Let's take those one by one.
+
+=over
+
+=item bin
+
+Inside F<bin/> is F<jifty>, the Jifty command dispatcher. Some
+of the most important commands are C<schema>, which sets up or updates
+your database schema and C<server>, which starts a standalone
+webserver. To find out what commands your F<jifty> comes with, run:
+
+    jifty help
+
+=item etc
+
+Configuration files live in F<etc/>, though if you don't have a config
+file, Jifty will supply some sane defaults.
+
+=item doc
+
+Jifty won't magically write your documentation for you, but when B<you>
+write your docs, put them in F<doc/>.
+
+=item log
+
+Jifty uses L<Log::Log4perl> to configure its logging. By default, it
+dumps logs named F<server.log> and F<error.log> into the F<log> directory.
+
+=item share/web/templates
+
+Jifty uses L<HTML::Mason> as its primary templating system.  Put
+your application's templates into F<share/web/templates/>.  Out of
+the box, Jifty comes with an application I<skeleton> that it installs
+in F<share/web/templates/>.  This default application is a convenient
+way to get a basic application up and running quickly, but probably
+needs some customization as you build a more advanced application.
+
+You can find where Perl stuck Jifty's default templates with:
+
+  perl -MJifty::Util -e 'print Jifty::Util->share_root'
+
+=item share/web/static
+
+Some nontrivial percentage of the I<stuff> your web application serves
+out doesn't need to (or I<shouldn't>) pass through your templating
+engine.
+
+Just drop your static files into F<share/web/static/> and Jifty will serve
+them out if it can't find a template with the right name.
+
+Out of the box, Jifty comes with a CSS style, Javascript libraries and a
+Pony. Look in F<share/web/static> in the Jifty distribution, or in the same
+place Jifty stuck its default templates.
+
+=item lib/MyWeblog
+
+For a full treatment of the Jifty object model see
+L<Jifty::Manual::ObjectModel>.
+
+To build a basic Jifty application, you only need to worry about two
+sorts of classes, B<Models> and B<Actions>.
+
+=item lib/MyWeblog/Model
+
+The real base of your application lives in
+C<lib/B<ApplicationName>/Model>. Classes here define your application's data
+structures and how they relate to each other.  Jifty will use your model
+classes to set up and upgrade your database's schema when it needs to.
+
+=item lib/MyWeblog/Action
+
+When we said you only need to worry about B<Models> and B<Actions>,
+we weren't telling the whole truth.  Jifty will take care of basic
+database-interaction (C<CREATE, READ, UPDATE, DELETE>) B<Actions> for
+your B<Models>, but they're there if you want to change anything.
+
+=item t
+
+Jifty starts off your application with a basic harness, but can't yet write 
+all your tests for you. (It does, however, build simple tests for model
+classes you generate.)
+
+=item var
+
+Jifty stores cache files here while the server is running. You shouldn't ever
+have to touch this directory.
+
+=back
+
+=head2 Building your data model
+
+As you might imagine by the fact that this tutorial application is named
+B<MyWeblog>, the example here is a simple weblog application.  Future
+tutorials will add authentication, comments, and RSS and Atom feeds.
+
+=head3 Posts
+
+Weblogs tend to center around posts, so it's no surprise that the first model
+to create is the C<post>:
+
+  # cd MyWeblog
+  # jifty model --name Post
+  Writing file /tmp/MyWeblog/t/00-model-Post.t
+  Writing file /tmp/MyWeblog/lib/MyWeblog/Model/Post.pm
+
+Great! Now you have a B<Post> model (not that it models anything yet).
+
+Open F<lib/MyWeblog/Model/Post.pm> in your favorite text editor.
+
+You should see something like this:
+
+  use strict;
+  use warnings;
+  
+  package MyWeblog::Model::Post;
+  use Jifty::DBI::Schema;
+  
+  use MyWeblog::Record schema {
+  
+  };
+  
+  # Your model-specific methods go here.
+  
+  1;
+
+
+Now it's time to tell the model class about posts. Start by giving our post a
+C<body> and a C<title>. (In a future tutorial, the application will become fully
+folksonomy-compliant by adding a C<category> and upgrading that C<category> to a
+C<tags> table.)
+
+Position your cursor right after:
+
+  use MyWeblog::Record schema {
+
+Add the lines:
+
+  column title =>
+        type is 'text',
+        label is 'Title',
+        default is 'Untitled post';
+
+  column body => 
+        type is 'text',
+        label is 'Content',
+        render_as 'Textarea';
+
+Save your model class.
+
+=head2 Setting up the database
+
+Ok. It's time to initialize MyWeblog's database. By default, Jifty sets up your
+application with the SQLite database engine.  If you'd rather use PostgreSQL or
+MySQL, you need to add some content to F<etc/jifty.yml>. (See C<Jifty::Config>
+for a bit more information).
+
+  # jifty schema --setup
+  INFO - Generating SQL for application MyWeblog...
+  INFO - Using MyWeblog::Model::Post
+  INFO - Using Jifty::Model::Session
+  INFO - Using Jifty::Model::Metadata
+  INFO - Using Jifty::Model::Schema
+  INFO - Set up version v0.0.1, jifty version 0.607280
+
+=head2 Starting the Jifty application server
+
+Ok. You have a working, if simplistic