From 5d3ee884ba04aefebb01784906a62bec2c8f9c02 Mon Sep 17 00:00:00 2001
From: Christoph Zwerschke John Dickinson has created three files which, together, provide a fairly simple way to implement some Ajax functionality into Webware servlets. AjaxPage provides a super class to your servlet (but below your site page). All JavaScript necessary is contained in ajax.js and ajax_polling.js. ajax.js provides basic functionality useful for most situations, and ajax_polling.js provides support for long-running requests and out-of-band server to client commands. The AjaxPage class creates a function ajax_allowed() which returns a list of function names. These function names refer to Python functions that are able to be called by an Ajax-enabled web page. This is very similar in functionality to webware's actions. Child classes should override ajax_allowed(). AjaxPage also provides the class PyJavascript. This class simply tanslates a Python expression into a string. For example: PyJavascript is based in large part on code from Nevow 0.4.1 (nevow.org). The AjaxPage class uses PyJavascript to set up several useful references to JavaScript functions. ajax.js provides all the client-side heavy lifting required to get Ajax functionality into a web page. Several pieces of it are based on ideas from Apple developer code (developer.apple.com) and Nevow 0.4.1 (nevow.org). ajax_polling.js provides functionality that allows the server to process long-running requests from the client and allows the server to send commands to the client without the user on the client side triggering an event. Client triggers an action. This request is sent to ajax_controller(). Once the server-side function has returned, the results are sent back down the pipe to the client... ...unless it took longer that TIMEOUT seconds to complete (the timeout is defaulted to 100). If the function take a while to finish, ajax_controller() puts the results into the results bucket that ajax_response() is polling. ajax_response(), which is being polled every few seconds by the client, sees that there is something for the client in the results bucket, grabs it, and sends it to the cient. The polling behavior of an ajax-enabled page may be controlled by overriding ajax_clientPollingTimeout. Setting its return value to None prevents the polling from happening at all. Otherwise, this function needs to return the number of seconds to wait until the client polls the server again. Downloads: Robert Forkel has compiled an extended example named AjaxSuggest. This example shows how to implement functionality a la Google suggest. Note: This example will be already included in the Examples context of Webware for Python starting with version 0.9.1. OpenRico is a Javascript for Rich Application library including ajax, drag&drop and many visual effects.
+Here explains ajax servlet with OpenRico. The Ajax Servlet library AjaxServlet.py: search zipcode servlet example:: for real working example: goto http://www.bodd.co.kr/member_register (only korean site) click input "신림9" and click first button -- whitekidAJAX in Webware
+
+AjaxPage
+foo = PyJavascript('bar')
+foo.hello('hi').another.element.func() # evaluates as the string "bar.hello('hi').another.element.func()"
+ajax.js and ajax_polling.js
+The Anatomy of an AJAX-enabled page
+
+
+
+
+
+
+Example
+class my_servlet(AjaxPage):
+ def ajax_allowed(self):
+ return ['check_if_even']
+
+ def check_if_even(self,val):
+ is_even = (int(val) % 2) == 0
+ if is_even:
+ ret = self.setTag('response_id','The value you entered is even!')
+ else:
+ ret = self.alert('Oh no! The value you entered is not even!')
+ return '%s; %s' % (self.setReadonly('even_num',False),ret) # don't forget to unlock the field
+
+ def writeContent(self):
+ wl = self.writeln
+ wl('<form action="some_page.py" method="post">')
+
+ # will first set the input field to read only, then call check_if_even with the field's value passed in
+ ajax_cmd = self.generic_ajax(self.setReadonly('even_num',True),'check_if_even',self.this.value)
+
+ wl('<input name="even_num" id="even_num" type="text" onchange="%s"/>' % ajax_cmd)
+ wl('<span id="response_id"></span>') # see check_if_even() for tag name
+ wl('</form>')
+Ajaxservlet
+
+from WebKit.RPCServlet import RPCServlet
+
+class AjaxServlet(RPCServlet):
+ def awake(self, transaction):
+ RPCServlet.awake(self, transaction)
+ self._response = transaction.response()
+ self._request = transaction.request()
+
+ self._session = transaction.session()
+ self._resp = []
+ def sleep(self, transaction):
+ RPCServlet.sleep(self, transaction)
+ self._response = None
+ self._request = None
+ self._session = None
+ self._resp = None
+
+ def respondToGet(self, trans):
+ try:
+ # ajax servlet don't need cache
+ resp = self.response()
+ resp.setHeader('Cache-Control', 'no-cache')
+ resp.setHeader('Pragma', 'no-cache');
+
+ self.writeln('<ajax-response>')
+ self._respond()
+ self.writeln('</response></ajax-response>')
+
+ self.sendOK('text/xml', ''.join(self._resp), trans)
+ finally:
+ pass # do error handling or database release
+
+ def request(self): return self._request
+ def response(self): return self._response
+ def transaction(self): return self._transaction
+
+ def _respond(self):
+ """ Here goes the response
+ self.write('<span>Here is ajax response!!</span>')
+
+ NOTE: You must call responseToElement() or responseToObject() before write something
+ """
+ raise NotImplementedError
+
+
+ def responseToElement(self, elementId):
+ self.write('<response type="element" id="%s">' % elementId)
+
+ def responseToObject(self, objectId):
+ self.write('<response type="object" id="%s">' % objectId)
+
+ def write(self, *args):
+ for arg in args:
+ self._resp.append(self.encode(str(arg)))
+
+ def writeln(self, *args):
+ self.write(*args)
+ self.write("\n")
+
+ def decode(self, str, encoding='euc-kr'):
+ """ Decode JavaScript quoted string to native string """
+ ret = []
+
+ while s:
+ if s[:2].lower() == '%u': # 유니코드 인코딩
+ char = s[:6]
+ unicode_chr = int( char[2:], 16)
+ try: ret.append( unichr(unicode_chr).encode(encoding) )
+ except UnicodeEncodeError: ret.append( '&#%s;' % unicode_chr )
+ s = s[6:]
+ else:
+ ret.append( s[0] )
+ s = s[1:]
+
+ return ''.join(ret)
+
+
+ def encode(self, str, encoding='euc-kr'):
+ """ Encode string to HTML unicode representation """
+ p = string.printable
+ ret = []
+ for c in unicode(str, encoding):
+ if c in p: ret.append(c)
+ else: ret.append( '&#%d;' % ord(c) )
+ return ''.join(ret)
+from AjaxServlet import *
+from Zipcode import *
+
+class ajax_search_zipcode(AjaxServlet):
+ def _respond(self):
+ self.responseToElement('search_result')
+ zipcode_list = Zipcode.search(self.decode(self.request().field('dong')))
+
+ self.write("""<table cellspacing="1" cellpadding="1" width="100%" bgcolor="black" bordercolordark="#DDDDDD" bordercolorlight="#666666">
+ <tr align="center" bgcolor="#DDDDDD" height="22">
+ <td bgcolor="#DDDDDD">우편번호</td>
+ <td bgcolor="#DDDDDD">주 소</td>
+ <td bgcolor="#DDDDDD">선택</td>
+ </tr>\n""")
+
+ for z in zipcode_list:
+ self.write( """<tr bgcolor="#DDDDDD">
+ <td bgcolor="#FFFFFF" style="white-space: nowrap;">%s</td>
+ <td bgcolor="#FFFFFF" style="white-space: nowrap;">%s %s %s %s</td>
+ <td bgcolor="#FFFFFF"><input type="button" value="선택" onClick="postaddr('%s', '%s');"/></td>
+</tr>\n""" % ( z[0], z[1], z[2], z[3], z[4], z[0], z[1] + z[2] + z[3] ) )
+ self.write('</table>')
+
+
+
button.
Here is a list of ideas for open source apps to build with, or for +Webware. If you add an idea or comment, please sign your name and +leave a date stamp. Many of the project ideas listed below will be +interrelated, so use cross-references where appropriate.
+Extensions to the Webware and WebKit core (as opposed to other Kits or +stand-alone applications) belong on the `Wish List`_ page.
+I'm not sure what this would look like, but some object to facilitate +the collection of RSS feeds and embedding them into a web page. I +guess there would be a few parts coded into a single class, or a +single class with helper classes:
+Configuration info: which site to connect to, how often to refresh.
Read and parse the RSS file at the specified interval.
Send some kind of "observe me now" signal to the object that's +serving the final output, so it can refresh itself. Perhaps +Threading.Event or a port of Java's Observable/Observer interface +can help with this.
Offer the RSS data in a Python data structure to any routine that +asks for it. Perhaps a method in the RSS-retrieval object can offer +this, or it can be in a well-known attribute somewhere.
Have some boilerplate output objects that convert the RSS data into +HTML hyperlinks, for simple sites that want an "out of the box" +solution. These classes should be scalable for adding cosmetic +enhancements via stylesheets or subclasses.
-- Mike Orr - 14 Apr 2002
+The following other web application servers may have objects worth +porting to Webware:
+Horde Horde may have some objects worth porting. "The Horde +Application Framework is a general-purpose web application framework +in PHP, providing classes for dealing with preferences, compression, +browser detection, connection tracking, MIME handling, and more."
+ +-- Mike Orr - 04 Apr 2002
+Webmail software that could be ported to Webware or ideas stolen from.
+Horde IMP -- IMAP/POP e-mail access.
+(This isn't something I need anytime soon, but would be worthwhile +someday.
+-- Mike Orr - 04 Apr 2002
+BoboMail is a decent POP webmail client that runs off CGI and bobo +(an old version of Zope). It's fairly decent code, and even if a lot +of stuff gets rewritten it would serve a good starting point for +writing such a client. -- Ian Bicking - 08 Apr 2002
+(See Python Card Interface)
+PythonCard -- looks very interesting, and maybe it could provide an +alternative to a browser interface, in those cases where the browser +provides a less-than-optimal interface (e.g., data entry). Using +XmlRpc, maybe there's a way to make this sort of thing easy.
+-- Ian Bicking - 23 Jan 2002
+(See Webware Objects)
+Just finished reading MiddleKit docs. What are the chances of adding +a feature to MiddleKit that will read an XSD file, instead of CSV. +I'm more than willing to take the point on this ... since I'm bringing +it up, but I would like some help in some of the nitty-gritty details +of MiddleKit. It's new to me. Otherwise I'm just re-writing a whole +bunch of stuff that's already been done.
+Thanks -- Ray Leyva - 20 Jan 2002
+I know ambitious name, but it's an ambitious plan. Generate simple +reusable objects that know how to render, replicate, and store +themselves. I'm initially interested in creating objects that will +automagically tie themselves into a database once imported into a +framework, and immediately become available for data entry using +internally defined display / validation schemes
+This came from my initial, and now semi-abandoned attempts to create a +single interface WebwareReportKit.
+I have so far created a validation, rendering, and reporting scheme. +I'm starting work on the storage components right now. Don't want to +redo the MiddleKit stuff, but until I know where I'm going with the +general object layout I don't want to commit to any single OR mapping.
+Things to note, the items I've completed work with XML / XSL / XSD, +and AFAIK the current best crop of those tools live in the java world. +I don't have the time to be able to both build this infrastructure, +and help out on the PyXML stuff. Wish I did. I use XmlRpc to tie +them together, of course this could be SOAP / CORBA or whatever remote +invocation procedure you like to use.
+WebKit is the Application server that I'm basing the framework off of, +but I'm designing these objects with modularity in mind. IE : I don't +want to rule out using Java based App servers ... if push comes to +shove, and some client somewhere REALLY doesn't want to use Python / +Webware ;D
+Is this of interest to anyone. I'm trying to figure out the best way +to make this available ... I really want to give back to the +community.
+All this because I figured out that for me to be able to print the +stuff from WebwareReportKit I would need to have a semi-intelligent +data-entry component first ... duh! ;D
+PS : I'll get to that re-org sometime soon! :D +-- Ray Leyva - 19 Jan 2002
+I have been working on (and then reworking over and over again...) +some XML tools, imaginatively known as XMLTools, which attempt to +provide mappings from database schemas to XML "instances" through +descriptions of those instances, which are themselves highly +simplified documents with the same purpose as XML Schema documents +(which is what I presume you mean by XSD).
+The aim is to support XML instance validation, templating and storage +in various forms (such as in relational databases). An +object-relational mapping could be a consequence of this work, but +that doesn't interest me that much right now.
+Eventually, I want to bring XMLForms back with its core replaced by +XMLTools, so that the main purpose of XMLForms is the integration with +Webware (and possibly other Web frameworks).
+-- Paul Boddie - 02 Apr 2002
+This would be more of a general compendium of standard reports that +can be generated. For example:
+Invoices
Bill Of Materials ( BOM )
Legal documents
Real Estate Documents
Generic process mandated documents.
Heck .. tax forms!
This could be used in conjunction with WebWare, and a database to +generate data driven reports. It'd be a very useful component because +a great many applications require reporting functions.
+PS: Are we putting newest ideas at the top, and oldest at the bottom? +If so I'd like to ask for general permission to re-order the older +inputs to reflect that.
+-- Ray Leyva - 27 Nov 2001 <br />
+That certainly does sound useful! Have you looked at Biggles for +producing charts? ... fine with me about re-ordering -- Tavis Rudd +- 27 Nov 2001
+Sorry, moved away from python, and code based reporting tools +... moved towards XSL:FO solutions. -- Ray Leyva - 19 Jan 2002
+(See WebwareXManagement)
+the link point to a page about some meta discussion about the several +SomethingManagementSystems. The "X" stands for "something" and not a +well known display manager :-) -- Stephan Diehl - 22 Nov 2001
+(See Webware User Manager)
+A good user management system is essential for most of the ideas +listed below! Click on the link above for more notes and +discussion. -- Tavis Rudd - 20 Nov 2001
+(See Webware Document Management System)
+This might be the same than Webware Content Management System +and/or a Webware Knowledge Management System. More can be seen on +the topic page -- Stephan Diehl - 21 Nov 2001
+(See Webware Wiki)
+a wiki built with Webware. Wikis are wicked! -- Tavis Rudd - 30 +Oct 2001
+(See Webware CVS Manager)
+A WebKit/Webware implementation of the infamous viewcvs.cgi +script. WebKit's persistence and potential for caching could make a +huge improvement in responsiveness and allow sites like SourceForge to +consume less hardware for this feature.
+-- Chuck Esterbrook - 31 Oct 2001
+(See Webware DB Admin)
+A database management frontend. Like phpMyAdmin, but database +agnostic. phpMyAdmin is one of the most popular applications on +SourceForge. Someone said that "the application sells the platform", +well a high quality tool like this would be a huge selling point for +Webware. -- Tavis Rudd - 01 Nov 2001
+(See Webware Content Management System)
+A ContentManagementSystem built with Webware (Similar to Zope and +Macromedia's SiteSpring). Comprising:
+WebAdminInterface
WebwareCVSManager
WebwareTaskManager
SafeDelegation
WebwareSearchEngine
WebwareFolders (like ZopeFolders)
NOTE: this AppIdea is strongly interrelated with the +WebwareSourceforge AppIdea and WebwareXManagement.
+-- Tavis Rudd - 31 Oct 2001
+(See Webware Cofax)
+Cofax is the Java software that powers Knight-Ridder newspaper web +sites, like http://inq.philly.com/.
+(See Webware Sourceforge)
+a sourceforge/tigris like application built with Webware. -- +Tavis Rudd - 30 Oct 2001
+(See Webware List Archive)
+a geocrawler-like email archive viewer (that actually works!) -- +Tavis Rudd - 31 Oct 2001
+(See Webware Forum)
+a discussion forum component -- Tavis Rudd - 01 Nov 2001
+(See Python Web Stats)
+a modular web log analyzer with a webware front-end, that can also be +used programmatically or with other frontends. The existing Open +Source log analyzers suck! -- Tavis Rudd - 31 Oct 2001
+I have a totally (overly?) interface-agnostic web log analyzer that I +never polished with a nice frontend. If someone wants to try +something with this, contact me -- Ian Bicking - 02 Nov 2001
+(See Webware Slash)
+a slashdot news site that sould let users upgrade from a common news +app such as PHPNuke. The existing PHP sites get slow under load and +the code is getting pretty complex and ugly. A python update will get +attract frustrated PHP webmasters -- Aaron Held - 2 Nov 2001
+(See Webware Vaults)
+a Parnassus-like site, not just using WebKit's base features, but also +using some of the other kits and extensions -- Paul Boddie - 06 Nov +2001
+(See Webware Groupware)
+Looking to create a Webware based Groupware application. It should +include email, and calendaring functions. There's a million of them +out there, but not for Webware ;D
+With this as a starting point I would like to eventually get to +something like a WyattERP (it's hosted on SourceForge), except ASP +and Python/WebWare based.
+ +-- Ray Leyva - 17 Nov 2001 <br />
+Facilitating non-browser interfaces -- Ian Bicking
+Why is there the avoidance of discussion on commercial implications of Wiki and related material? An example would be for how we might implement it our (ASP) ecommerce software http://www.veracart.com +please inform me if such a discussion is taking place already: y@mytechsupport.com
+This pages links to recommendations and notes about how you should set +up your application:
+SitePage -- How to create a master template for your site.
Directory Structure -- Notes on how to create a robust directory +structure for your site.
ModelViewController -- A paradigm for keeping content, design, and +code separate.
Web Style Guidelines -- Links and notes related to good hypertext +style.
Managing The URI Space -- Creating persitent, meaningful resource +names.
Model Two plus One -- An example of using the Logic / View + +Actions design
See also: Webware Recipes
+Webware's core is its "Application Server", which is known as "WebKit".
+See http://webopaedia.com/TERM/a/application_server.html for more +notes on application servers.
+Several people have suggested that the name "WebKit" should be +scrapped when Webware is transitioned to a DistUtils based package +architecture. ChuckEsterbrook likes the name and has rejected these +suggestions so far, but the discussion isn't over yet. My argument is +that it is better to position and describe Webware as 'A +Python-Powered Application Server', that comes with a suite of useful +components, than saying that "Webware for Python is a suite of +software components for developing object-oriented, web-based +applications." The former is clearer and more direct. The latter is +ambiguous and needs clarification. The name "WebKit" and the latter +description imply that the AppServer is just another component of +Webware. This is misleading: the AppServer is the heart of Webware.
+Using the name WebKit also makes the module/package structure and path +management issues more complex than they should be.
+-- Tavis Rudd - 29 Oct 2001
+I wouldn't mind seeing other kits which handle other forms of +communication. What about MailKit, for example? One could imagine the +nature of requests and responses to be quite different in that kind of +environment.
+-- PaulBoddie - 30 Oct 2001
+Such 'kits' could still be created if the name 'WebKit' was removed. +A sensible package layout would be something like this:
+Webware [package]
+MultiPortServer [module]
AppServer [module]
Application [module]
Transaction [module]
Servlet [module]
Request [module]
Response [module]
Session [module]
SessionStore [module]
Cookie [module]
WebUtils [sub-package]
MiscUtils [sub-package]
MiddleKit [package]
UserKit [package]
FunFormKit [package]
Cheetah [package]
XMLForms [package]
other 'kits' and related packages ...
-- Tavis Rudd - 30 Oct 2001
+I brought this up again on the list a few weeks ago and Chuck said his +final answer to my request to get rid of the name 'WebKit' was no. +I'll agree to disagree.
+-- Tavis Rudd - 23 Nov 2001
+Doing "View source" from the browser doesn't work if your page was +produced in response to a POST, since your browser may not re-POST +the form variables (mozilla doesn't, at least).
Debugging by hand is tedious, and if posible should be avoided by +using HTML validators.
You can't use online web validators (which validate a given URL) in +the context of a web application, because your web application often +requires a session id, which the validator obviously can't send to +your server
This approach uses Web Design Group's HTML validator, which can be +installed on your local machine (available at +http://www.htmlhelp.com/tools/validator/ ).
+You hook it up to your servlets so that the HTML output your servlet +produces is automatically validated, and the validation output and +full HTML source (with highlighted errors) is appended to the normal +output and sent to the browser.
+Install the WDG offline-validator. In particular, you need the +"validate" script which can be called from the command line. Debian +users: apt-get install wdg-html-validator
Apply the patch at +http://www.opensky.ca/~jdhildeb/webware_validator_streambuffer.patch +to webware. This makes it possible to get the accumulated HTML in +the response object from within your servlets, before the response +has been committed.
Add the validateHTML method (available at +http://www.opensky.ca/~jdhildeb/webwarevalidator.py ) to your +SitePage, and call it at the end of writeBodyParts (you'll have to +override Page.writeBodyParts() if you haven't already done +so). validateHTML won't get all the HTML produced by your servlet if +you call response.flush() explicitly, so don't do that. :)
Enjoy!
+-- JasonHildebrand - 20 Sep 2002
+From the 0.6 Install Guide:
+++The most common installation problem is a Python exception +appearing in your browser that says "bad marshal data". This is +always caused by pointing the web browser to the app server:
+http://localhost:8086/WebKit.cgi/
+But the app server hides behind a web server so the correct URL +would be:
+ +That requires that web server and app server are set up to talk to +each other.
+
See InstallGuide.html in Webware/WebKit/Docs for full details, or +you can read the one for the last production release at:
+http://webware.sourceforge.net/Webware/WebKit/Docs/InstallGuide.html
+-- ChuckEsterbrook - 30 Nov 2001
+A packaged version of Webware that comes with the latest versions of +other tools that are commonly used with Webware.
+Examples of these tools are Cheetah, FunFormKit, XmlForms, and +Python database-adaptor modules such as psycopg.
+-- TavisRudd - 31 Oct 2001
+Create a BatteriesIncluded distribution of Webware that comes with +other related tools, such as Cheetah, FunFormKit, XmlForms, the +database adaptors, etc.
+TavisRudd
+TavisRudd
Packaging/installation system using distutils has been created as part +of WebwareExpRefactoring.
+There are several tools that are designed for, or complement, Webware +that are not currently distributed with it and must be downloaded and +installed separately. As a result Webware installations take longer +than they should.
+Uses Python's DistUtils to create a meta-distribution that gathers all +the most useful Webware tools in one place and installs them in one +operation.
+incompatible license problems
overkill
Webware 0.7
+Contents
+Webware and all the core components
Cheetah
FunFormKit
Database modules like psycopg
a plotting module like Biggles (http://biggles.sf.net) for +quickly adding charts to websites
example sites
Implementation
+use a master DistUtils setup.py script to control the whole +installation process so that all the components can installed in one +fell swoop. "python setup.py install" will install Webware, while +"python setup.py install-batteries" will install the third-party +packages.
the end-user will control what will and won't be installed out of +all the included stuff using the setup.cfg
make Webware's setup.py compile and install mod_webkit or the iis +version (when complete). This could be controlled via the setup.cfg +file.
Add your thoughts and comments here, along with your sig -- +TavisRudd - 31 Oct 2001
+empty
+(This not exactly a Webware issue, but you may experience this in the +course of using Webware.)
+On a LAN machine, I set my HTTP server to run on port 79. I could +browse it with http://foo:79/ using the lynx, konqueror and opera +browsers, but mozilla and galeon gave me this mysterious message:
+++Access to the port number given has been disabled for security +reason.
+
I posted this to netscape.public.mozilla.general and found out that +this behavior is in response to the "cross-protocol scripting" +vulnerability described at http://www.kb.cert.org/vuls/id/476267.
+I also learned that you can override the banned ports by putting a +preference in the all.js script of your mozilla site installation:
+pref("network.security.ports.banned.override", "79");
+My all.js was found at /usr/lib/mozilla/defaults/pref/all.js. I +located it with rpm -q mozilla -l | grep all.js.
+Credit: Thanks to the folks at netscape.public.mozilla.general for +their help. For details, see the thread starting on 2001-12-26, +"Access to the port number given has been disabled for security +reasons".
+-- ChuckEsterbrook - 27 Dec 2001
+Which ports are banned? All below 1024 except 80?
+Some might argue that building an opt-in mailing list is not e-commerce, +because it is not directly involved in the "transactional" commerce. +However, anyone who has been marketing online for more than a month +knows that the gold is in the list -- you will continue to struggle +selling online until you build a list, or become Yahoo!
+So how do you start, and what does it have to do with Webware?
+who are you selling to
what do they want
what makes you different from your competitors
Second, you will need an followup autoresponder service You can program the web part of +this is python/webware, but unless you want to become an expert in handling spam +complaints and staying off blacklists, you might want to leave the email broadcasting +to someone else. YMMV.
+relevant and specific to your offer
valuable to the prospect
easy for you to provide (low cost in money and time)
The plan is to offer the bribe as a motivation to get +the suspect (e.g. fist time visitor) to opt-in. Once +the suspect opts-in, he becomes a prospect, and you can +begin to follow up with him until he knows, likes, and +trusts you enough to buy when the time is right.
+What does this have to do with Webware?
+The ability to generate dynamic pages allows you to create +a website that captures the opt-in aggressively without +being annoying.
+You can control when exit popups appear.
You can test multiple offers and easily +track where the visitor came from.
You can offer a repeat visitor something +he hasn't seen before.
If someone visits your website, and leaves without opting in +it would be nice to know why. An exit popup survey is the +perfect tool.
+Before you go hollering, let me say that I work primarily in +B2B markets, and my target market is not too terribly annoyed +by popups. In a B2C market, you'll need to test it.
+What about popup blockers? Well, there is not a lot we can +do about them. But even if 90% of your popups get blocked, +that's 10% that got through, and 10% of your abandonment +traffic got a chance to tell you why they left. That's better +than nothing.
+If your visitor is coming from a Google AdWords Ad, you need +to supress the popup. That's pretty easy with Webware.
++++
+- if "google" not in referrer:
+- +
# include popup code
+
Ok, now the part about not being annoying.
+Suppose someone visits your site, then leaves and gets the popup. +He answers the question, and clicks ok.
+Later, he comes back, pokes about, then leaves again. Are you +going to show him the same popup? No.
+What if he just closed the popup the first time he left? Are you +going to annoy him again by showing it again? Probably not.
+How do you do this? Set a cookie (about 90 days) the first time +the popup code gets loaded. When he comes back, you know from +the cookie that he has already seen the popup, so you suppress it +just like you did for Google.
+If you have flash audio clips that play automatically, you'll want +to use the same technique to say that they don't play automatically +when the page is revisited.
+In order to make your marketing messages most effective, you need +to continually measure, change, and measure again.
+The most significant Response Modifier is "traffic source." It's +easy to set up different pages for different traffic sources if +you have control of the link -- you can just link to a different +page in the site. (But in terms of concentrating page rank, you +may not want to do this all of the time.) If you don't have control +of the link, you'll just need to trust the http-referrer header.
+In any case, you'll want to track each traffic source, measure +how many "hits" vs. "actions" you get (that's your conversion rate) +and possibly create different offers for each.
+Another important Response Modifier is the headline. How do you +test a headline?
+When someone first visits your page, you randomly select one of +two (or more) headlines, and include that in the page. You also +set a cookie (about 30 days) so he sees the same headline when +he comes back or refreshes the page. When the visitor finally +does take action (opt-in or purchase), you record that as an +action for that particular headline. The first version to get +40 actions is the winner and becomes the new control.
+Use the same pattern to test as many other response modifiers +as you want. (BTW: you should never stop testing.)
+Caveat: This part is just a theory. I have not tested it, and I +don't know whether it works or not. After I do test it and get +significant results, I'll come back and update this paragraph.
+Suppose you have a dozen different sites that are related. Each +site has a different ethical bribe, a different offer, and a +different autoresponder sequence. Because the sites are related, +someone who opts-in at one site is likely to be interested in +the other sites and offers.
+Suppose someone visits site A, opts-in, and downloads the ebook. +The next time he visits site A, it may make sense to cross-promote +site B. You can do that because you know he has already opted-in +on A, so including the same offer as before is just wasting +screen real estate. And if he goes to site B after opting-in +on A and B, you can make offer C. Similarly if he keeps ignoring +offer B, stop showing it to him.
+If you would like more information about testing and tracking, +or about building pages that compell the opt-in, you can join +my shy-yes list.
+-- TerrelShumway 10 July 2004
+People often ask 'Is Webware ready for prime-time use?' or 'Can +Webware really handle it?' The answer is yes, but this is the wrong +question.
+A better question would be 'can Webware help me build an application +that can reliably handle heavy loads?' Webware is not an application, +methodology, or recipe for success. It is a development framework and +a collection of useful tools. If you use the framework and tools +intelligently, and design your application well, then yes it will help +you build an application that can reliably handle heavy loads. If you +use them poorly, or botch your application design, don't cross your +fingers.
+An even better question is 'does Webware's architecture encourage and +facilitate effective application designs?' I believe it does, for the +following reasons:
+it uses Python: a well designed, modular, object-oriented, easy to +learn, and easy to maintain language
it is thoroughly object-oriented and encourages object-oriented +applications, unlike other frameworks like PHP and ColdFusion, which +tend to spawn a maze of spaghetti code and include files.
it is fairly simple to understand and very fast to develop with once +you've groked it. This encourages rapid prototyping and testing, +and helps weed out bad designs early on. Webware is a great fit for +software engineering methodologies such as eXtreme Programming +and Agile methods.
it doesn't dictate how you handle data storage and object +persistence.
it is extremely portable, allowing you great flexibility in your +choice of operating systems and other tools.
the Python and Webware user community is supportive, intelligent, +and experienced. If you run into technical or conceptual hurdles, +ask some smart questions and you'll get some real gems of clear +thought in response.
objects (servlets, sessions, data caches) persist in memory between +requests. This can lead to huge performance gains over other +frameworks without in-memory object persistence.
it is extensible by design.
Drop by the Webware Propaganda for some more info.
+Keep in mind that Webware is only one part of your toolkit. +Non-trivial applications will rely on many other resources. These +might include server and network hardware; operating system(s); +persistence mechanisms, such as filesystems and databases; web +servers(s); web caches, such as squid; external credit card +processors; shipping processors; and, of course, web browsers. The +performance and reliability of your application will depend on how you +utilize these resources in conjunction with Webware.
+Here's some notes on Using Webware Effectively.
+-- TavisRudd - 30 Mar 2002
+Have a look at some recent Webware benchmarks.
+-- ChrisZwerschke - 18 Apr 2010
+Chad Walstrom is a long-time Linux and Python enthusiast. He is also a Debian +Developer, maintaining packages such as pnm2ppa, cheetah, clamsmtp, and +GNU GNATS (gnats).
+Cheetah is a Python-powered template engine and code generator. It +can be used as a standalone utility or it can be combined with other +tools. Cheetah has many potential uses, but web developers looking +for a viable alternative to ASP, JSP, PHP and PSP are expected to be +its principle user group.
+Cheetah:
+generates HTML, SGML, XML, SQL, Postscript, form email, LaTeX, +or any other text-based format.
cleanly separates content, graphic design, and program code. This +leads to highly modular, flexible, and reusable site architectures; +faster development time; and HTML and program code that is easier to +understand and maintain. It is particularly well suited for team +efforts.
blends the power and flexibility of Python with a simple template +language that non-programmers can understand.
gives template writers full access to any Python data structure, +module, function, object, or method in their templates.
makes code reuse easy by providing an object-orientated interface to +templates that is accessible from Python code or other Cheetah +templates. One template can subclass another and selectively +reimplement sections of it.
provides a simple, yet powerful, caching mechanism that can +dramatically improve the performance of a dynamic website.
compiles templates into optimized, yet readable, Python code.
Cheetah integrates tightly with Webware for Python +(http://webwareforpython.org): a Python-powered application server and +persistent servlet framework. Webware provides automatic session, +cookie, and user management and can be used with almost any +operating-system, web server, or database. Through Python, it works +with XML, SOAP, XML-RPC, CORBA, COM, DCOM, LDAP, IMAP, POP3, FTP, SSL, +etc.. Python supports structured exception handling, threading, object +serialization, unicode, string internationalization, advanced +cryptography, and more. It can also be extended with code and +libraries written in C, C++, Java and other languages.
+Like Python, Cheetah and Webware are Open Source Software and are +supported by active user communities. Together, they are a powerful +and elegant framework for building dynamic web sites.
+Like its namesake, Cheetah is fast, flexible and powerful.
+-- TavisRudd - 29 Oct 2001
+Is maintaining the project since 2007.
+Please use our mailing lists for any questions, suggestions or contributions.
+I founded the Webware project in the spring of 2000. For a long time, I managed the +project, wrote code, applied patches, made design choices, wrote +documentation, cut releases and answered questions on the discussion +list. Of course, other team members were doing similar things.
+In 2007, I handed project management and leadership to the capable hands of Christoph Zwerschke so that I could focus more on my next project, The Cobra Programming Language.
+I'm still the primary maintainer for MiddleKit. If you need help in that area, I'll probably respond to your webware-discuss message. If I don't, track me down.
+My home page is at http://ChuckEsterbrook.com.
+The Webware home page is at http://webware.sourceforge.net.
+My latest project is The Cobra Programming language, found at http://cobra-language.com/
+This is the place to document all known compabilities and +incompatibilities between Webware, Python, and third-party +modules. The information here supplements official documentation, and +is meant to provide information on a more frequently updated basis +than the documentation revision cycle may allow.
+| + | Python 1.5 |
+Python 2.0 |
+Python 2.1 |
+Python 2.2 |
+
|---|---|---|---|---|
Webware 0.7 |
+no |
+ok |
+ok |
+ok |
+
Cheetah 0.9.12 |
+ok |
+ok |
+ok |
+ok |
+
FunFormKit 0.3.2 |
+ok |
+ok |
+ok |
+ok |
+
-- EdmundLian - 11 April 2002
+Contents
+ +Download: http://webwareforpython.org/downloads/Component/Component-0.2.tar.gz
Source repository: http://svn.webwareforpython.org/Component/trunk
Discussion: webware-discuss@lists.sourceforge.net
The repository is a Subversion repository. To check out a copy:
+$ svn co http://svn.webwareforpython.org/Component/trunk Component+
FreeBSD ports
+cd /usr/ports/www/py-webware-component && make install clean
+Component is licensed under an MIT-style license. This gives you +permission to most anything you want with Component.
+Component is a toolkit for Webware For Python. Webware is the only +prerequisite.
+Many enhancements in Webware require subclassing WebKit.Page. But +each of these enhancements is incompatible with the others, because +you have to choose an specific inheritance hierarchy to use them. You +can't subclass SecurePage and SidebarPage and MVCPage all +at once.
+One solution is Mixins, using multiple inheritance to add various +functions. This technique is available in Webware through +MiscUtils.MixIn. However, there are many places where Mixins are +mutually incompatible -- for instance, code often has to intercept the +awake() method, but delegating to each Mixin requires that they +all know about each other.
+Components are essentially a way of creating Mixins that all know +about each other.
+Components are useful if you have code that should know about the +request and response, and possible intercept it. If the code doesn't +need to know about the request at all, you should just create a normal +Python library, and call into it explicitly. Components can also be a +convenient way to add new convenience methods to your servlet.
+In order to use components, all your servlets must inherit from +Component.CPage. This subclass of WebKit.Page adds some new +convenient methods, but mostly just adds component support.
+New methods:
+Called automatically in writeBodyParts. If you are not using +a template, this can be used to write the HTML that goes at the +top of every page (the text written goes just after <body>).
+writeHeader compliment.
+CPage adds the idea of views. The default view is +writeContent -- that's the innermost method that is called. +This can be used with actions so that the action method performs +some work, then changes the view to display a different body. +This way actions occur before content display, but can effect +later display without losing the normal Python templating +mechanism (writeHead, etc). Templating components (like +ZPTKit) may use this concept of view to indicate a template to +use.
+Returns the view, as a string.
+For error responses. This can be used like:
+def awake(self, trans):
+ CPage.awake(self, trans)
+ try:
+ self.id = int(
+ self.request().extraURLPath().split('/')[1])
+ except (ValueError, IndexError):
+ self.sendResponseAndEnd(500)
+A simple error body is created if you don't pass one in.
+preAction and postAction are modified to do nothing (in +WebKit.Page they output a little HTML).
+CPage looks for any components you have in the .components +class variable (which should be a list). One very simple component is +included, NotifyComponent. As an example you can use this +component like:
+from Component import CPage +from Component.notify import NotifyComponent + +class SitePage(CPage): + + components = [NotifyComponent()] + + def writeHeader(self): + self.writeMessages()+
If the component was configured, it would probably take arguments to +its constructor (this simple component has no configuration). A +component can add new methods to the servlet. In this case it adds a +.message(text) method, which adds your message to the session, and +a .writeMessages() method which writes the messages and clears them +from the session. (Also a .messageText() method if you don't want +to write the messages immediately.)
+It's up to the component to add methods or attributes to the servlet. +It can also respond to "events" -- one example (and one of the only +current events) is the awake event, where it could intercept the +request. An example of this is in LoginKit, where the component +checks the servlet for permission settings, and may abort the +transaction with a login screen (or a Forbidden response) during +awake().
+Read the source -- there are many docstrings in Component.py.
+About this trick:
++++
+- def compute():
+- +
# ...
+data = compute()
+
I think I succeeded in applying this. +But, +Where/How can I check that the socalled 'data' variable is imported/computed only once ?
+P-Y Delens
+On Thu, 2002-04-25 at 07:47, Geoffrey Talvola wrote: +> Already partially done. Look at WebKit/Docs/Application.configlist and +> WebKit/Docs/AppServer.configlist. These files are used to auto-generate the +> documentation sections of the user's guide using +> WebKit/DocSupport/config.py.+
OnceAndOnlyOnce suggests that the foo.configlist should come from +the same place as defaultConfig.
+class ConfigurationOption:
+ def __init__(self,name,default,help):
+ ...
+
+class ConfigurationSchema:
+ def __init__(self,namespace,version,options):
+ ...
+
+ def default(self,key):
+ return self._optionMap[key].default
+
+ def defaults(self):
+ config = {}
+ for opt in self._options:
+ config[opt.name] = opt.default
+ ...
+
+class Configureable:
+ #configSchema() supercedes defaultConfig()
+ #config() uses the schema
+ #setting() can (optionally) warn if a key is requested that
+ #is not in the schema
+
+ def loadConfig(self,file): # factor out from userConfig
+ """
+ can (optionally) warn if there are keys present in the
+ file that are not in the schema (e.g. a setting gets
+ refactored or removed, user upgrades and cannot figure
+ out why his setting is now ignored.)
+ """
+# Application.py
+
+class Application(...):
+
+ _configSchema = ConfigSchema( "Application", "0.7",
+ [
+ ConfigOption("PrintConfigAtStartup", 1, "does what it says"),
+ ConfigOption("AdminPassword","webware", "blah blah blah"),
+ ...])
+
+ def configSchema(self):
+ return self._configSchema
+documentation and code are less likely to get out of sync
developers are more likely to provide documentation consistently
when schema changes, things are less likely to break without giving a clue as to what the problem is
config files can be upgraded automatically (if versioning is implemented)
an introspective tool can be written for configuring webware components/applications
if setting names or default values change, they change in one place.
future proofing:
+In Application, there are a dozen settings that deal with error +handling, half of a dozen that deal with sessions, and a few that are +already dictionaries with only an informal internal structure.
+It would be nice to be able to group these into their own schema with +a separate namespace.
+"AdminPassword" is in Application.config. If the current Admin +context were to get replaced (or if the "ErrorEmail" stuff were to get +refactored), it would be nice to be able to break these out into +another config file.
+it would be nice to be able to automatically upgrade .config files, +either in an =upgrade.py= script, or as the file is read into +memmory. This could accommodate name changes, namespace changes,
+an option could be deprecated by adding a deprecated attribute to the +ConfigOption.
+an option could be marked as experimental in the same way.
+a reserved "ConfigSchema" key/namespace to be included in all +configuration files:
+# foo.config
+{
+ "ConfigSchema": {
+ "Namespace": "Foo",
+ "Version": "0.0.1",
+ "Owner": "FooKit",
+ }
+
+ ...
+
+}
+this could also extend to "inline" namespaces such as "ErrorControl" +or "SessionControl": if a dictionary has a "ConfigSchema" key, it can +be versioned and handled by the config tool and treated as a +"namespace".
+If a config file does not have a "ConfigSchema" key, it is treated as +a legacy config with a mild suggestion that the user update the file +to match current conventions.
+e.g. current code does: +application.setting("Debug")["Sessions"]. New code might say +application.setting("ErrorControl")["EmailHost"] ... but this +would get out of control quickly. Maybe Configurable could be made +to handle "Debug.Sessions" or "ErrorControl.EmailHost"
+Maybe Configurable should become a delegate instead of a +superclass, then a refactored ErrorManager, could look up +setting("EmailHost") which might delegate to +application.setting("EmailHost",namespace="ErrorControl") or +even:
+import config
+host = config.setting("EmailHost",namespace=("Application","ErrorControl"))
+...
+OK. Lets calm down and take it one step at a time.
+---++ Blue Sky
+if ConfigOption could be related somehow to optik.Option, +settings could be overridden on the startup command +line. (OnceAndOnlyOnce again)
+A simple type system could eliminate the need to look at the name for +"Filename" or "Dir" in ConfigurableForServerSidePath. Use +option.type == TYPE_SERVER_PATH as the predicate.
+-- TerrelShumway - 25 Apr 2002
+Since tabs (at least at the moment) are a reality in Webware, perhaps +we can collect some practical tips for coping with them. It probably +makes sense to collect these by editor.
+-- JasonHildebrand - 27 Sep 2002
+?? why can't we use spaces? I use spaces for my Python coding using +Vim, and I use WebKit. I don't seem to have any +trouble.. -JamesBecker
+You can use spaces in your own Webware-based application -- no problem. +But if you need to modify Webware itself, you'll run into trouble if you +mix tabs and spaces.
+-- JasonHildebrand - 15 Apr 2004
+To teach Vim to switch to "noexpandtabs" mode when editing a file in +any subdirectory of "Webware", add these lines to your ~/.vimrc
+autocmd BufEnter */Webware/* set noexpandtab +autocmd BufLeave */Webware/* set expandtab+
Converting python files from tabs to spaces is a snap.
+> cd ~/dev/Webware +> for file in `find . -name "*.py"` +do + sed -e "s/^V<tab>/ /g" $file > $file.new # hit ctrl-v and the tab key after the first slash + mv $file.new $file +done+
--VictorNg April 15, 2004
+The GNU Coreutils contains the utilties expand and unexpand convert tabs to spaces and vice-versa. A tab is considered to align at specific columns, by default every eight columns or four columns with option -t4, so the specific number of spaces that correspond to a tab depends on where those spaces or tab occur. Unless you specify the -a option, unexpand will only entab the initial whitespace (which goes along with the Webware styleguides).
+--ChrisZwerschke July 26, 2005
+The Editor/Mini-IDE "DrPython" supports converting from tabs to spaces and vice versa via the menu entries "Edit - Whitespace - Set indentation to tabs..." and "Edit - Whitespace - Set indentation to spaces..."
+--ChrisZwerschke July 26, 2005
+This page is about accepting, storing and processing credit cards.
+A brief, high level overview of accepting payments on-line, with a focus on credit cards is at http://selfpromotion.com/credit.t
+-- ChuckEsterbrook - 18 Mar 2002
+This information comes courtesy of Jeff Johnson:
+For starters, you'll likely store them in a SQL database. You'll want +to encrypt them for safekeeping, but might also choose to store the +last 4 digits as plain text so that customer service reps can tell a +customer which card they used (without seeing the whole number).
+You can encrypt them using either M2Crypto or the Python rotor +library.
+The rotor module implements an encryption algorithm used in the second +world war. Beware that data encrypted with this algorithm are easily +cracked!
+--AlbertBrandl
+Here's an interesting link about credit card handling, including the +pitfalls of not retaining card information: +http://www.arsdigita.com/books/panda/ecommerce#credit_cards
+-- PaulBoddie - 06 Mar 2002
+Here's what Jeff Johnson said:
+I store them encrypted using the rotor library, I might use M2Crypto if I +were to do it again but so far rotor is fine. I also store the last 4 +digits as plain text so CSRs can tell the customer which card they used +without seeing the whole number. Then, I store the hash so we can search +the database and compare numbers without passing the actual number. Here's +my code, altered a little for security reasons:
+def decryptCreditCard(self,number):
+ r = rotor.newrotor(???,???)
+ number = binascii.a2b_hex(number)
+ number = r.decrypt(number)
+ number = re.sub(r"\D","",number)
+ return number
+
+def encryptCreditCard(self,number):
+ number = re.sub(r"\D","",number)
+ r = rotor.newrotor(???,???)
+ number = r.encrypt(number)
+ number = binascii.b2a_hex(number)
+ return number
+
+def creditCardShaHex(self,number):
+ number = re.sub(r"\D","",number)
+ return binascii.b2a_hex(sha.new(number).digest())
+
+def creditCardFromNumber(self,number):
+ number = re.sub(r"\D","",number)
+ numberShaHex = self.creditCardShaHex(number)
+ sql = " select creditCardID,number,expiration,numberShaHex,numberPart from CreditCard where numberShaHex = '%s' " % numberShaHex
+ rs = self.recordset("DEG",sql)
+ if rs:
+ return rs[0]
+ else:
+ return None
+
+def creditCardFromID(self,creditCardID):
+ sql = " select creditCardID,number,expiration,numberShaHex,numberPart from CreditCard where creditCardID = %s " % creditCardID
+ rs = self.recordset("DEG",sql)
+ if rs:
+ return rs[0]
+ else:
+ return None
+
+def insertCreditCard(self,number,expiration):
+ # Get rid of non-digits (\D).
+ number = re.sub(r"\D","",number)
+ expiration = re.sub(r"\D","",expiration)
+
+ # Encrypt the number before storing it.
+ numberRotor = self.encryptCreditCard(number,expiration)
+ # To find a credit card in the database, get the sha hex value, then query the database.
+ numberShaHex = self.creditCardShaHex(number)
+ # If a customer wants to know which card they used, read the last 4 digits back to them.
+ numberPart = number[-4:]
+
+ sql = """ select nextval('CreditCardSeq') as creditCardID """
+ rs = self.recordset("DEG",sql)
+ creditCardID = rs[0].creditCardID
+
+ sql = """
+ insert into CreditCard
+ (creditCardID,number,expiration,numberShaHex,numberPart)
+ values
+ (%(creditCardID)d,'%(numberRotor)s','%(expiration)s','%(numberShaHex)s','%(numberPart)s')
+ """ % locals()
+ rs = self.recordset("DEG",sql)
+ return creditCardID
+You'll need SSL for encryption. You can run Apache 1.3.x + mod_ssl and +get SSL certs from a variety of +companies. http://google.com/search?q=buy+ssl+certificates
+You can use stunnel to talk SSL to the credit card company.
+-- ChuckEsterbrook - 04 Mar 2002
+Eventually, you are going to need persistent objects, or just some way +to store and retrieve data. The approach you use depends on many +factors, such as:
+Do you have a lot of data to store?
Must you work with an existing database schema, or can you start from scratch with a new schema?
Do you need/want to have a traditional relational model so that you or your users can use standard report generating tools?
Do you need close control over the database schema for purposes of optimization?
If you must use an RDBMS, does it have object-relational features (e.g., inheritance) like say, PostgreSQL?
Do you need support for transactions to commit changes to one or more objects/data fields atomically?
Do you care about ACID compliance (because your data and/or transactions are mission critical)?
Do you care about closed source vs. open source?
Must you support ad-hoc online queries, report generation, hot database backups, and heavy multi-user or transaction intensive use?
How much do you want to spend?
The following is a list of possible solutions:
+Use an object-oriented database or object store like ZODB
Use an RDBMS and the Webware MiddleKit object-relational mapper
Use an RDBMS and some other object-relational mapper. Possibilities include: +* PyDO +* Database Objects (dbObj) +* SQLObject +* Modeling
Forget about object-relational mapping--use the Python DB API and an RDBMS directly
Use DBUtils on top of the Python DB API
Use Python's pickle and shelve modules
Roll your own system with a flat file
dbObj
Python's pickle and shelve modules
Informix (proprietary)
InterBase (open source)
MySQL (open source)
Oracle (proprietary)
PostgreSQL (open source)
SAP DB (now open source, based on ADABAS code)
SQL Server (proprietary)
Sybase (proprietary)
Database Debunkings is a great place to look for intelligent +discussion about database issues by people like C.J. Date and Fabian +Pascal.
searchDatabase.com seems to be another great site to start +exploring the literature on databases.
When will they ever learn is a critique (by Fabian Pascal) of an +exchange on whether MySQL and Innobase are DBMSs, or even +relational. C.J. Date makes an appearance, and you get to hear the +horses speak directly.
Linux RDBMS Library Compilation of free readings on Linux +relational databases.
What exactly is a relational database? C.J. Date explains in A +Closer Look at Relational Database. This site requires free +registration.
Fabian Pascal explains why SQL sucks and why all SQL DBMS violate +important relational features, some more than others in Little +Relationship to Relational.
Think OODBMS are the bee's-knees? Better read this first.
-- EdmundLian - 30 Dec 2001
+DBUtils is a suite of tools providing solid, persistent and pooled connections +to a database that can be used in all kinds of multi-threaded environments +like Webware for Python or other web application servers. The suite supports +DB-API 2 compliant database interfaces and the classic PyGreSQL interface.
+The current version is available for download at
+ +You can read the User's Guide online. The documentation is also contained in the download package.
+Here are some guidelines for Webware Developers:
+If your change is non-backward-compatible or involves design +considerations, please discuss it on the webware-devel list before +checking it in (and preferably before implementing it!). Your ideas +are probably good, but someone else on the list may come up with +better ones!
+Following Python's development model, Webware also has a BDFL. Chuck +Esterbrook is Webware's BDFL. As such, he has final say over Webware +design issues and if he makes a pronouncement, please obey it.
+Jay and Geoff can also make pronouncements if Chuck isn't available or +if they are better qualified to decide on whatever issue is at hand. +But pronouncements from Jay or Geoff are overruled by a pronouncement +from the BDFL.
+Follow the Webware Style Guidelines. +http://www.webwareforpython.org/Docs/StyleGuidelines.html
+Please test before checking in changes. If the component you are +modifying has a test suite, please add a test case to the test suite +if appropriate.
+Please update the Release Notes. If a new feature has been added, +please update the User's Guide. If a new setting has been added, +please update the Configuration Guide.
+If you agree to abide by the rules listed above and you want SVN write +access, send an email to Chuck Esterbrook and Geoff Talvola. You +should let them know what it is you plan to do with SVN -- fix bugs, +improve the docs, add new features, write a regression test suite, or +whatever. Also, if you can show evidence of one or more of these:
+Previous history of writing quality Webware patches
Previous history of writing quality 3rd-party extensions to Webware
Previous history of writing quality open-source Python code
Or any other evidence that you'll be a good addition to the Webware team
Then Chuck or Geoff will probably give you write access.
+-- GeoffTalvola - 06 Jun 2002
+There are two aspects to DirectoryStructure: client-side (URI) and +server-side (file-system, database, etc.).
+This article by Tim Berners-Lee +http://www.w3.org/Provider/Style/URI.html is a great start if you're +trying to decide on a URI directory structure for your site (thanks to +IanBicking and KendallClark for posting about it)!
+-- TavisRudd - 16 Nov 2001
+At 10:39 AM 10/27/2001 +0200, Georg Balmer wrote: +>I have 2 basic questions +> +>--[1]-------------------------------------------- +> +>How do you layout the directory structure ? +[snip] +>or case B: +> +>someDirectory/Webware/WebKit/ +> ... +> +>someOtherDirectory/appOne/pages/ +>someOtherDirectory/appOne/lib/+
Case B. Mingling your projects with Webware is a bad idea. It makes it +harder to upgrade Webware and confuses people into thinking they have +to modify Webware to make Webware apps.
+One notable exception is when you bake your own plug-ins. Those can be +convenient to drop into Webware/ because then they get picked up +automatically. However, there are 2 settings related to this in +WebKit/Configs/AppServer.config which allows you to put your +plug-ins outside of Webware.
+Just for clarification: If you are building a Webware site, you are +probably NOT creating a plug-in.
+---
+I recommend using MakeAppWorkDir.py to create a working directory +for your application separate from your Webware directory.
+-- GeoffTalvola - 29 Oct 2001
+The term "distutils" refers to the "Python Distribution Utilities". +Since their introduction in 2000 they have become the standard way to +package, distribute and install Python modules and applications.
+See http://python.sourceforge.net/devel-docs/dist/dist.html for more +information.
+The current version of Webware does not use distutils. The transition +to a distutils architecture will hopefully be made by Webware 0.8.
+users don't need to maintain a local copy of all the Webware modules.
the core modules can be used easily by other frameworks
it can be packaged for Debian and other OS distros.
installs on Windows now make use of the GUI installer.
distutils offers many advanced packaging facilities!
distutils is the Pythonic way to do installs.
-- TavisRudd - 29 Oct 2001
+A style of Wiki writing that presents a synopsis, or synthesis, of a +discussion. The synopsis is owned by all of the participants of that +discussion, although it might be moderated. See +http://www.usemod.com/cgi-bin/mb.pl?DocumentMode for a fuller +explanation. It is complemented by ThreadMode, which is better for +freeform discussions.
+-- TavisRudd - 23 Nov 2001
+jjw_JoWQH)XictLl6)>Hp(=u zoVHD%l6pL5eY>x<+yiK7D&?T_V>SB(<$f=*B4XoD1|`b$n43!v{l0Jq%cq!rn0N4h zLJMNEpmuwGXCrA8zmsI-(`KyrmDrYGmHFVoyHE0Yy-=1hzrKtoF@6;#?y3ZRx2g-y zU+9tH1H=<+!=^sjV$0SstHUOhBH0;oSuNWH+P7eO1`vI+2jHuO?xG+BG{=<2<8UpM z;|H3SwW85{$;|E^eaxrhNwG(!BQ!_e80QLGg>;Sv1v|bq3cvS_Wwn&kJmF63rI@#0 zpdZki>4SR@ZiH>&LY-7?2BddXmc-YiPwDL1D$t~vbfy((O zeLFbp604-wlC&*&%v=jmhasi*yO42VpBzJn^baRz3ljX$h3s0~sT%8JTQD}Rll&5C zmd9U;*O{%v8u9XMI;$N1lS7ayB*^_@Y78pk?E!zKu!pR*h@1m)FOk(~d 3c4fn6vxtX-UIbHJ!Q^y{6@S09faeyE*uFq_Fn-e`} z*ziKf;E`+M2tlWOY6ipv+nUrO0TLT^u1RL>=$%BAgO5f!&E3IePe#G1BRyQCSp2MD zBGrZ}PkA4O2-1sL34H`JCqht_zH!HqL+G&6N-tD+7@U-r+#JkW*;B&=;`0ja+1CNR z6^{|%udG}_ 2<(L)kMYZ zB~2mhta&axfUK1+1{LO~4M2vbu>JnA92cW2G))fiJ`L=oXYn>2jqv7}0<*G?&>f4p z-;u2}8l{7TTs>@q2sUG~oci6r3RzgeKScIM-v-aA^(I-Z+seC!5M_j=ZE`5kZO_fU z FbP{OO5BMg)`r;hqWuq8@Xr_mcnMm+BtaWF)TUq%NWbv74TTlY?`E-Y#3E#_8SGOgrO5 z_pAvAV>ae0nh%=<@wO-R*k+F}y4?u+n%0NFrQ{P^DQr>g6&T^bREsniSwf&m8?}g} z8>VVDB45YRD7wuNlV}~<8A*Zly%6|Y3eJ}olRdnz(YTsjHP?zXc$q4BrPg~<-LSqZ zXsX{KJy9}Upf@stZk$(Rk?0u&l@L`Ya0A?snz7g9q$uW%w~e!$zN|I%Us?Z;CZXFf z{;kyiZ{L6PAk_bVcYkYb|NnaSKjl?vwEkoSw1<~2h4QfCkEQ%K9VWH4$2uQWi=rdv z*9$7B4zIBA^Bj(=XrHE&U1LpbZPS)8bi>#!$X`*rE1E-E%ml3In_L#v)ZSyEz~VXN zNdQ2{9AD0UATnkUOM%|oIh<`CgHAR86eKJ5)H1e*a(srWBIMpC`8B$5%N?`i?q^-5 ziN2x(be1KU%MooJ&ECnO)ruV`#G|Ul@$$}~qTD;3W~aqW5xReRS{ly-6g@$dVt$ak zL81IP9I_F&(0><+pS}4OQzuYoTI}lCF4$Ks0&wLDD2fS!r}isUvWhb36s(AEsLpue zBtoD&KF8!poO_U9#A(=3QNp^0*{7)-ixlSq+~*$aqeB3*J;QwOrBsRBZ3d`UlyeuL zYS&!(wVKFA@;3!UE@-8LB_@Tnvlmz%*!ILd_YJ~p1veV+Nq0%1dRA4PxEXPAVH@(~ zly)>5=_VNcc1lsH&U2UDajhRC>_V{zm>5A(xu{Cx0vdHeg rvnMGt%9k7n= zEOd>qses0tOq3D+cu+&h))C+;iATa8PT6+2T6sd&QvYKhc^h8$skdJbL-|~f>}O%= z(7Ea#9{)~LLZL;8*4~^VDw}xQ?`>0u{&=t(XBiaps_D()c%-8^?T{w=THgc*l4j^{ zpkxS$pH^D%Bv&@!)yGM~Yn<2nG!CHja3>~AV69Lqa6>^Jet(e^@4=Np)`0F#Gco`` z6Bf%FCSPw^a9$_Q%Gwl=nw?}3J>BXZU?AcS7!UoX?FepGCp#~$W74V-6;GW1l$ICS zJld*JYTqqb@z4zW2A%Y^ZQLF+B9@z-cM}cDb3EJfsj;h?(BbgNfy3}mKm34K=3O6~ z+tY1mOjXG3??lYsUOy}AIV$@L;N|`#KIil6v3=Xfoe&+F(Hplc5bW_0EK<+THh{QO zM^r1;T9K-qHu+v!>cs)NRMc eD13 ;BSO6dVz_=bH~bvux5ol zpf%AQ6Vv_miheR28WZI*{Azsq1N%h=q>|Fa)R{LJ+LGZ_d0D#^JuRomJx2H!UgmIt zLomfutK@7OYTaL!({m}!$4-7s*)ED9$=}$9iz}sY*+JaA0K0w|99fzUV?Wm7#0Df8 z!S@){g@RBDg#F{)%h_G|kbW-#pUM%4!XnYdpvcMZCr `%-K4is_03sn8(<j9W-M5vP-;t4T4vf{*Y%gI{F@ zOXD#!2HK$)AD)u?d^C=WOY}rRJ pk*m82$Wa{{TpgeYwB) z?r(eVMz42Y?WKXSi4-csM$xx#-eC*rzuik48gi=guS5FSM0Xw?{`+l`?xgUqRg#3C z5jy!ep99B$$4#$~RqkRH5Afxwhm2ACoGuV9dvlDsG=h@))Gs@2Gl~|%^@ME@9MgDd zW*|*9O$>Z!j?0sn*NXC%%;0>wr~_9f!;KD%Ts@79!%7Ad&O3v9HBO{ZKUGc_MU#Tk zR1AL!%;b=fj;&V8asWI9vzLQbDj4^Y@!O!W_WJ>*dWiKGT(R`eY4#tpa@yko_Cv-3 z$~wA-yZ&Id54{Q5TTSqy#7!clR`C~ x3*z3lfvL)SgQvTm@u3mA$>?q~`=3+F~xgl-5&4BCN5wtW9Vm`>o@6`$*J!#;D7F z3cUsV>_-jSzAaWYv)UH!3i}hk;gmUKnepE^c&qtxik-lvbL!dmZxs+~HtjPPks?yo z92%Ttr{&C$t~`mPReX@XXzk035!ygv!of1{28+onJCl)7XV}xoqdmW)J7Ug*QXnk9 zkUR&JnG03$$$2>)yYx03?Z1<3R47mTIAvr`F|*^+#*u5kVDH=%%cSC0YgR<p}G;E|FX~fwi`0xE943H?T_TOqr8~E#O z2%F5wlxqqy0H*7}^-#(VlAZ$Spx>faa_OO3JBjF5nn#`^>WH0&o^#8nCQps8rC7!# zU=gi`NZti7gJc8#k9^HWogs;rK@BYA*Z{yRh= ~G3TGTcpL>%Q #@IAaOf hB44ahB Gd4%|{tt4C@)tAzDQ z_o>+w+pi>JV&6B2bALOlluuI5=&E9Tx$aoi_PWCfg+fg&;Zyi+xiDu+rjP03hQ~Ol zCyz;@eX>zMzRSNJ-{tp|(iE?=z)$cWR%;2I8?f- MnJjQ{U3ud)L%qzjcCqMTOi@5t^+O62a1cssAS@1H2sv&=vV#zI(78=70L` z;e&^3|Ie@H|Jle989KlXlEy__oZRsy5x~B?F!#&lYKX7wUccKE~j88%y> zkSU#=ks>c?S}vp-y*y2tU-TJs85mtyC5S%@=a^|SFm`mF<8X{>e9`=ls2~te+pB^i zNa5@u@T0hhlP@mjnBtA9(E!AI?Sdpb%I3(4qy6yz6@H*Avw${|fVRr(t$9HGT)VMG zc&H32lY;${epfDScD(>efI=`8;07e^p@SX=FOaLtwZcw6ZZ548Oh8+b_u%X^Dr}6p zr6ZB7>6k>yQu4EUP@G*b6b(3aKGoH^hHsE<*jUz`8A7;uIFYe;%CDPZ+O^OqIR*e- zE>2G|q`k2sW+wm}0Yy+TMlqo$@cMKCa}R6{EPSDr@?9}5D?mcvT&XH0BTgf!VMR@~ z94C4yhTaobGM=HhZ$_L72K n~bd z%&q{9Y}!=XL7bc0?0PCJh$!*JQ*zs_3ww#hb5fIo=vNhaO|m5U(DD##P5M5PC62RW zs&t*6!)q+Rf(#w)y598gg-Yw1wp#B}kT`UuGi+b}R1B;^2?@>v5*gQg0crM$rXqPQ z`o6lE=0PebVgNmIxjG~6vX{nBsmuZ7{h?pohBw0Cb@${lbi+2WoqnK^w4_UN<+Quj z{YtrWk>JRY;OMy*zH4*1COu502ou(sM4+rBj^JIQw=AXbMR#(*o_@Q2RVUOi{A62e zG@pJ06X+Yym I9=Cv{UkT~w2=Js}%xZ>JkD8Nr`qF%${6$?fU zJf0s4zuBnqe bzO{`GklyRQj- z|I(uWrIC}r4tn8);9%0q2KtDqT^D8Sk_s4a)G~*kic85Y(xt`e%!uum^q46hw*YO`o=z K08PGmOiZNaE?vI`KSb@h<
#m+ z!u+2P?r*R4KVRbkF(Du4m-*)3%(aeN*}V?=cqyHa{fL)@?k_Gba=b|MX_&}R<>v0- z-JhG0%RkKp0>Oo!y9*Fks-5ITK23fsPtGy0lHY9>7r;{OBxOE5{^4XcnN=X+jVWlz z+%dV6yn1oac~;aXRY~s9VosaqC+EnCNMf5vd@l|)t&`@(GPz31=UxBBnky4l%Ki=) zm?{c{dwa k_Nu(CW@lA? zae++d%Y1saz{Q2~e5I9F^k6nGPw*Rs!cGew`mev Ux@AKoL 5^uU+ zU+D7xX8)TL;CB01vHu?c1JKz2>-%56&U1&uO=fJm;Cx|pZADc~3cRhf=fVo)jtX-- zocy v+(|Nb|a&LEk&*Xy(QoIq)5gjq!NA#vO#T!*Z+Oxo0YO)hd z$mLa(KR|BB%<6T={K!sA)c=@2dtFW#-W?>}U#1w*Go@xJ;)gt%NtM*?cT9`*bq$lH zY$R>~6xU1FkfxZXW?s15RNWJ+Q>eSid2#(|R*gI8j&WUQ28xf9bUWM5?x)e&jma*> z-9J- ffxBXD~|WCHrP|Co& +8s?*6n`i+=9;c%XPiCqvKt!+l5&g z2&nBneBWKJ&Fx10db-Q?x-FGfXn0#{-AvcpQhB-7x24kW)&H()<_k2z@g@(=+nlT$ z!>+P;bp3B5vV07?5zB`y2^4$Sy@7$nZ5@X7unT~ Z5 z{loTOwEy3K^ytx=|6kjG*Y@AF{daBuT|et*{j8t$vwqgk`dL5gXZ@_7^|OA~&-z(E U>u3F}pD%g-8_arqa{%xF0E~`k_y7O^ literal 0 HcmV?d00001 diff --git a/downloads/LoginKit-0.1.tar.gz b/downloads/LoginKit-0.1.tar.gz new file mode 100644 index 0000000000000000000000000000000000000000..2b23eb7afb65b545b79dd10c0df650b411787f8a GIT binary patch literal 13688 zcmb7JQ;#i-78~2PZQDF!oUv`&wr$TD+qP}nwz=>37w%hMnlw$CwbBwsLqR!cV2Oi( z%G#S-+R0eD&@(YGGq@N!0bT2QyKiwc&h34oML7FNwZPDSc&;{d%b~uFnkQGs-?%8) zXB{b%kU7dF>I6j 4NUKc55PUMV23{l4t_hXUD@)# zvnXKZ1^4iOZ}G10F#{^kgzLK2cJ6L(USAOiT)elsAbAnTcZ2Khr!{WPL-?@d8xwwZ zbL>~X1TUTzbNpXSue9d?w{CZSzkLVa`9Ak$mSP*LoLPXL;Nab#ZvgNqKvUu;r`M3} zX>mmN)ZgE|&GNSmv9rtT*WDYjb8BaZVcP%gKk_^4WD<4alJ99eHFTL}(utXJxa<$s zuUXA1(<3%%7PStk_E-H1$vv2h7>UV0=g)l2jD>zvHk<)%lKhy{COQh;+@1WdwG{KK z1imL@vttge`^t|fo8kls;0sir3)6WP(~hlI52r+Gyhxu~*5KK(-xMDFMRuIz%wrG! zY1c<$6K>}lC)+ACf$ke>Q#hC|gvD?hmP1LQS_5IKx^d#{e_HAlG&sy!HF(ZL?<#9X zJZGr$wKM0;S$&BsU9?%OQ#k|Av&nRdrph0_nwiNJgc6lNBaBl{eH>oP%h@dW;BDYR zK-pJF_2t0}TwG 1Y7H;-m; z|3CsJ-E~L%^D@I*$%DJ)meML6VFw?y(F?jWu`7F B0`f@f zuOtjcP?-X-<~(5dzcKOvrQM^+cuWm|JY>=tlC`RF6mco^i1ac(rZ;(5a&^a1UCMS~ zRf?E@gJbxT1Iu*iGRi+XG%IfCKiPMpXXeza!O{|jGHGcz=GORR* *4;4c zGDh6A?OTdABsfL36|(lJ x?(?`R#SKKQOA_LXXu~@xJ zB91LuMhs#in6jsP2|wK8gA3s4v2%ZFmw-)@G}#|xmi1Cy`5o79Zwb}Fnh(s^?3s*% zrV}?|BA`%8df_C<-G4$=pF7~XJ(Gf=W19PJ*6YxZ(2Aw->}gk9dBYEvy3qq0JN7>W zmdVcmB$2nkfhRRoF?-XOzjG2DDtY;^jZbF{lda91bq)dbo0^L&U%Jj4Wn%)x8k(gM zF^+K?eSmm~(IrRNw1&Z9{F1bxU8#dGCB-LYBS;AVSF=ZaAFvxrp+P9bfcpbg9MNTt z3>XWHgdZo~#Y^-8LVOn4kBYpLOo5Ist#r#4e|&Wg^N?PAhY6b!i|GY=jj=32Wiy_E z6!C2b2m{N=xH^spHDLM4=rgRNFBGJb7|Y%kz!a?qDVP{d+Y4VX<^))m(`G{|rq@f~ zl|r&2I!raD8~73u&F#aIv*G#)9?zXD#@;YsM7s)(JwPCbYN2QTZR#yhMT}gDA%Jy` zW6+f?71yXJ7Q31czmzoszEez&$RKl_AfM)FzQf1oM*VqrcD%peR;~rXn{g^G)UYZt z{7tdzg*Kd+%I{^AqPt+)GQQxCM&6EXofV|9%+6)0KKJ^qosM*XV8oBQ6!TfAwx$no)?cLj7{)$OX_m~n zr*3k!19n^I!9`4?G7rR1n?dQH{ojtJ@4m-7hF{u~zBXTjDZs1So8E6<*7x4@aPc$n zV^|4-BHMz752Lp~@`vEm;G3WPT`7p#1i;RID-965^IvY_TYqKr+NUz@?@lT0`^Z>X z9`;Br?!!@Wkn;Z(k&62W!1#K?Uo9lu5O5Ts;=%10#tR}x3$xH z(%0qB2+%+Kej}*dI|4*~=bK7NH}Qq^?CWv@uJ!>v{IGyK!spljL|F4d1ujeo%k?Z- z^^{?Qs=!y+wTXJ26K`07Pb7Sy_b ZfzQ@+PBdBUv<`g25wl4lq6D&k(R zQI1$pj~PZ~Y2q-ZhmDX^Bk#2GwE*_VfF`=Ht1SSc&DY-V?Ca0Rp1S9w4e>l<_{+u1 zJ54cNrs)vKn#_US0-|Wv>2XS#QyJ9IZkcbIsoNU$Jx^ZN)26jfE6uFdU;^Ves8||o zUJ$k`z35hI^)=(FNQOVo(6q#YB^_GiRoMmjj8MnU7Pa~$;M^JStBxA5wFSxB`eW~Z zw@(1@PnDcR%zmE)Fe8?!_|6(+%9n @YqJ=Bq2TObikA#Q`f2&dg-MF_{mhA~L2*Rse!? z>~x^~dMK<$F8?Gk)F@lp61eZY*PpYjIDJ>tf9MBA7|Dr|zi 6Lr&PH{$*F&&o zUWQMYqrVOCNMcp-OyW~~RccR$E?V3QUe?%5+g`0lEuvYa7^>gmfggAeQZMaMZLaUf zCEcHDc)=&hDHWNHfLEAV%lgWY`nqtix*4ND0LQ8pOr}!#s17@&n4;29TWy%AQf?MM zzq^QGT&|0DnFuROqzGKz LyTcDew+ KbRVRx|P3;xz_X=WO6 LJJ_F_*clHmb&aGQyD *Vr-5fF{ zEdAm)&KQ+SZjIMuF0BN|B(QCjmI<&@F%j`)bJHZKTydZNOlNU}If^izq~6M-M4ZoY zDlyQqhZl8cgTmsN1L$QAQ{%4;8CvS{`!ghs?U)RulN!)c+Hy^Ct>=c-Ql2`GYNXm_ zA5*uq+I~g`{hsP!nr{sPQRlaoBZ1oAi-yvwTN^3=Eig1PWs_^D@p(wI9^jGL8?CJ> z>Y=HWHP>i)^-<*lfz9^12&Id 5}*krN5nRTM!ERbUwUJx}z?Mq?FFi!uNF5a8t`381QPzA>cyO;wjj zH9c^@KDf%22IY$fMifjl)l;5hjampFKj3-oq{f#^MH_>`p%xen=OsmDv3zVab;nEd zET;Pzk*HJ+7jcP|>fc%BYxy-Oi8{;cOsMicU2PT||DMwM;D8dp?Y-LOCOCD4Z>;9d zyrwJ)6|y~eAosu)?JMyOYukExX!a)z5zf2Dc6?d;{{2xocxxe>R2x%(&AL;hkr=P& zLRGjcPgQl0v;+-;|GX&p3JK01XR#%&rK!Y}Sc-!k)FdaDf0dqypkuifd4X~GUxwXy zC^XzusH@#0gH(*6|8mya$BMYKl$=F;bx48mNh_7u{c(&9Z1*eg$S*|`ake*NcG0ed z{ Rh7e;i?32(OcNb^@xOEA(B+d~IpKW6z+-UEt8BD89muAJ z#Fk5?A{*UqqZGB=K_#ya{p-t^Vw@!EN5P5C6J%p7qTY(It7saQFR_7}mw<~u(ah*f z#TT4Y9uj;}vPaLQ(~KO7!yfOcm;4|X6`4?0nUm&Bo!;~~v|4vOv7@BbSdUKPUX}dx zwG>r^?%O0yy(#ZM98Fs3%7zG#t<#=) ;i;?jOE}2|!O1_KKW*&I*?S;Od^OQ8B-Ybmce>>oz z0BsCq7sl1Sv*%>#+p+Mh Wgu#pCiCMk`-zVe zxtb+rmQS>zE189BTz`0R{h&HtGOnHp`sMip6T2ah`t$*sCf1bm%Gi|Ipaz#@K&%rU zqXAU=+3q<%2k-rN;Fxa`DWzI++|=kgRBMw!Kptu59{(WwDLtHi9Z?uJKs~UiW|H6N zFsq4A3G#0#jRl`At3qQ4-c< G P3C uUq0S7A ?H9=P=HQJP4>T;4_s|$SoWvYrtmOf3;-oDNaYFA$9G_88umL@;0rK|P^ zJ@^{IvfLYm3Snt1ZC}7g&YL%F zTj6)oO<(*UrypB2UGD(Z+V!uX2f-e@I*MQWyIsH??mGZsBsFAGiZMgZa1EW@Z~pve zDw;h_nISY;Hl)Y({U$1wQ($t(ckKB?bzm&D3ng}L@&@q;Vi=l%PIa52AO;!^LvZrl zkwHO$t6(3~2U-vDJ!*Uy`34YHKlTp4*0eW_5m;m>>oL7gtPFAz W^fXI8X&b#RqqtRlOVT)q&$`>kWOXnFCcR@> zgou3~L{Phbu-iJhuayQ8Mwb*#CFZ;*1guThdEM*tJ2jt1B}DdHf;^4h9Q@ H{LUL12;zK21XHW AqPul?NQuP<@$f6U)^?Wp@IO8 77%6Io09$E@$E}`4a`(qof zgHm{A80a@Th;s#-h7LYU3pHO?cS(F?)b2t~(Bv@9=YbcWa szV&qSKx6%9p4Enm%8vr|i->o&zc>~ZTh96g?Rs@WIz4L^8+z+hlln4Xd zx)mP8vE-a^Jt)CT&8SjdY^=bsgk#D4P|?G=N9fTIsHzl7I4AnFMMJJ2F_*>BWNHdL zAkEsX4?#uN%l)dA&J6hQ6lS X?tS-D~;NaMVf?;(J2}#`GHF&%oT+OPdk`0f; z9%!W7 VtH#ch;E^mj;(ZK9@I)eqU9HGSD( z#M3FUR%&f6Y3kC?re7;NtJ2lO+0AbL) _ zIRDVZ6J|@MX_Q%0z`VDRVtt^jH}&o5T0M&^5L#A(Cq{U5r^4D`%)F;MjX#EKYoFhT z5@P$ qoO{|O<_{7AYZUFk#Qh@X~p2YMeop9iq3R%bsTGTk#s49ZN zmg9X3)rR6pthlt&x 5fh1#&aT0p-0b=U@1 zVclYys7K|sgMU~@8ZC+~E4sf4Ew$eV)isiqv75TmPasFG#?ZT0j44yAd2bK&c(MqV z5#9gj1xFpfFzJz-^D%^=jZrO+;H8@+#5%qctmiZdk|dIF$g*;elSG{4NF*XjuB*G& zx3Bwrn6zz?vV`e`u!b1x2#s)SS^Pp_J_Bbj4Mz0HG~T-tH{R-83^c0M%da%s0EH$p zluxcq5L;;ZZxR=LG=h5>d>m2p47|V!9akVS_)tMc-d`qk;i)*tXTs)@JIaPH_NW=r zAhwkH8RBWGR2g5bx+`fH`a*zI3jx==E(~JogCfP628Y)J#IN$+S6Lv(Bb93<2-xjx z8vE>>iVJAR$D43!PwMLp1zp#+r6v&JC{cD{BQBI~d8mHcVfvr>H@LO~{9zr-Jz(VC z?F$aD_a)CNCUDMkX@Ocm(G86ACw*ykz&Z7D_ In24xl96PB`kB8Ate|nt>`((Zb<2)d?%w|@6)d{@# zPyaY%<{=^L!YoU9d$1h*fQUgXg8c14b@s+|mXg+pR}rP0V@R?l3h2D&7C8hid50Tf z&BuOjS?GA&uHY}pEnb__N-Yd1Je#-(k+vgr>w(N`Lpws!x$+8=Wdm}YPO_9`tg;}1 zC_Vi9p}pr)OTX@>x<}V`@W*;{y`wPvQf?4XDR{N9`0a*u>0RT!he872J>qEOd0S{m z!Tymfp8xm|Y+8EgtEuzH{;6wuvFFHFxzAt2{a#~?1dO8E0rfEB9be|To#1x^9=TJD z1wv@0Odsk>vz>71;nW}+Qkjgtbd}mu`aw!y7Cf#j1irRFKM&TnBj_8LbQGW;7v*o7 zpFRHoJYGV@O~H<;IA=5r;%OE+lLv}rAO|bYL$rmU`EI?Ov2yV2wOu^Rl?VOHUEBuO zz0kR~^R tY6|yCAz+hrB;+LEphkmIwu$#!SyUMr&8kI{`L{xPab@VU)`V z3Lsro#SvK~#9`9sG6Mq|=`d2M$-z#?d;gK}=qSH2pqTAo)%Mf j&d-Lazx`q7mME^dUp^O8pjp5>6;m-U3$b)pYnD$_J&N={ysUjft*9X|+3--`W3Jn24seOOl_UjG79_ z7O&G48m`)-5&t23`IyLSr+8}Yd`p~YDR9dF@QJ7_6!SEM`E4kGfseIac4(Fb^T!nK z8by4A+TeGDP)?#$6CUy?n!dCnr}yWAEh4#(o;<)z >NwqHRv&XR@47X!Y)MnO zK$f~9PZ2RFUiw11!Y4wQY*M|&Y8f!?>^R)tT2RXPsaz` EV6FAr9reR4O++p zGHADALnJ^~9FM^~-~miqYuOQ{zotVbkyEWY6V)=q^!>+_6t!w5MbSmq_jzOkKli0p zQgf&0+=kulO3amgn;$v7_EQvlWK8F!%lS0}j onk7yg{h-{HxLWXPP*Kj3}ELcJ9KXc=@2ZAojo*RIx zoixXvoF*~grI;G<7lzVQbv)2kRTi^==ILMv8#%r6Qnc_Q-s@b7k_N_AP3^DCgj0z~ zdz58{cq@$rLmZ#;Y6G#vtzZp)a6Z8JL!*lo)*=#6SEkVC_~UOUu%l!DE~uXXIBI{Z zZNG9tcJ{K1i=Tkb@;CuC`8lT1jx3k3^8Ic)dB=-+B*89Vz>?9KAdfu;L?spat;dy| zRpR*#HH0M+mP(h%Z?E+O_h@5qz#%EtV+; a^B`$BDMvhz);p()bi^|i#)Se61ff+Dw}9JV zSvdc2MkV1B(z=a3I4X+e|7n>l&?nc2bY)Du6cFG@fr^W-h>51lQ%GWX>SVz|Y=j$l zhSTwy#7W%NU)5TZWmtVMx<^&H?iQPS_*Y)B(k!L!7iMPJ?t(T4PuWtE@@5l_a=}eE zMrCG(mmZsjsq@;9L}vurf$K&d8rfZ0s7{0mZ;2Mubp2Pla)Xa`8wCp}^%d>+WO&WY zbNocc34TKE2t>U+4}r!u{Q$&Y`ac&lH=yQFu{jHj3#}M3Q*}|Z3m1ra-rl*k_k4d| ze{Ro*25$X4e6~|*USU$Q>+^WLArqu-T;kdP#L22ESm^dTIoE(7#_}CuFhR`0MfF2+ zq0LJ{P849uvQj1@H7pO<=qZ}sFNr;7MnC>MFwZf~@Dmpr8d-wIHwk-5TJfj+#dAT+ zuy7C#lZT3)d>Snfu*}I3V`V3~W2L%Bb#nQe0TTwEbTi5`I5xHt9E}isbfibrZe7tc zYFSJ^OZB(#a(GDI(SK=hU+nC>Y(p#1OPu;_y3@CQ)NE4-1e1N{h<82TQb`D&?Y29p zoxg!$vl%y%Vp0=}U)Y3paQnsdcDZ? M+G&n*E0ewzZMdG}ydo zrPEo9jP;6d&^3(;cDt4X@1UbYnpD%Sn{1_*%BPh^_rgspVFOy^5;L>5gM9J~Jg_^T z{A4kJzW*vPN6D-n>u))(fTpw;|?%6sbf$f#i6u(hb=fEpR6ebo1STJk69XULpG)TXM@RH`JxH zno^9Dxy9@3Gel*`+Y|JxWd&o*Ekgm58 Fn&%Ft#J7T*M*C!^-V?R;{P{!3hq7bpavxeKM{9nSveIY3s=O b_-ftCA-Og7m?Y;`~?B(ERr}?ftG5EYp($cK#OXNvAA{GchQw;Zs9? zYTsjF(t8ZU@$MpPq93=q1R8X#eNDER*b?Q1HlF~=BiABF&1WeSJex?3We>Cu=kUYi zC&U^r76IjRIG61u{&H3ZHn~Bc_bI*;CjPYrxK`hq*FK7G_(T7)fZp8cXp^?f+l$2z zPwgFinoie%3BQRv{7F<;Ou04Vo)U{v)yY3)R&_Dmrr6LoAQQ%=5S1KA748E4JN12U zZMkpW_Iq4NokH|0rry6pdD$(!{24<_6nB0#^kPZNsl|B|-T4a^LqubL`c?&>DP~TC z20dY0%bDobnK*AfAP-cONK5@{7AqfB4VM%ZCBgS4lg0c9$E+0F<^0I%$*o86A*vlA zW3@t_O;W47wf~m4&5d%fEhLf~qUZITj?)dO(rMWTn#zKIc;MVc>#oeQ?TRy;F11hw zGEBOB7`b&Xi=(niW|DMmU@6=ola8Ql(fM3Oa^RkljmWEIU45FbTA`a)+bY}Es0I@| z)BEH( AwvK`q2SbLaDTGm6l&)SbE`A~%pEFM*z?seeu&Jo9&< zmUEPu-O V;zil=L{QL81_g-5~Czjgp4DNmj^=C^q6^^h4 zu@qc^(iJRufUY-j`-Egxw_Pes9TRf 6;L`YOwtJV{SrF0glIzv_*DmWXv)KgI@5%)uoiehW4)k>rorT(xSe$C=` z&Fjn^eL*Xdy7eAf!O4n~Lt0-L_&xpRM;L&Hgv#DEoET=riGxiE&vjLdL*p7>A2g`s z6dK)}n417iFsg;-Qx}q?Gk%uzp(Ds{hmbg2P$%OiK-Qmm2(=UXY{|nhOns6jjmO1a zPFXLA+3O2CYu`?g6cchwVRf}bcaGp8+&rEOXD3N$acm0(w(p*XaRbdW$p(C`Xx}F- zr*TQig$q>}I45 nN|jy9Iu5V7bh3Vteixb_}gnCr`DG#b}HHxrOapWTe~5 zjF9~9(%5ij(mu=8BBx--Tf>s%*SWpHRfSozN$%ljm}z9Jyi$KIPYO(t^_#;P0ATpd z%I0}&gs+TV@sjs_^{UaWf+`}(i|?M}o2!Sljp$A6){OfdpqLbqe~_Ip?{#;(ltCTU zev@Y`tdxc_DqnAbI2r0xUHKsY6May3FcwevCDHp2Y!c~~DrdL^)#LLu8~oc&V798b zB){}~@})0X+Rb$5s?DyCu8daA^ba_Nw5OaIku1d`#QRlBlUt71aNE&Mv^10ItnJ!L zK5dE3+lAf+z^>_~&?M+o@1I$j21c8k2y&~>y|=wurLdvK8RQSk6zt7~&dk6_dC!i~ z-r=NaSDckSZQUM@Qr3>2I^KWn$03(eTbKPOoB7?|%?tY!w|gw-Q;EPxkNxh5tHs>m z&5Ik7+#>5cJB4}C&5d~PNCiTd&;wa5UWA}=Pm=+P+}x?dCc+i~SyvqL8JXqRxo g9a&>qG37|4tqEY=JHf#@88Kev$bwovRx7 8j(KeUv8Wvf$1 3SHEG|!#B*ZMQIo7gt()3;J( szp}W2;uw_Z-av_vs?Q%!-Co95fz60neEMGH z%d>xSWOHInmo6_9{&r`4v$&niy9QynmL*@^%&U|?c_UOi;-4?|fBg;2TDt;7*_U_& z1!@=peq5d&jMsj>kFsYZ0B 6eN5@m7x;W!zb}1Y}}Jr}#{!P(xv=C`#wtisavAEw+qG^&rl!-D`V(nkIM{KVB_t zWMeioWLfCG=mz&M)acmw(qXt0%3J1 JWV(q5>LardG72i`E#!~UpF0ZbDKAa`-D$MyL4DsB_7DXp>!4&B^G@{2aGVmr| zoC$C-7xuzu$l?+65P0LT3ub~4hiN2<<+qC{@1XV&B&c6MN&g~YIAbgwlQ}$vN`|W} z47rAL_AQcWs*dp~F~_OHvmZVL>rL}a&W2Gh;_znMSv!_w;RieAVe^sDJI&^Iv2=_s z_1ST6)~WcgJkh2SR&3d`XcAjIyCh>yh<}j1#7_+suu7HYs 8dQ}-2E^A{5=zU>p8KXW zX_7UDE;?$-+C{(;Le73X3oVmZkV=c=x%xpLy^uv+ss6L`RE7=P2z_I|iVJz_e;@{) zcV`aMW!jhD5=+{FPGw|aAg)D@-&3}pp0YzPWNXsSMJv5t*ND1xdnPHRrgqT{w4nR% zN0$!eXA#-0cI17lbStZmX|rjw=u16vO3W{WeazJq$r=KiwlDf{UMR788v5RH2u$a+ z1-E#tH0X}Dsq|FUF~MEEbJm#853@xJ(;s5a(M5!!@^D-5%y91-sC!fzcpr3p(#|gN zwTRpZY;{*c0~3@P&=2+NeDNNZac#NH{q4hC6Qn&5 8XBgiVNl(P4E7x#BAW08mNxW z9!^3`;ww9n=B-QEE(5ia9PA{fFN={qgJqEvSd(>cYYg#c9cwx;sCjxQmM}MR%cqWC zJ?7Zpy^G|WIX4CsZ>e-gS_{9RcTcLeuGqjki0#KI9F>ooU8`-EI;w2IqAF45A1z4I z$5RZk3!1B?A9i5ZutDU+%^G89Sf-T;(ZYKoxIcQ(VN~n=A+5HLOL54wPs}5+u)=a= zAc&en9>d4a(pZ$ IzD8f*`WHoU zL}@cy??Ab{t_S3e+3bz@qGCX %^=fWMiH22H&>dS1R6vWcyzq z5+En*M)E>~>R3fAMlF`inO+t#ge@ {go&_zVk;^2P(>JqXR;TzJYEF*gBU&1 z&Ea?;hIC&fkn#cg2kRwBnDN|s^KNj&FM36~(R{Ay6?0avf<}weJ0lR&o*TR?nAL*n zcsAg%YhVg$Tu#J(;Y4>DdgLUEfy4vS(O#wv?`#2%O24^p8N(vk0*(_mja{Sr&!lD* zU9xzUSj&uHC?GV=Q{pMNghhh|KNZyp*=%;V!V<1#HH~8|*~@%F6-5r^JnsT!{@#A1 zpLhH)z`XFi(g@V1*RD9T{W^gnwY2V}OBf>69QgddjR|VSx*b!ygp0E|%KP?Y)Ya%~ z#w&4^=&G3c`!89t)CU4H#Zn_QrT5^Jrdw*!ZI3&K|FqK1Pf7oKWCPd4wmVJ!o8G+&D0g~+I=LG{@Y$HY3pS;V zG7Q;%ERrwx9Ie?gbkGQf3keCFB{!{qmzN2B{p^UMoPU5i3Lydpu1~S|{Nig~!jcoo z=E9dAHw*~B8J-1G(OO~wG8%%RuGW>r@ePBhCL#XFEC&m#aB@Vsg!Qk?I(~gJN(L1` zQBNzb^(xmV+jCh8Ke3e?SVWdWn!3PlDT!kzyL$aEYR>TUZH3Bjhw4-YqYiU8Y-_#( z_O_$90i42{1$y7<6tAr{kjGk%lrD{g;!To%4V2+8n_iy%1OS`N+}!t>>+5{?9>B@T zVf6qYPWjG{l^X`^>1@5185AD?z89VVw`GK%-u8OEKl~s5S4cS@d&A@l_kdm@k6bh* zJai>MokytIQqBH@K~3m>xAvxjo6Oh%i6#CtBSX ml`3eAiAMWkCV`4C^U zv9!#{!kXPXS}{s866iv3fdf!(P@KdFBFF1Yoa-8DKJdSbkFZ#g)TRXtVyBytM=A6q z!EueT*HHv4oM->YS_@5M@)D|E2klR85(1l(z>*VoI4=wbuD)q9Q xAm3A3VJvQW{4=k&76}l-izmuDksPPOq8ndpV+GA5aTk{g3Efxu^|~wGvQz) z5i@DoC+;~U$}hoUF#_|D@EeebFcxt!18YuwgVo)6$eZ2Tax>jgC 8%oUQ}DHS z7q0#??f}HyxDQc_-%H+mz6EPCKm9!bb#?r@_Q(GEF2C8fYuEmBzk(iLhJcUT0bMu1 z;t#;X_6axrcW>S1yU#Z 0l1-f-%!tXdUTf9H{=wasc-SL DlWk r z;{oBpx(8a%YfM9O3DbZ1s+{3;hps0`?Sr%>E>Un(2WsZyql^czV(2jEO4kHf_qe|F z=hxM@zTfNn (}p;_3eS^d4O+Q|*p4NbV+?^`OOZL}#uUcHc^*WopdTI$X~-TlV$-PgoMPvha^ zE4yEu(Y}Q2d JD%T?3Bp>X zM{)%jZN?wk(L5w>8~aqsX+suI$6G5P-jNef9D1jNT7$d_rYvmpewT5*3tiwEX)EUI zjR;g~yLg+)<_PO8CVWM<{%nNkw;+?li&X^2M2JY>CmD2!f2_K&NF#c7wJfEZ3CYG} zSkhpFVO=$xij-Uwr9h(DMR2VQ^l-{L!&4m;Yc7lfx?2ZYc_*}*TXUQY%3XlkVTqS0 z(txeG0CyDQ;5o=SL!F^oR)EMY>mU`EPzuNlts}uQLJo)cnpjbr|KR@Z#H}24L!YNH z 7w89iS#cA6%EFPJ-WPja;5}d$5^!5vv?8R7IXe-1yW= z1FDiMqQ=EhiU(X#BtUj4IQ # %?|suKkkeDZc7AkJnl*SZiP^=6++8dh@fW8|DO # L{+k6P1Pt^)*F+$M literal 0 HcmV?d00001 diff --git a/downloads/LoginKit-0.2.tar.gz b/downloads/LoginKit-0.2.tar.gz new file mode 100644 index 0000000000000000000000000000000000000000..83cd85de5dd7b00bd57dd93b294a659967cef559 GIT binary patch literal 13694 zcmbW7({d$>0tI8+nq*>6Y)@?4wr$(CZS09{+qP|I-}4Q(YW+dKtg3FJXc!nN@K7-@ za2b1ZOFL;x7kb7&%zs=Aoj|VmES)zwo8D{m138aL*ox vOVSDsJe1yV>+zu-6H-igMz89)*cu_g5DVt9@wVrxZ3xPN_}KED{U;;E z^^Y$5>znKSz1`j0^pEvkgwGwFo88lP_T{bb6`Pw|JJ)<9Jn=pKEasva=nod0 b68XSUCVFx7q=I}6(DlMk2n`1{72e6 zZ^rhP`L}y(Yxau2v%Pb@4zQLm#on#8Gdo`5)$qIbgJl9hojB=>7e^gg4xnS0DniN( zqyC!Kt~Eqs7GqU>6Kj6)s}|jhJc}TckT8GJf8;DroV8#MY8Bz ge$D_@$?) zS1TOFE0d|Xc}85ZLR%eclqFIke`lH?Jez{)$FnzVTIxY|@xDU >j;VQ9uCZm@0 zh}f`lKbnC#<-XaRtM+!+Q=Y ^^ zlE8pxRTPZ@1J>9X3kVTTy1epvN4VG^#QIw5Tkd#xuar_qS@?9hdS_AjF0~{)d!Ji_ zlw)Nyq-aj*PwOo5m9Z48WV(y`+@I$!qwBlYrveygSiUC&qiLrgaA=yI%>G_j+0o&U zA!<)^*`Xrk`T`>Ox6XB2_Z%&`*lR1q#y{}YDb|S1F|%yjhyWLi(?zS{SN3%$R?PQ( zA=F=lWcvXWoR2>n+}b=k=AY2`T~~Jo;5&y+A7GSk_KXPTj;Iv(w@dasleB$cW1P9u z@Ns{Uk~uK)4 ybsI =Zw)I zB~GD F~5mc@Umy4G?ivXRRi73IVee(k%2r?do$M1u6B{BV@s<{}1=fB0L& zr*szs-Mu=IKY-ciz}|V#8m|I1J`Ee>goJS{F~ewZ?ui07xF!`go`qWs$4YgHf2O{j zQjF2z>ae2wl+U?VE))6&i>nJ1jh~1MH4)+*RUi02vacl3EGt&TcZvuANaEXHp@Xo? zNA`WMS_a4<3Kr;714d{tY&YrCr2_%0%8YV?s~NXiR&U=IW4;ip92ZiT6M|L#WLNcY zEvdC^DlCJVT>!?5$-2#7*zkUz-D&}%I%NO){~mTjiy?~J=V5ce^5rXNDdwhvLN_C7 zrR}9?t-SKy1{lgxKPs5oBH&8gH1+75tPY6%&L0DDL79G)WCA6hXd;Un`wbheK086N z$QZu7P1y+ua>-BB#1VDm-l5FC^YvCcivqV`p8 d z3&sLo@Y&l7kX}q$urh}`HuN{Tz`QxBpPbTla3MMuEN-r|>VP_4M@G8^?ykuAmT3PF zlvSGg;Z5X$bH G-e)WTZ3v(>(Kgb$h3J&0ib&C*R%z znCiAFLEp+;F!8LO2Rdq`Z9`3yTo!V`05FtE?)SJS^<3peo6Ku3J%#;2K9#)Bu|KpX zzZ<*8hGG^){n76Sb{+9|^}+$|ZMna8H#avnJ@ cP8)P6GniP125(~!`uuC)`YAyD@K ZSu jf8dO*>hke(azegv4larjW(UX(jxB-(_y>`!Ez0vpi$Pd6v0eM1?*FYfcmw%Qy zOBObh>8smMO%rf)-SNf0)4MzTG2i}SFAR#*U}?d-b_F_%Wlce-a`!qxHYUNgxyWYB zSf=j@ECkb;kR6=@APGaCg8%w-qQ310u$i=5uo*G3X=-U1@g_0Eb9_|D4*dFhe=5r` zp Wf_0&j58-fq>3s-#egBa`~8jh~sRlE1>$`R8Et9HvG6pj@dohk6=MlNX~;g z-VY6t38Jmkc*WFpm-f}Vt$A Tk;Gb0%z zja^bsiCFT>ft{zEOQN-f=??l^e-v2Efcnx%@*k!f*H@jN-Stbp|7dxT0UIPMf{dd* zq?S(!mR#7`2Fz5SEt#Yb0u3YxS1`NyJ$-$I1kwm9dpIDWs)LY(%494Io9fZoi~cff zW%Xzm_(-Qe9n#IT>*L6TPuo6($Ou+2{XD?FpO^b4DdANvTHr#GWHED3F`<`b6hs!I z5tukC_|WkJ2$wv;b)!jgE*`1CU?--W=81z*$xv~HvyH$;P)6b9OL1 n9uTmznW0P$ zQpIeE%rzF1NA?czWbF}IA85ip$93=e@NzIUED}Hr@WGK#)MQf%W$8YmVW)mak@wL( z% 1_40aqq2odE4FY%H|qXyT}{s$dJH7CxG0=WAWCf>KnMGXDG-zw% zdu9=CYlE}qBf~ {Kr-R>oxPA=B?lh{mXY zVlLr>039VdXoD3j1;yOlS5S#uQF?T}UftAP(jSnJPmLSK^=leEDKG&n2wD;{jsNLo zE$A@Qc~z;NE-S=_B aERxRkb}MqJqbRQjJ0;A=m< )LZ;+$pv!5$+cqA&^e|VR-a6%2RK`P={O>; zx#p0r@} %1274OrCN3`G7tkwK~ZG$|=h5Hm(oMo@*m)aN@^m?mG`oC;u z3q9YIEQ1F`Yy}q2IYtcV->*p&3M2{}No7L#Q7-8j-A?}6GK?bF8(%s@%cqCYC=luL z)XVT+)*Eat8GY1Xk*a0kELADnAxzncVcu=R%X=q9TjORasbhFk8?5I*gOm3aIvGQD zkjcm@2FOghYn4`9;TZHyzzUc+LMWKQW+)pfh78iGRf}Rv9Gi~ZtTq}+15`)E3i&eB zBdzl{9l{#lF=KV2C)I)r$NDB_^h*uf*%9eQ)$#)!UE%vH#Sna)>4qnA!Qf)6w7+vV z>$G(bX#%rm;)d8@-7lqg8XL6KagO`V3^#Ubo&aNcc_GviuH9yAx)liH+BjRKwcA?P zeh~DCYL 6uqL6KdvfPt#uE~?v zTw^ySvyx5N$d}3|g9?qwCaZ4bl?-w@AC}$WKj%tDZfsh1Qq}|0Hb`PX&d{hE>YTjX zFQV$zVG-0t|DwaOOuYFa_aIV6tB<$G!1VqNKaLevWv 5~x=a7I@B#!_1_U zjLiP!yyv|i4o5E@bWB`DS-R FSDL|hTHyOlZNr?TN? zJb9t33*I18uQmPZ$wzF@99fJSX0zi?pHPcGKim4~lUU&}qQYlFm;^}#OM)q>VY0@c z*{+G??e;I {~vsX{FoOC lF#tBteU2X@nC?q1<-hDU(^^ZD)SVft}( zbmx=XQ?`o={5{StE<1ndI}+yK&r|)&+J8r=%S-uQbW}t}T+u09xjc}>P^LNnWS2tQ z12!3jzWX)e_x*a^9sJYaZWj1ID;<+BUoLiW>GeG67_fml5gcKMpN|6-#X#O*4veIV zI0RSR`F@|AIb_y*@9h@w1ZgBk+_K12_v3^e=T;k(Ch31u3yr?AD9}tY%r5n~;kR0b zTp_O^InmRb0xT{%<{od3q2Y7~J(G03On<~>E4DT}!k1LJ)8GJUA(yv*mG`XcMN&7^ zMUrwRJ=HH_3#8b=g$fJ;A-(zTtZ35Kfh`Y9x0rD0`juL%mN(7Wl!4wgj1Sdm&j&lX z#$S_V&OWCEdA*Ay758V|>;Byx^%~KxwV@Nf*zqWuy0c4Aur)2;RuP}`paNzk$jH&u zq@eL0i$4zq#Ha)oi^XudM{lqF7Z1aqAi$$DipNeO@w Eo4i2 QUT?}5azb9Zsji$sQDVlc} zsn-i|lnDd7Hu1Yx?4O{3CM+Ffo|IN1^N}=x&P_ Rd^5NDRBwYfSw9^ z6+<~(HxgX(&xnWt!TWxAwY6|b_4+<3G P4<$`wY(~g0FSE@ zW9Bf*lu$RdG;K1@0U~S$ h7N3>wfD8C zx{-9%x&Ma^PBTKwbL?P$y1oO!%tVWA366(LnBm%#ba 2tJH6W4Nk`C zGa*h4E-JjFzPL?Qmg?^{j+MU}HSB5^5D0s@M83ETmv_}G@_89!nK1Xri}j2rMj`^b z@tEKR9MXMrxwzsi)4#?K355L|%!9#BB)ZK4p&1h@hkjQt=5$_O!qmDK4S26YlHd1D z) UHP{4s~vYl=IbZ$EjP^=^|(_Fct~rVB#hv3f)dlX-YvrFIQlwM z@zpaP<8kUzM#Yn{3Wusqzmph=$kvmAs6M~J`#Eq7q}hc|e<9v6x=>hTrBJH>!H(%2 zD(KSQ5K4owjl}a}biC%NJ(fHej~>=U%aZeCM08f4G^m0^3F$W15sMC-nXafL6;2<( zQcf}aGpo$YqJ=oh*uIkN%{!OTMSno{$8O9bFX}1yQ%GfVfMXqAs9H>}{O%4Xrr_H< ztHG2dQt#-eG)$|ucg{u0NlQV>LB)Jj yUq0)3mZVT4A+dw~Kk=_-RBF5!2C3;}BY5^X+)E+cp z5!HFKbFP%= {^qxtVZ3P^#C%LGuHF}GG8lG^vUI`N~h z*3#o*ADvmD%_GJlPqY)9uo-+fR(@YN{Y7H(Rg59W3(Nxo^>(7r3CVjGu@HF}A17A1 zz6OY)zBcEWDwAQKfW{25>*JfD%B+~3JQ&>_;sd+zi5AUG`-@gW`|LDEb^a>P?G-IO z>iP6}-4ODD-h9(}<@JT7+pv@1;6xIPI2+1@i3;{|U z_-WDLiGyubR7p+md_Nnzfg{8c0ZI5>W1 FULIR-L-oDC|eWzfRcV(ZYYsjoB4u|kAnG#~8=*Va2 z5+Q~2_?wpESWuW$3Z>fXuYp&cfyg>8c)1~dB=?SdimcGm1z&!9!yqGc*S*9wD19AM z4b)>N>XLRdhhJRL(Ma+!svbt%P@tb=TjVk&mn$R)*<`!+io$LK;h5(-_Ct;{Kbh z2lk~lbI%g|TV1EiN+jj_;8#06N5qWEC?h#&H5-%SR&nv6*Xtg{Dx)^#1Yv6NgY>g{ z(Wppt(88OCz%tK$M141ta)5~|-#BjMP7Gfwn-MieHR;XX32!HVao^pyUU0;b0}k{! zY&;9`Fc+MoV=OnWhcUq+WOdHhJO*|0Fl!<>1DLknA{pux3{MpjJN9N>f{nYk2t{i2 zSC~f(o(e(9Fph-**^;q)7Ota T#!9c6(_9)H;;0n@N{oe&WStz6&|KIe5@>(= zu7QFYXP%LcPA_W&*mHk4vfBa-bokJ5q0gfY3FpK@3X*AC?Y~MejI57PM-xTJQMFKa zJ@`33a8RiNg9g|6!F0Vq;;adzSHr{T9lrZoQ@I4vVJOmgyw#QU{MB~lIc$p~)mR1R zIcrWiK30FD(6D{(0dGSis1$MZiMhH3gO9|T>-zp)at@WCaEh z>_3s^@TLUW7Sv6;CgQtDU=^(o8RX&2{CILsTfAbeSVAfGCOs2O6g4-e<&9t?4G( zLyKK8l3GpU(*VLM9#~-YPYssz 8{L zvGLyZs&|DwkDq?szt)!ZA-_HnI09}5(#=G0bYYmW%;y1IhNl|qf=OT45E8aRP_{D; z>QDRK0x4#*OYM}7SkYL4;@ldSR@ci@K;#FAU0Z-1Tu&+ZeZ3?nT_64wzv`!PC3@%m zo`DPhqA2-nCgtvO-luw;>wv!&@Lb0cPCRnIP&6s*jrJp43P2xOiS0xER;l7Uz?2QV z;Rfych-%O-?APCtbFR117zoF8$j2RIb=f+&sMWmL#em@1^SctPvH^D~ud_N9%BvjP zd7xlH2}$#U%xn@gaJ-_WDH #iy3Z_mdH&Vqs5+}2mW3)-@L kr+0K*AJs5?T7JkZ|C+10__}k{{5h{F^YXo?ei~^> zYx9W5Yoz-9EA=eu97t7(*)^@KI0z8oGLodS5qw-f<`v~qZE2G^3C$iEw#kDLJYkSC z%q%7+%=`_#M(8J-Gd@X%4{pz(v`$hoQcvtF#$*y0tis4(sB<*PDm8_MXZIt98YH8X zo39f?%gj*iO%$rbmioziA `M8VL0@l`S9s*1w`j9SwK>CqwQl-4gM}Xng;FsgOkE?#ECemXGxYH94+8b2 zguYaZEVII0%Ndyf=)z_7vc2|__n*C@-6pI~5ACgytumt}J4?o3%CJzs IukC#(kIHB$tC2ImO9$mtA9SkH7zg!E$rpl(bgbme&rqz{p z#EBsCQ!F!@q)}UCRluyl>w4*#VX^xOtAqRd(Cnjpm2%>kw9tdtHvb?tw%EWdW9{9f zSf~;bVdckPl(_N+rdqUS4BOMh@f>DPsnRpH Gk%SVhKe>o_%nu(KcTNH>+MYq8hjJ_DTg 5xUJK1h~(ZP5ZVapNHc6pKf<;HUb2dTF` C#kPVO0pHSVvr!%cXj+lxeSD76Z^Z^h?2nDMQ$U+?lY z8Sj5UIcf(?TjVvzjSUdga-}LbK(v&Oa_|m;{+yrwv?Ck2qJq)~{(S3R7eoH~yIxJp zL%^@B2O`QYZ)%-%_@YH;XCEoKxj|a|f+I@hb+`n!ri;UTdX*tC@DTGsSJrrNSDT37 z3?y(oUU+t>c-(p8I6Kk$BFQpvR1#}DkVG761EA(Dq%}Qdi($&~IEd{`8wgw=sf(ZR z_#Be$D08`L;BleI*PCM%-7A?6l1*c$sG%@P5gN_#fWYy?r8L_+ zv*WJhx=mx5srndBEt>W;Z>fJw8B^4iq`5>(DqkR?5c&lf5i;23UoD$9sz=y&A(RcO zelBKQ2i78lP?-j*_4~%8Dgq*C&! 1=GZh zn2ulq1xCKZ(!8c^a*lM{!)Cfz*>N0W$Z2tgLKAlA<&iy;MEPW7^EkBY{fw5B*n;ae z68i9UoMF1h!>0NE;7NWpZW*$KY(w>=?0|Z_eMn}-bg_mavwUS{kkdp%sRD474du6V zbp7n(eI*&@SO~fAq=72ML7~!XW`%wE@#%Y}N!EQo;%}%JDwSz+fTXRFG#U3$1tC%R zXQ%y+@7gb4-nDJy`1nqxVZFEs+?KG@0tn`c+?&RcgT%rMSinS=Q5oWO;229;K%w7> z0>n;1VSpUB1XQ;Hw=)_nwiIFxy;Bu}Usiw+Jkz}Z{|RbYBP9a63>~Y30DhNq$%!!2 zkdSzP1{C&@e5geYuU*Wql#y{sR&~AyLnuf;v3^H5;r=t>rmZ!!_qVn#`*}SFpDlQZ zd-~>6PWpdC=cY6&wjOI#cJ^8L4|ca?OUY89fh%MKtl8G`2sx{)DYu4^Wu8c>3agJ~ zMoC7x|IQ20WK}$vJH*DULiR5w? L?I+;If=(s&Oxp&8p3E4{j{b zyecEe*z`uFO@|cD!xo2Riog<;lBNerlLut FbJd8WrlAwj<%Gwa&P({8wg zrt-;$p8`_*oP+-A<#+DR9^gG;CVpIBLB7g}b2u(~zOZy}tcf9o-H_F6QVY^7DCB zI#`^JJR+2jl(3;c(!>90h<>X;HP(+OO=+UyroNL72$Tc+b>5adk%BLN#>1IAo^nb6 zQA5r`E%u8ep_`>UkY=CIC&*Y!gVMMGkt${|6$39VCcND_Y42jD<^=QDrE%8IMVGEU zEt7$-T3ZMybMgxWyUdt0wvFIo@GcQTj3Xy2LijFYH;HAS!8d??RMG+DRHzd>gK{as zgF#=+T}iFfWhS+7HKjl+?db141|qrn*MU5xsbd&&w4cL5L-0z1cRw2%BR6QM<4As~ zlGLU1**THEbd;T9EcK4cXjmy9bln+AV{!gVduaVzTXiIs^-~iZY vGV~e zeamA*Rwe%f2$4rL<3F2uHiy7Y^|5?7tb5)pvk?_)Tu=VK>wE5b2}UmtX7*MQ9S`0* z@XW!lal!~Y5tbb_3nCY=Bfg3UGgjX@pWk!5M~u84Oi~9@{@}iljCG(qT>q|35-B^6 z1C-M#8n!M#HJBP85MF5G=oPQDI4wH}-I<2@Yn8;fRjo~r=qDvCuqBvy*tA+eqq`qb zXTra`dvAQ!ykA%P?;%GjX*Q#YUbbqMpA3+YWp|#nG$Y6=X~egcJot*UBl 8H%i<&|RuwT-X8{abye3BsIjM>eo2oS+S!ptMA9C0~zHHeeX{ qwuzu5kgUNww2VQN`tvCjcHOp)M(`e`8@xrH=;)csn3FVvBe@Cf!i>J)+ z|J+)?TfUDMCJ2>HV*{8zoe&F3yV_`yvC!Ejl{WlQIS4%6c7k5?!nA(r&D`2i9*k0a z!rU>{Kid*|_{BLYP?Q^C($jwxQ&zF7u$|~3+adrZQLV*VH=g=S;-7XR$~3bgXaY|q zZd903T8in~^)4zD*jA~Vag!(i>|}49lkA&ikde;BfHPEGT_D@0yT`M2mBF)v^~!cx zRlSvqJn{}&=WQb)EA$dPv8_iq-Y==08 $TIWvHoZwi6H>3-m+0Ve!Qd`eS#J+q;GnYblvtT^E^r z*udDryz}sb1(ounmBLWq+F=Mp_0ow2K$msI@6+9X1c9Cq6~+ g4Y?KTMWFZR1PQ*fII}{UGE9 wH!Os%a+cN6T65dCf$DaWxRaRLL^1<3y^QEEQ zLQj2&r^k{^HnEQ`H8FB#la-Ouq8gn@D#D~mqw=eXkJUOq8SO!!iVd}v+NSQYM*zk> z8gXk*f&}-i>By-${=b?^DFN|7clxFVGtArR4K2Aj0Rg(i2q1x-9Z_o6rOj9XC)026 zJ7q3H%UKi52!vkmU7)~A!2xf4*Fe~VN%J2=eO`UqQyQagi8+ef B=r=lBH-}YXzNA>2XLe<2UQK^TqO>L IItftEo=#P_qX!(!tV62M-}aTeIy)EKV&>u4CC~ z*E~dBUP_r3x;aihxLrz~Uc`7JD9&-e@RS{vULHF%&Q-#73q-`!LFe-utApoh wJ`U#dd8qeBoNRVIdFKV_AWgFZ^q&YpFb7&vF{1Ouv_5bls1`) zusik_pD_k_3_?{v?Ilx5;3mzw>^3Vk{Hd<_6i$QHWlYuq>BIZO`(Whj;nBUkKv;{; zPVdRyCivSwqkWCtCQIv xTeDPH@ADQZaTfA&iNHiW0agQQJ$5?mjos! z#9MA8yo<-1O0%VoBZkI@#x)YurZciOCXUh@t5@ojHY$X3jUvO-D)R&gj6``w@@@64 zF+cSqYh93kqey@C=G*XXyL|U@wC1tC^y(kpXMf_k^&H=2j>v2cay3OATa@O4jSsmf zj;&$!aPKF2o7aPRan_8Prr(&g1gGIh?`)MsVR~LmN@B{CiDk*X$>0q7)U91OBXO_# z5qc>&BF)cckQFs@&S}ZXhx9Gdzb|&UceiaMtL0eu@&nlPy7(oTT5oc|ZSw^vYqHYR z33NGMvh w!7ybEUx12V*@0!c}E zxl6PN?Kqk5Q^l$(I8NrH^277SPJcRG`ERM*EzAyRwhB9IRjY)XCkX6xu|AE>Qx!iv zFM27=o4+G-O>60bGY&e!)8$WlUfn2IkbGC{n|Rv|2DFb8GszZbXsQ=h$!ETj-T#S( zY)|Y7AknDzr+*C5llac*NR~3CK(E%uc#8AJ_3iiuY}O#Z#WjlI24G@7dE{rl6fPab z)DhtF5EoUD|0;h!3M1Qb+_TX^9;!&hE4pf*=T3LfmoIADh&WHnZWYYd^|%eUljn4Y z%HQSd#$H{_LUOl2-*%!@xgT!}Y5QyFE8Y30-a>h4h;GA0DPu#&n5Khv1-_*0X+RZ{ z Hr3M26#_Vi&)Cfmw_Q@xAN1qvBt%KO`zm^5ymSlJKQ8_I z@r!@T&$$&CZZYr1bt?$ys7MUVFY&)j)2!8Y{?UV~ZB7F2c8C0E!UE6lN5U?FtuHRs z`@mj`AM3vw;$;N}{^=oe;5q8&Wam?ZK(3e%|J`%ov&4_?CGhmDGap*uHNNM)buO<~ zjCCY#<&2Zi 0f4sp-L_9x-?| z^M7hvfl53CpOd%odolv#V7!pY8nHF}qOFbd{n=tfwzG zhAN(7kgb