Ticket #575: svn-diff.txt

File svn-diff.txt, 25.0 KB (added by Mariano Reingart, 17 years ago)

svn diff output

Line 
1Index: editor/filemanager/upload/test.html
2===================================================================
3--- editor/filemanager/upload/test.html (revisión: 387)
4+++ editor/filemanager/upload/test.html (copia de trabajo)
5@@ -91,7 +91,8 @@
6                                                                        <option value="aspx/upload.aspx">ASP.Net</option>
7                                                                        <option value="cfm/upload.cfm">ColdFusion</option>
8                                                                        <option value="lasso/upload.lasso">Lasso</option>
9                                                                        <option value="php/upload.php">PHP</option>
10+                                                                       <option value="py/upload.py">Python</option>
11                                                                        <option value="">(Custom)</option>
12                                                                </select>
13                                                        </td>
14Index: editor/filemanager/upload/py/upload.py
15===================================================================
16--- editor/filemanager/upload/py/upload.py      (revisión: 0)
17+++ editor/filemanager/upload/py/upload.py      (revisión: 0)
18@@ -0,0 +1,177 @@
19+#!/usr/bin/env python
20+"""
21+ * FCKeditor - The text editor for Internet - http://www.fckeditor.net
22+ * Copyright (C) 2003-2007 Frederico Caldeira Knabben
23+ *
24+ * == BEGIN LICENSE ==
25+ *
26+ * Licensed under the terms of any of the following licenses at your
27+ * choice:
28+ *
29+ *  - GNU General Public License Version 2 or later (the "GPL")
30+ *    http://www.gnu.org/licenses/gpl.html
31+ *
32+ *  - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
33+ *    http://www.gnu.org/licenses/lgpl.html
34+ *
35+ *  - Mozilla Public License Version 1.1 or later (the "MPL")
36+ *    http://www.mozilla.org/MPL/MPL-1.1.html
37+ *
38+ * == END LICENSE ==
39+ *
40+ * This is the "File Uploader" for Python (Standalone CGI and WSGI).
41+ *
42+ * Tested with:
43+ *  - Apache/2.2.3 (Win32) mod_python/3.2.10 Python/2.5
44+ *  - Apache/2.2.3 (Debian Etch) mod_python/3.2.10 Python/2.4.4
45+ *
46+ * You shouldn't need to make any change to this file, instead see
47+ *  config.py and .htaccess
48+ *
49+"""
50+import config as Config
51+
52+import cgi
53+import cgitb; cgitb.enable()
54+import os, sys, re
55+try: # Windows needs stdio set for binary mode.
56+       import msvcrt
57+       msvcrt.setmode (0, os.O_BINARY) # stdin  = 0
58+       msvcrt.setmode (1, os.O_BINARY) # stdout = 1
59+except ImportError:
60+       pass
61+
62+def WSGIApp(environ, start_response): # entry point
63+
64+       # This is the function that sends the results of the uploading process
65+       # WSGI compilant (generator)
66+       def SendResults( errorNumber, fileUrl = '', fileName = '', customMsg = '' ):
67+               yield """<script type="text/javascript">
68+                       window.parent.OnUploadCompleted(%(errorNumber)s,"%(fileUrl)s","%(fileName)s","%(customMsg)s");
69+                       </script>""" % {
70+                       'errorNumber': errorNumber,
71+                       'fileUrl': fileUrl.replace ('"', '\\"'),
72+                       'fileName': fileName.replace ( '"', '\\"' ) ,
73+                       'customMsg': customMsg.replace ( '"', '\\"' ),
74+                       }
75+       
76+       def GetRootPath():
77+               # WARNING: this is not be thread safe, and doesn't work w/ VirtualServer/mod_python
78+               # Use Config.UserFilesAbsolutePath instead
79+               if environ.has_key('DOCUMENT_ROOT'):
80+                       return environ['DOCUMENT_ROOT']
81+               else:
82+                       sRealPath = os.path.realpath( './' )
83+                       sSelfPath = environ['SCRIPT_FILENAME']
84+                       sSelfPath = sSelfPath [ :  sSelfPath.rfind( '/' ) ]
85+                       sRealPath = sRealPath [ : len(sRealPath) - len(sSelfPath) ]
86+                       return sRealPath
87+
88+
89+       # Start WSGI response:
90+       start_response ("200 Ok",[("Content-type","text/html")])
91+       
92+       # Check if this uploader has been enabled.
93+       if not Config.Enabled: 
94+               return SendResults( '1', '', '', 'This file uploader is disabled. Please check the "editor/filemanager/upload/py/config.py" file' )
95+
96+       # Get the posted form data
97+       oForm = cgi.FieldStorage(fp=environ['wsgi.input'],
98+                                                       environ=environ,
99+                                                       keep_blank_values=1)
100+
101+       # Check if the file has been correctly uploaded.
102+       if not oForm.has_key('NewFile') or not oForm['NewFile'].file:
103+               return SendResults( '202' )
104+
105+       # Get the posted file.
106+       oFile = oForm['NewFile']
107+
108+       # Get the uploaded file name extension.
109+       sFileName = oFile.filename
110+
111+       # Replace dots in the name with underscores (only one dot can be there... security issue).
112+       if ( Config.ForceSingleExtension ):
113+               sFileName = re.sub( r'\.(?![^.]*$)', '_', sFileName )
114+       
115+       sFileName = sFileName.replace('\\','/')                 # convert windows to unix path
116+       sFileName = os.path.basename (sFileName)        # strip directories
117+       sOriginalFileName = sFileName ;
118+
119+       # Get the extension.
120+       sExtension = sFileName[ sFileName.rfind('.') + 1 : ]
121+       sExtension = sExtension.lower
122+
123+       # The the file type (from the QueryString, by default 'File').
124+       sType = oForm.has_key('Type') and oForm('Type') or 'File'
125+
126+       # Check if it is an allowed type.
127+       if not sType in ('File','Image','Flash','Media'):
128+               return SendResults( 1, '', '', 'Invalid type specified' )
129+
130+       # Get the allowed and denied extensions arrays.
131+       arAllowed       = Config.AllowedExtensions[sType] ;
132+       arDenied        = Config.DeniedExtensions[sType] ;
133+
134+       # Check if it is an allowed extension.
135+       if ( len(arAllowed) > 0 and not sExtension in arAllowed  ) or ( len(arDenied) > 0 and sExtension in arDenied ):
136+               return SendResults( '202' )
137+
138+       sErrorNumber    = '0' ;
139+       sFileUrl        = '' ;
140+
141+       # Initializes the counter used to rename the file, if another one with the same name already exists.
142+       iCounter = 0
143+
144+       # Get the target directory.
145+       if ( Config.UserFilesAbsolutePath ):
146+               sServerDir = Config.UserFilesAbsolutePath[sType]
147+       else:
148+               sServerDir = GetRootPath() + Config.UserFilesPath[sType]
149+
150+       if ( Config.UseFileType ):
151+               sServerDir = sServerDir + sType + '/'
152+
153+       while True:
154+               # Compose the file path.
155+               sFilePath = sServerDir + sFileName
156+
157+               # If a file with that name already exists.
158+               if os.path.exists( sFilePath ):
159+                       iCounter+=1
160+                       sFileName = sOriginalFileName.replace('.','(%d).' % iCounter )
161+                       sErrorNumber = '201'
162+               else:
163+                       # Read file contents and write to the desired path (similar to php's move_uploaded_file)
164+                       fout = file(sFilePath, 'wb')
165+                       while 1:
166+                               chunk = oFile.file.read(100000)
167+                               if not chunk: break
168+                               fout.write (chunk)
169+                       fout.close()
170+
171+                       if os.path.exists ( sFilePath ):
172+                               oldumask = os.umask(0)
173+                               os.chmod( sFilePath, 0755 )
174+                               os.umask( oldumask )
175+
176+                       if ( Config.UseFileType ):
177+                               sFileUrl = Config.UserFilesPath[sType] + sType + '/' + sFileName
178+                       else:
179+                               sFileUrl = Config.UserFilesPath[sType] + sFileName
180+
181+                       break
182+
183+       return SendResults ( sErrorNumber, sFileUrl, sFileName ) ;
184+
185+
186+
187+# Running from command line (CGI), in case of no mod_python nor wsgi server available
188+if __name__ == '__main__':
189+       try:
190+               import cgi2wsgi
191+               cgi2wsgi.run(WSGIApp)     # (call cgi to wsgi wrapper to execute WSGIApp)
192+       except:
193+               print "Content-Type: text/plain"
194+               print
195+               cgi.print_exception()
196Index: editor/filemanager/upload/py/config.py
197===================================================================
198--- editor/filemanager/upload/py/config.py      (revisión: 0)
199+++ editor/filemanager/upload/py/config.py      (revisión: 0)
200@@ -0,0 +1,61 @@
201+#!/usr/bin/env python
202+"""
203+ * FCKeditor - The text editor for Internet - http://www.fckeditor.net
204+ * Copyright (C) 2003-2007 Frederico Caldeira Knabben
205+ *
206+ * == BEGIN LICENSE ==
207+ *
208+ * Licensed under the terms of any of the following licenses at your
209+ * choice:
210+ *
211+ *  - GNU General Public License Version 2 or later (the "GPL")
212+ *    http://www.gnu.org/licenses/gpl.html
213+ *
214+ *  - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
215+ *    http://www.gnu.org/licenses/lgpl.html
216+ *
217+ *  - Mozilla Public License Version 1.1 or later (the "MPL")
218+ *    http://www.mozilla.org/MPL/MPL-1.1.html
219+ *
220+ * == END LICENSE ==
221+ *
222+ * Configuration file for the Python File Uploader.
223+"""
224+   
225+# SECURITY: You must explicitelly enable this "uploader".
226+Enabled = False
227+
228+# Set if the file type must be considere in the target path.
229+# Ex: /userfiles/image/ or /userfiles/file/
230+UseFileType = False # deprecated, use UserFilesPath { file_type : file_path }
231+
232+# Path to uploaded files relative to the document root: { Type: Path }
233+UserFilesPath = {   'File':'/files/',
234+                    'Images':'/images/',
235+                    'Flash':'/flash/',
236+                }
237+
238+# Fill the following value it you prefer to specify the absolute path for the
239+# user files directory. Usefull if you are using a virtual directory, symbolic
240+# link or alias. Examples: 'C:\\MySite\\userfiles\\' or '/root/mysite/userfiles/'.
241+# Attention: The above 'UserFilesPath' must point to the same directory.
242+# WARNING: GetRootPath may not work in virtual or mod_python configurations, and
243+# may not be thread safe. Use this configuration parameter instead.
244+UserFilesAbsolutePath = {   'File':'/var/www/files/',
245+                                   'Images':'/var/www/images/',
246+                                   'Flash':'/var/www/flash/',
247+                }
248+
249+# Due to security issues with Apache modules, it is reccomended to leave the
250+# following setting enabled.
251+ForceSingleExtension = True
252+
253+AllowedExtensions={ 'File': [],
254+                    'Image':['jpg','gif','jpeg','png'],
255+                    'Flash':['swf','fla']
256+                  }
257+   
258+DeniedExtensions={  'File': ['html','htm','php','php2','php3','php4','php5','phtml','pwml','inc','asp','aspx','ascx','jsp','cfm','cfc','pl','bat','exe','com','dll','vbs','js','reg','cgi','htaccess','asis'],
259+                    'Image': [],
260+                    'Flash': [],
261+                 }
262Index: editor/filemanager/upload/py/.htaccess
263===================================================================
264--- editor/filemanager/upload/py/.htaccess      (revisión: 0)
265+++ editor/filemanager/upload/py/.htaccess      (revisión: 0)
266@@ -0,0 +1,30 @@
267+# you must use either wsgi, php-like o cgi functionality
268+
269+# php-like functionality (default):
270+#  - calling .../py/upload.py
271+#  - can serve files from the same directory
272+#  - can do automatic reloading of source files
273+#  - no need to specify PythonPath (if wsighandler.py and modpython_gateway.py are already inside PythonPath, in site-pacakges, if not, see PythonPath directive below)
274+
275+AddHandler mod_python .py
276+PythonHandler wsgihandler::handler
277+PythonOption reload-modules no
278+
279+
280+# wsgi functionality:
281+#  - calling .../py/ executes the script
282+#  - cannot serve files from the same directory
283+#  - no automatic reloading posible
284+#  - you must specify PythonPath to include the script directory
285+
286+#SetHandler python-program
287+#PythonHandler modpython_gateway::handler
288+#PythonOption application upload::WSGIApp
289+#PythonPath "['C:/Archivos de programa/Apache Software Foundation/Apache2.2/htdocs/'] + sys.path"
290+
291+
292+# cgi functionality (not recomended, very slow)
293+#Options +ExecCGI
294+#AddHandler cgi-script py
295+
296+Allow from all
297Index: editor/filemanager/upload/py/cgi2wsgi.py
298===================================================================
299--- editor/filemanager/upload/py/cgi2wsgi.py    (revisión: 0)
300+++ editor/filemanager/upload/py/cgi2wsgi.py    (revisión: 0)
301@@ -0,0 +1,69 @@
302+# -*- coding: utf-8 -*-
303+# taken from http://www.python.org/dev/peps/pep-0333/
304+
305+import os, sys
306+
307+def run(wsgi_app):
308+    #if sys.argv.:
309+    #    instancedir=sys.argv[1]
310+    #else
311+    instancedir=''
312+       
313+    stream=sys.stdout
314+
315+    environ = dict(os.environ.items())
316+    environ['wsgi.input']        = sys.stdin
317+    environ['wsgi.errors']       = sys.stderr
318+    environ['wsgi.version']      = (1, 0)
319+    environ['wsgi.multithread']  = False
320+    environ['wsgi.multiprocess'] = True
321+    environ['wsgi.run_once']    = True
322+
323+    if environ.get('HTTPS','off') in ('on','1'):
324+        environ['wsgi.url_scheme'] = 'https'
325+    else:
326+        environ['wsgi.url_scheme'] = 'http'
327+
328+    headers_set = []
329+    headers_sent = []
330+
331+    def write(data):
332+        if not headers_set:
333+            raise AssertionError("write() before start_response()")
334+
335+        elif not headers_sent:
336+            # Before the first output, send the stored headers
337+            status, response_headers = headers_sent[:] = headers_set
338+            stream.write('Status: %s\r\n' % status)
339+            for header in response_headers:
340+                stream.write('%s: %s\r\n' % header)
341+            stream.write('\r\n')
342+
343+        stream.write(data)
344+        stream.flush()
345+
346+    def start_response(status, response_headers, exc_info=None):
347+        if exc_info:
348+            try:
349+                if headers_sent:
350+                    # Re-raise original exception if headers sent
351+                    raise exc_info[0], exc_info[1], exc_info[2]
352+            finally:
353+                exc_info = None     # avoid dangling circular ref
354+        elif headers_set:
355+            raise AssertionError("Headers already set!")
356+
357+        headers_set[:] = [status, response_headers]
358+        return write
359+
360+    result = wsgi_app(environ, start_response)
361+    try:
362+        for data in result:
363+            if data:    # don't send headers until body appears
364+                write(data)
365+        if not headers_sent:
366+            write('')   # send headers now if body was empty
367+    finally:
368+        if hasattr(result,'close'):
369+            result.close()
370+
371Index: editor/filemanager/upload/py/modpython_gateway.py
372===================================================================
373--- editor/filemanager/upload/py/modpython_gateway.py   (revisión: 0)
374+++ editor/filemanager/upload/py/modpython_gateway.py   (revisión: 0)
375@@ -0,0 +1,212 @@
376+"""
377+WSGI wrapper for mod_python. Requires Python 2.2 or greater.
378+
379+
380+Example httpd.conf section for a CherryPy app called "mcontrol":
381+
382+<Location /mcontrol>
383+    SetHandler python-program
384+    PythonFixupHandler mcontrol.cherry::startup
385+    PythonHandler modpython_gateway::handler
386+    PythonOption wsgi.application cherrypy._cpwsgi::wsgiApp
387+</Location>
388+
389+Some WSGI implementations assume that the SCRIPT_NAME environ variable will
390+always be equal to "the root URL of the app"; Apache probably won't act as
391+you expect in that case. You can add another PythonOption directive to tell
392+modpython_gateway to force that behavior:
393+
394+    PythonOption SCRIPT_NAME /mcontrol
395+
396+Some WSGI applications need to be cleaned up when Apache exits. You can
397+register a cleanup handler with yet another PythonOption directive:
398+
399+    PythonOption wsgi.cleanup module::function
400+
401+The module.function will be called with no arguments on server shutdown,
402+once for each child process or thread.
403+"""
404+
405+import traceback
406+
407+from mod_python import apache
408+
409+
410+class InputWrapper(object):
411+   
412+    def __init__(self, req):
413+        self.req = req
414+   
415+    def close(self):
416+        pass
417+   
418+    def read(self, size=-1):
419+        return self.req.read(size)
420+   
421+    def readline(self, size=-1):
422+        return self.req.readline(size)
423+   
424+    def readlines(self, hint=-1):
425+        return self.req.readlines(hint)
426+   
427+    def __iter__(self):
428+        line = self.readline()
429+        while line:
430+            yield line
431+            # Notice this won't prefetch the next line; it only
432+            # gets called if the generator is resumed.
433+            line = self.readline()
434+
435+
436+class ErrorWrapper(object):
437+   
438+    def __init__(self, req):
439+        self.req = req
440+   
441+    def flush(self):
442+        pass
443+   
444+    def write(self, msg):
445+        self.req.log_error(msg)
446+   
447+    def writelines(self, seq):
448+        self.write(''.join(seq))
449+
450+
451+bad_value = ("You must provide a PythonOption '%s', either 'on' or 'off', "
452+             "when running a version of mod_python < 3.1")
453+
454+
455+class Handler:
456+   
457+    def __init__(self, req):
458+        self.started = False
459+       
460+        options = req.get_options()
461+       
462+        # Threading and forking
463+        try:
464+            q = apache.mpm_query
465+            threaded = q(apache.AP_MPMQ_IS_THREADED)
466+            forked = q(apache.AP_MPMQ_IS_FORKED)
467+        except AttributeError:
468+            threaded = options.get('multithread', '').lower()
469+            if threaded == 'on':
470+                threaded = True
471+            elif threaded == 'off':
472+                threaded = False
473+            else:
474+                raise ValueError(bad_value % "multithread")
475+           
476+            forked = options.get('multiprocess', '').lower()
477+            if forked == 'on':
478+                forked = True
479+            elif forked == 'off':
480+                forked = False
481+            else:
482+                raise ValueError(bad_value % "multiprocess")
483+       
484+        env = self.environ = dict(apache.build_cgi_env(req))
485+       
486+        if 'SCRIPT_NAME' in options:
487+            # Override SCRIPT_NAME and PATH_INFO if requested.
488+            env['SCRIPT_NAME'] = options['SCRIPT_NAME']
489+            env['PATH_INFO'] = req.uri[len(options['SCRIPT_NAME']):]
490+       
491+        env['wsgi.input'] = InputWrapper(req)
492+        env['wsgi.errors'] = ErrorWrapper(req)
493+        env['wsgi.version'] = (1,0)
494+        env['wsgi.run_once'] = False
495+        if env.get("HTTPS") in ('yes', 'on', '1'):
496+            env['wsgi.url_scheme'] = 'https'
497+        else:
498+            env['wsgi.url_scheme'] = 'http'
499+        env['wsgi.multithread']  = threaded
500+        env['wsgi.multiprocess'] = forked
501+       
502+        self.request = req
503+   
504+    def run(self, application):
505+        # 20070226: DISABLE Exception Handling to be directy handled by wsgihandler
506+        #try:
507+            result = application(self.environ, self.start_response)
508+            for data in result:
509+                self.write(data)
510+            if not self.started:
511+                self.request.set_content_length(0)
512+            if hasattr(result, 'close'):
513+                result.close()
514+        #except:
515+        #    traceback.print_exc(None, self.environ['wsgi.errors'])
516+        #    if not self.started:
517+        #        self.request.status = 500
518+        #        self.request.content_type = 'text/plain'
519+        #        data = "A server error occurred. Please contact the administrator."
520+        #        self.request.set_content_length(len(data))
521+        #        self.request.write(data)
522+   
523+    def start_response(self, status, headers, exc_info=None):
524+        if exc_info:
525+            try:
526+                if self.started:
527+                    raise exc_info[0], exc_info[1], exc_info[2]
528+            finally:
529+                exc_info = None
530+       
531+        self.request.status = int(status[:3])
532+       
533+        for key, val in headers:
534+            if key.lower() == 'content-length':
535+                self.request.set_content_length(int(val))
536+            elif key.lower() == 'content-type':
537+                self.request.content_type = val
538+            else:
539+                self.request.headers_out.add(key, val)
540+       
541+        return self.write
542+   
543+    def write(self, data):
544+        if not self.started:
545+            self.started = True
546+        self.request.write(data)
547+
548+
549+startup = None
550+cleanup = None
551+
552+def handler(req):
553+    # Run a startup function if requested.
554+    global startup
555+    if not startup:
556+        func = req.get_options().get('wsgi.startup')
557+        if func:
558+            module_name, object_str = func.split('::', 1)
559+            module = __import__(module_name, globals(), locals(), [''])
560+            startup = apache.resolve_object(module, object_str)
561+            startup(req)
562+   
563+    # Register a cleanup function if requested.
564+    global cleanup
565+    if not cleanup:
566+        func = req.get_options().get('wsgi.cleanup')
567+        if func:
568+            module_name, object_str = func.split('::', 1)
569+            module = __import__(module_name, globals(), locals(), [''])
570+            cleanup = apache.resolve_object(module, object_str)
571+            def cleaner(data):
572+                cleanup()
573+            try:
574+                # apache.register_cleanup wasn't available until 3.1.4.
575+                apache.register_cleanup(cleaner)
576+            except AttributeError:
577+                req.server.register_cleanup(req, cleaner)
578+   
579+    # Import the wsgi 'application' callable and pass it to Handler.run
580+    modname, objname = req.get_options()['wsgi.application'].split('::', 1)
581+    module = __import__(modname, globals(), locals(), [''])
582+    app = getattr(module, objname)
583+    Handler(req).run(app)
584+   
585+    # status was set in Handler; always return apache.OK
586+    return apache.OK
587+
588Index: editor/filemanager/upload/py/wsgihandler.py
589===================================================================
590--- editor/filemanager/upload/py/wsgihandler.py (revisión: 0)
591+++ editor/filemanager/upload/py/wsgihandler.py (revisión: 0)
592@@ -0,0 +1,123 @@
593+# -*- coding: utf-8 -*-
594+"""
595+    WSGI Handler form Mod Python:
596+   
597+    This module implement cgihandler-like functionality but for WSGI.
598+    It allows to call standalone WSGI script without too much configuration,
599+    and keep serving static files in the same directory (ala PHP)
600+
601+    Each script (.py) must contain a WSGI compilant callable named WSGIApp
602+
603+    Use .htaccess:
604+        AddHandler mod_python .py
605+        PythonHandler wsgihandler
606+
607+    This need either modpywsgi.py or modpython_gateway.py (WSGI gateways) be
608+    present inside python path.
609+   
610+    If this script is stored inside python path (normally site-packages),
611+    no PythonPath directive is needed (script directory is appended to
612+    sys.path), so you could import modules in script directory normally.
613+   
614+    If you cannot install both scripts in site-packages, just modify .htaccess:
615+        AddHandler mod_python .py
616+        PythonHandler wsgihandler
617+        PythonPath "['/your/script/path'] + sys.path"
618+    And copy modpywsgi.py or modpython_gateway.py and wsgihandler.py with your
619+    script.
620+   
621+    license: GNU GPL
622+"""
623+
624+# Copyright (C) 2007 Mariano Reingart <mr@nsis.com.ar>
625+
626+# This program is free software; you can redistribute it and/or modify
627+# it under the terms of the GNU General Public License as published by
628+# the Free Software Foundation; either version 2 of the License, or
629+# (at your option) any later version.
630+
631+# This program is distributed in the hope that it will be useful, but
632+# WITHOUT ANY WARRANTY; without even the implied warranty of
633+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
634+# General Public License for more details.
635+
636+# You should have received a copy of the GNU General Public License
637+# along with this program; if not, write to the Free Software
638+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
639+# USA
640+
641+import os
642+import sys
643+from mod_python import apache
644+
645+try:
646+    # first, try to import "official" modpython wsgi gateway
647+    import modpython_gateway
648+    srv=modpython_gateway.Handler
649+except ImportError:
650+    try:
651+        import modpywsgi
652+        srv=modpywsgi.WSGIServer
653+    except ImportError:
654+        # sorry, no gateway found, raise apache error
655+        raise apache.SERVER_RETURN, apache.HTTP_BAD_GATEWAY
656+
657+__author__ = 'Mariano Reingart <mr@nsis.com.ar>'
658+
659+# keep original modules, in order to refresh user ones
660+# (only in development, to prevent restarting apache to apply changes)
661+original = sys.modules.keys()
662+# find out the standard library location
663+stdlib, x = os.path.split(os.__file__)
664+
665+def handler(req):
666+    options=req.get_options()
667+
668+    # this allows make changes to source files and get them imported without
669+    # restarting apache
670+    if options.get('reload-modules', '').lower()=='yes':   
671+        for m in sys.modules.keys():
672+            if m not in original:
673+                # unless they are part of standard library
674+                mod = sys.modules[m]
675+                if hasattr(mod, "__file__"):
676+                    path, x = os.path.split(mod.__file__)
677+                    if path != stdlib:
678+                        del sys.modules[m]
679+                   
680+    # get the filename of the script (copied from cgihandler)
681+    if req.subprocess_env.has_key("script_filename"):
682+        dir, file = os.path.split(req.subprocess_env["script_filename"])
683+    else:
684+        dir, file = os.path.split(req.filename)
685+
686+    module_name, ext = os.path.splitext(file)
687+
688+    # automagically append script directory to sys.path
689+    if dir not in sys.path:
690+        sys.path.append(dir)
691+   
692+    try:
693+        module = __import__(module_name)
694+    except ImportError:
695+        raise apache.SERVER_RETURN, apache.HTTP_NOT_FOUND
696+   
697+    app = getattr(module, "WSGIApp")
698+
699+    try:       
700+        # create server and run WSGIApp
701+        if srv.__name__ == 'WSGIServer':
702+            # this is to prevent that modpywsgi alter SCRIPT_NAME
703+            options['untouched_scriptname']='yes' 
704+            srv(app).run(req)
705+        elif srv.__name__ == 'Handler':
706+            srv(req).run(app)
707+    except:
708+        # print fancy exception output
709+        import cgitb
710+        req.status = int(200)       
711+        req.content_type = "text/html"
712+        req.write(cgitb.html(sys.exc_info()))
713+   
714+    # allways return apache.OK (status was set in Handler)     
715+    return apache.OK
© 2003 – 2022, CKSource sp. z o.o. sp.k. All rights reserved. | Terms of use | Privacy policy