mirror of
https://github.com/Hopiu/linkchecker.git
synced 2026-04-21 22:54:45 +00:00
readding files
git-svn-id: https://linkchecker.svn.sourceforge.net/svnroot/linkchecker/trunk/linkchecker@192 e7d03fd6-7b0d-0410-9947-9c21f3af8025
This commit is contained in:
parent
27ae52dd56
commit
40f7cd55ca
9 changed files with 1875 additions and 0 deletions
|
|
@ -7,3 +7,4 @@ MANIFEST
|
|||
VERSION
|
||||
LinkCheckerConf.py
|
||||
locale
|
||||
Packages.gz
|
||||
|
|
|
|||
34
debian/postinst
vendored
Executable file
34
debian/postinst
vendored
Executable file
|
|
@ -0,0 +1,34 @@
|
|||
#! /bin/sh
|
||||
#
|
||||
# Written 1998 by Gregor Hoffleit <flight@debian.org>.
|
||||
# used by Bastian Kleineidam for LinkChecker
|
||||
|
||||
set -e
|
||||
|
||||
DIRLIST="/usr/lib/python1.5/site-packages/linkcheck"
|
||||
FILELIST="CSV.py LinkCheckerConf.py StringUtil.py fcgi.py fintl.py
|
||||
http11lib.py httpslib.py robotparser2.py sz_fcgi.py util1.py"
|
||||
SITEPACKAGES="/usr/lib/python1.5/site-packages"
|
||||
COMMAND="'import sys,py_compile;py_compile.compile(sys.argv[1])'"
|
||||
|
||||
case "$1" in
|
||||
configure|abort-upgrade|abort-remove|abort-deconfigure)
|
||||
for i in $DIRLIST; do
|
||||
python -O /usr/lib/python1.5/compileall.py -q $i
|
||||
python /usr/lib/python1.5/compileall.py -q $i
|
||||
done
|
||||
# use /bin/sh -c, otherwise I get a SyntaxError from Python
|
||||
for i in $FILELIST; do
|
||||
/bin/sh -c "python -O -c $COMMAND $SITEPACKAGES/$i"
|
||||
/bin/sh -c "python -c $COMMAND $SITEPACKAGES/$i"
|
||||
done
|
||||
;;
|
||||
*)
|
||||
echo "postinst called with unknown argument \`$1'" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
#DEBHELPER#
|
||||
|
||||
exit 0
|
||||
18
debian/prerm
vendored
Executable file
18
debian/prerm
vendored
Executable file
|
|
@ -0,0 +1,18 @@
|
|||
#! /bin/sh
|
||||
#
|
||||
# Written 1998 by Gregor Hoffleit <flight@debian.org>.
|
||||
# used by Bastian Kleineidam for LinkChecker
|
||||
|
||||
set -e
|
||||
|
||||
PACKAGE=linkchecker
|
||||
|
||||
dpkg --listfiles $PACKAGE |
|
||||
awk '$0~/\.py$/ {print $0"c\n" $0"o"}' |
|
||||
xargs rm -f >&2
|
||||
|
||||
rmdir /usr/lib/python1.5/site-packages/linkcheck 2>/dev/null || true
|
||||
|
||||
#DEBHELPER#
|
||||
|
||||
exit 0
|
||||
208
fintl.py
Normal file
208
fintl.py
Normal file
|
|
@ -0,0 +1,208 @@
|
|||
## vim:ts=4:et:nowrap
|
||||
"""i18n (multiple language) support. Reads .mo files from GNU gettext msgfmt
|
||||
|
||||
If you want to prepare your Python programs for i18n you could simply
|
||||
add the following lines to the top of a BASIC_MAIN module of your py-program:
|
||||
try:
|
||||
import fintl
|
||||
gettext = fintl.gettext
|
||||
fintl.bindtextdomain(YOUR_PROGRAM, YOUR_LOCALEDIR)
|
||||
fintl.textdomain(YOUR_PROGRAM)
|
||||
except ImportError:
|
||||
def gettext(msg):
|
||||
return msg
|
||||
_ = gettext
|
||||
and/or also add the following to the top of any module containing messages:
|
||||
import BASIC_MAIN
|
||||
_ = BASIC_MAIN.gettext
|
||||
|
||||
Now you could use _("....") everywhere instead of "...." for message texts.
|
||||
|
||||
Once you have written your internationalized program, you can use
|
||||
the suite of utility programs contained in the GNU gettext package to aid
|
||||
the translation into other languages.
|
||||
|
||||
You ARE NOT REQUIRED to release the sourcecode of your program, since
|
||||
linking of your program against GPL code is avoided by this module.
|
||||
Although it is possible to use the GNU gettext library by using the
|
||||
*intl.so* module written by Martin von Löwis if this is available. But it is
|
||||
not required to use it in the first place.
|
||||
"""
|
||||
# Copyright 1999 by <mailto: pf@artcom-gmbh.de> (Peter Funk)
|
||||
#
|
||||
# All Rights Reserved
|
||||
#
|
||||
# Permission to use, copy, modify, and distribute this software and its
|
||||
# documentation for any purpose and without fee is hereby granted,
|
||||
# provided that the above copyright notice appear in all copies.
|
||||
|
||||
# ArtCom GmbH AND Peter Funk DISCLAIMS ALL WARRANTIES WITH REGARD TO
|
||||
# THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
# AND FITNESS, IN NO EVENT SHALL ArtCom GmBH or Peter Funk BE LIABLE
|
||||
# FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
|
||||
# AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
|
||||
# OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
_default_localedir = '/usr/share/locale'
|
||||
_default_domain = 'python'
|
||||
|
||||
# check out, if Martin v. Löwis 'intl' module interface to the GNU gettext
|
||||
# library is available and use it only, if it is available:
|
||||
try:
|
||||
from intl import *
|
||||
except ImportError:
|
||||
# now do what the gettext library provides in pure Python:
|
||||
error = 'fintl.error'
|
||||
# some globals preserving state:
|
||||
_languages = []
|
||||
_default_mo = None # This is default message outfile used by 'gettext'
|
||||
_loaded_mos = {} # This is a dictionary of loaded message output files
|
||||
|
||||
# some small little helper routines:
|
||||
def _check_env():
|
||||
"""examine language enviroment variables and return list of languages"""
|
||||
# TODO: This should somehow try to find out locale information on
|
||||
# Non-unix platforms like WinXX and MacOS. Suggestions welcome!
|
||||
languages = []
|
||||
import os, string
|
||||
for envvar in ('LANGUAGE', 'LC_ALL', 'LC_MESSAGES', 'LANG'):
|
||||
if os.environ.has_key(envvar):
|
||||
languages = string.split(os.environ[envvar], ':')
|
||||
break
|
||||
# use locale 'C' as default fallback:
|
||||
if 'C' not in _languages:
|
||||
languages.append('C')
|
||||
return languages
|
||||
|
||||
# Utility function used to decode binary .mo file header and seek tables:
|
||||
def _decode_Word(bin):
|
||||
# This assumes little endian (intel, vax) byte order.
|
||||
return ord(bin[0]) + (ord(bin[1]) << 8) + \
|
||||
(ord(bin[2]) << 16) + (ord(bin[3]) << 24)
|
||||
|
||||
# Now the methods designed to be used from outside:
|
||||
|
||||
def gettext(message):
|
||||
"""return localized version of a 'message' string"""
|
||||
if _default_mo is None:
|
||||
textdomain()
|
||||
return _default_mo.gettext(message)
|
||||
|
||||
_ = gettext
|
||||
|
||||
def dgettext(domain, message):
|
||||
"""like gettext but looks up 'message' in a special 'domain'"""
|
||||
# This may useful for larger software systems
|
||||
if not _loaded_mos.has_key(domain):
|
||||
raise error, "No '" + domain + "' message domain"
|
||||
return _loaded_mos[domain].gettext(message)
|
||||
|
||||
class _MoDict:
|
||||
"""read a .mo file into a python dictionary"""
|
||||
__MO_MAGIC = 0x950412de # Magic number of .mo files
|
||||
def __init__(self, domain=_default_domain, localedir=_default_localedir):
|
||||
global _languages
|
||||
self.catalog = {}
|
||||
self.domain = domain
|
||||
self.localedir = localedir
|
||||
# delayed access to environment variables:
|
||||
if not _languages:
|
||||
_languages = _check_env()
|
||||
for self.lang in _languages:
|
||||
if self.lang == 'C':
|
||||
return
|
||||
mo_filename = "%s//%s/LC_MESSAGES/%s.mo" % (
|
||||
localedir, self.lang, domain)
|
||||
try:
|
||||
buffer = open(mo_filename, "rb").read()
|
||||
break
|
||||
except IOError:
|
||||
pass
|
||||
else:
|
||||
return # assume C locale
|
||||
# Decode the header of the .mo file (5 little endian 32 bit words):
|
||||
if _decode_Word(buffer[:4]) != self.__MO_MAGIC :
|
||||
raise error, '%s seems not be a valid .mo file' % mo_filename
|
||||
self.mo_version = _decode_Word(buffer[4:8])
|
||||
num_messages = _decode_Word(buffer[8:12])
|
||||
master_index = _decode_Word(buffer[12:16])
|
||||
transl_index = _decode_Word(buffer[16:20])
|
||||
buf_len = len(buffer)
|
||||
# now put all messages from the .mo file buffer in the catalog dict:
|
||||
for i in xrange(0, num_messages):
|
||||
start_master= _decode_Word(buffer[master_index+4:master_index+8])
|
||||
end_master = start_master + \
|
||||
_decode_Word(buffer[master_index:master_index+4])
|
||||
start_transl= _decode_Word(buffer[transl_index+4:transl_index+8])
|
||||
end_transl = start_transl + \
|
||||
_decode_Word(buffer[transl_index:transl_index+4])
|
||||
if end_master <= buf_len and end_transl <= buf_len:
|
||||
self.catalog[buffer[start_master:end_master]]=\
|
||||
buffer[start_transl:end_transl]
|
||||
else:
|
||||
raise error, ".mo file '%s' is corrupt" % mo_filename
|
||||
# advance to the next entry in seek tables:
|
||||
master_index= master_index + 8
|
||||
transl_index= transl_index + 8
|
||||
|
||||
def gettext(self, message):
|
||||
"""return the translation of a given message"""
|
||||
try:
|
||||
return self.catalog[message]
|
||||
except KeyError:
|
||||
return message
|
||||
# _MoDict instances may be also accessed using mo[msg] or mo(msg):
|
||||
__getitem = gettext
|
||||
__call__ = gettext
|
||||
|
||||
def textdomain(domain=_default_domain):
|
||||
"""Sets the 'domain' to be used by this program. Defaults to 'python'"""
|
||||
global _default_mo
|
||||
if not _loaded_mos.has_key(domain):
|
||||
_loaded_mos[domain] = _MoDict(domain)
|
||||
_default_mo = _loaded_mos[domain]
|
||||
|
||||
def bindtextdomain(domain, localedir=_default_localedir):
|
||||
global _default_mo
|
||||
if not _loaded_mos.has_key(domain):
|
||||
_loaded_mos[domain] = _MoDict(domain, localedir)
|
||||
if _default_mo is not None:
|
||||
_default_mo = _loaded_mos[domain]
|
||||
|
||||
def translator(domain=_default_domain, localedir=_default_localedir):
|
||||
"""returns a gettext compatible function object
|
||||
|
||||
which is bound to the domain given as parameter"""
|
||||
pass # TODO implement this
|
||||
|
||||
def _testdriver(argv):
|
||||
message = ""
|
||||
domain = _default_domain
|
||||
localedir = _default_localedir
|
||||
if len(argv) > 1:
|
||||
message = argv[1]
|
||||
if len(argv) > 2:
|
||||
domain = argv[2]
|
||||
if len(argv) > 3:
|
||||
localedir = argv[3]
|
||||
# now perform some testing of this module:
|
||||
bindtextdomain(domain, localedir)
|
||||
textdomain(domain)
|
||||
info = gettext('') # this is where special info is often stored
|
||||
if info:
|
||||
print ".mo file for domain %s in %s contains:" % (domain, localedir)
|
||||
print info
|
||||
else:
|
||||
print ".mo file contains no info"
|
||||
if message:
|
||||
print "Translation of '"+ message+ "' is '"+ _(message)+ "'"
|
||||
else:
|
||||
for msg in ("Cancel", "No", "OK", "Quit", "Yes"):
|
||||
print "Translation of '"+ msg + "' is '"+ _(msg)+ "'"
|
||||
|
||||
if __name__ == '__main__':
|
||||
import sys
|
||||
if len(sys.argv) > 1 and (sys.argv[1] == "-h" or sys.argv[1] == "-?"):
|
||||
print "Usage :", sys.argv[0], "[ MESSAGE [ DOMAIN [ LOCALEDIR ]]]"
|
||||
_testdriver(sys.argv)
|
||||
394
http11lib.py
Normal file
394
http11lib.py
Normal file
|
|
@ -0,0 +1,394 @@
|
|||
#
|
||||
# HTTP/1.1 client library
|
||||
#
|
||||
# Copyright (C) 1998-1999 Guido van Rossum. All Rights Reserved.
|
||||
# Written by Greg Stein. Given to Guido. Licensed using the Python license.
|
||||
#
|
||||
# This module is maintained by Greg and is available at:
|
||||
# http://www.lyra.org/greg/python/httplib.py
|
||||
#
|
||||
# Since this isn't in the Python distribution yet, we'll use the CVS ID
|
||||
# for tracking:
|
||||
# $Id$
|
||||
#
|
||||
# Modified by Bastian Kleineidam to squish a bug.
|
||||
|
||||
import socket,string,mimetools,httplib
|
||||
|
||||
|
||||
error = __name__ + '.error'
|
||||
|
||||
HTTP_PORT = 80
|
||||
|
||||
class HTTPResponse(mimetools.Message):
|
||||
def __init__(self, fp, version, errcode):
|
||||
mimetools.Message.__init__(self, fp, 0)
|
||||
|
||||
if version == 'HTTP/1.0':
|
||||
self.version = 10
|
||||
elif version[:7] == 'HTTP/1.':
|
||||
self.version = 11 # use HTTP/1.1 code for HTTP/1.x where x>=1
|
||||
else:
|
||||
raise error, 'unknown HTTP protocol'
|
||||
|
||||
# are we using the chunked-style of transfer encoding?
|
||||
tr_enc = self.getheader('transfer-encoding')
|
||||
if tr_enc:
|
||||
if string.lower(tr_enc) != 'chunked':
|
||||
raise error, 'unknown transfer-encoding'
|
||||
self.chunked = 1
|
||||
self.chunk_left = None
|
||||
else:
|
||||
self.chunked = 0
|
||||
|
||||
# will the connection close at the end of the response?
|
||||
conn = self.getheader('connection')
|
||||
if conn:
|
||||
conn = string.lower(conn)
|
||||
# a "Connection: close" will always close the connection. if we
|
||||
# don't see that and this is not HTTP/1.1, then the connection will
|
||||
# close unless we see a Keep-Alive header.
|
||||
self.will_close = string.find(conn, 'close') != -1 or \
|
||||
( self.version != 11 and \
|
||||
not self.getheader('keep-alive') )
|
||||
else:
|
||||
# for HTTP/1.1, the connection will always remain open
|
||||
# otherwise, it will remain open IFF we see a Keep-Alive header
|
||||
self.will_close = self.version != 11 and \
|
||||
not self.getheader('keep-alive')
|
||||
|
||||
# do we have a Content-Length?
|
||||
# NOTE: RFC 2616, S4.4, #3 states we ignore this if tr_enc is "chunked"
|
||||
length = self.getheader('content-length')
|
||||
if length and not self.chunked:
|
||||
self.length = int(length)
|
||||
else:
|
||||
self.length = None
|
||||
|
||||
# does the body have a fixed length? (of zero)
|
||||
if (errcode == 204 or # No Content
|
||||
errcode == 304 or # Not Modified
|
||||
100 <= errcode < 200): # 1xx codes
|
||||
self.length = 0
|
||||
|
||||
# if the connection remains open, and we aren't using chunked, and
|
||||
# a content-length was not provided, then assume that the connection
|
||||
# WILL close.
|
||||
if not self.will_close and \
|
||||
not self.chunked and \
|
||||
self.length is None:
|
||||
self.will_close = 1
|
||||
|
||||
|
||||
def close(self):
|
||||
if self.fp:
|
||||
self.fp.close()
|
||||
self.fp = None
|
||||
|
||||
|
||||
def isclosed(self):
|
||||
# NOTE: it is possible that we will not ever call self.close(). This
|
||||
# case occurs when will_close is TRUE, length is None, and we
|
||||
# read up to the last byte, but NOT past it.
|
||||
#
|
||||
# IMPLIES: if will_close is FALSE, then self.close() will ALWAYS be
|
||||
# called, meaning self.isclosed() is meaningful.
|
||||
return self.fp is None
|
||||
|
||||
|
||||
def read(self, amt=None):
|
||||
if not self.fp:
|
||||
return ''
|
||||
|
||||
if self.chunked:
|
||||
chunk_left = self.chunk_left
|
||||
value = ''
|
||||
while 1:
|
||||
if not chunk_left:
|
||||
line = self.fp.readline()
|
||||
i = string.find(line, ';')
|
||||
if i >= 0:
|
||||
line = line[:i] # strip chunk-extensions
|
||||
chunk_left = string.atoi(line, 16)
|
||||
if chunk_left == 0:
|
||||
break
|
||||
if not amt:
|
||||
value = value + self.fp.read(chunk_left)
|
||||
elif amt < chunk_left:
|
||||
value = value + self.fp.read(amt)
|
||||
self.chunk_left = chunk_left - amt
|
||||
return value
|
||||
elif amt == chunk_left:
|
||||
value = value + self.fp.read(amt)
|
||||
self.fp.read(2) # toss the CRLF at the end of the chunk
|
||||
self.chunk_left = None
|
||||
return value
|
||||
else:
|
||||
value = value + self.fp.read(chunk_left)
|
||||
amt = amt - chunk_left
|
||||
|
||||
# we read the whole chunk, get another
|
||||
self.fp.read(2) # toss the CRLF at the end of the chunk
|
||||
chunk_left = None
|
||||
|
||||
# read and discard trailer up to the CRLF terminator
|
||||
### note: we shouldn't have any trailers!
|
||||
while 1:
|
||||
line = self.fp.readline()
|
||||
if line == '\r\n':
|
||||
break
|
||||
|
||||
# we read everything; close the "file"
|
||||
self.close()
|
||||
|
||||
return value
|
||||
|
||||
elif not amt:
|
||||
# unbounded read
|
||||
if self.will_close:
|
||||
s = self.fp.read()
|
||||
else:
|
||||
s = self.fp.read(self.length)
|
||||
self.close() # we read everything
|
||||
return s
|
||||
|
||||
if self.length is not None:
|
||||
if amt > self.length:
|
||||
# clip the read to the "end of response"
|
||||
amt = self.length
|
||||
self.length = self.length - amt
|
||||
|
||||
s = self.fp.read(amt)
|
||||
|
||||
# close our "file" if we know we should
|
||||
### I'm not sure about the len(s) < amt part; we should be safe because
|
||||
### we shouldn't be using non-blocking sockets
|
||||
if self.length == 0 or len(s) < amt:
|
||||
self.close()
|
||||
|
||||
return s
|
||||
|
||||
|
||||
class HTTPConnection:
|
||||
|
||||
_http_vsn = 11
|
||||
_http_vsn_str = 'HTTP/1.1'
|
||||
|
||||
response_class = HTTPResponse
|
||||
|
||||
def __init__(self, host, port=None):
|
||||
self.sock = None
|
||||
self.response = None
|
||||
self._set_hostport(host, port)
|
||||
|
||||
def _set_hostport(self, host, port):
|
||||
if port is None:
|
||||
i = string.find(host, ':')
|
||||
if i >= 0:
|
||||
port = int(host[i+1:])
|
||||
host = host[:i]
|
||||
else:
|
||||
port = HTTP_PORT
|
||||
self.host = host
|
||||
self.port = port
|
||||
|
||||
def connect(self):
|
||||
"""Connect to the host and port specified in __init__."""
|
||||
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
self.sock.connect((self.host, self.port))
|
||||
|
||||
def close(self):
|
||||
"""Close the connection to the HTTP server."""
|
||||
if self.sock:
|
||||
self.sock.close() # close it manually... there may be other refs
|
||||
self.sock = None
|
||||
if self.response:
|
||||
self.response.close()
|
||||
self.response = None
|
||||
|
||||
def send(self, str):
|
||||
"""Send `str' to the server."""
|
||||
if not self.sock:
|
||||
self.connect()
|
||||
|
||||
# send the data to the server. if we get a broken pipe, then close
|
||||
# the socket. we want to reconnect when somebody tries to send again.
|
||||
#
|
||||
# NOTE: we DO propagate the error, though, because we cannot simply
|
||||
# ignore the error... the caller will know if they can retry.
|
||||
try:
|
||||
self.sock.send(str)
|
||||
except socket.error, v:
|
||||
if v[0] == 32: # Broken pipe
|
||||
self.close()
|
||||
raise
|
||||
|
||||
def putrequest(self, method, url='/'):
|
||||
"""Send a request to the server.
|
||||
|
||||
`method' specifies an HTTP request method, e.g. 'GET'.
|
||||
`url' specifies the object being requested, e.g.
|
||||
'/index.html'.
|
||||
"""
|
||||
if self.response:
|
||||
if not self.response.isclosed():
|
||||
### implies half-duplex!
|
||||
raise error, 'prior response has not been fully handled'
|
||||
self.response = None
|
||||
|
||||
if not url:
|
||||
url = '/'
|
||||
str = '%s %s %s\r\n' % (method, url, self._http_vsn_str)
|
||||
|
||||
try:
|
||||
self.send(str)
|
||||
except socket.error, v:
|
||||
if v[0] != 32: # Broken pipe
|
||||
raise
|
||||
# try one more time (the socket was closed; this will reopen)
|
||||
self.send(str)
|
||||
|
||||
#self.putheader('Host', self.host)
|
||||
|
||||
if self._http_vsn == 11:
|
||||
# Issue some standard headers for better HTTP/1.1 compliance
|
||||
|
||||
# note: we are assuming that clients will not attempt to set these
|
||||
# headers since *this* library must deal with the consequences.
|
||||
# this also means that when the supporting libraries are
|
||||
# updated to recognize other forms, then this code should be
|
||||
# changed (removed or updated).
|
||||
|
||||
# we only want a Content-Encoding of "identity" since we don't
|
||||
# support encodings such as x-gzip or x-deflate.
|
||||
self.putheader('Accept-Encoding', 'identity')
|
||||
|
||||
# we can accept "chunked" Transfer-Encodings, but no others
|
||||
# NOTE: no TE header implies *only* "chunked"
|
||||
#self.putheader('TE', 'chunked')
|
||||
|
||||
# if TE is supplied in the header, then it must appear in a
|
||||
# Connection header.
|
||||
#self.putheader('Connection', 'TE')
|
||||
|
||||
else:
|
||||
# For HTTP/1.0, the server will assume "not chunked"
|
||||
pass
|
||||
|
||||
def putheader(self, header, value):
|
||||
"""Send a request header line to the server.
|
||||
|
||||
For example: h.putheader('Accept', 'text/html')
|
||||
"""
|
||||
str = '%s: %s\r\n' % (header, value)
|
||||
self.send(str)
|
||||
|
||||
def endheaders(self):
|
||||
"""Indicate that the last header line has been sent to the server."""
|
||||
|
||||
self.send('\r\n')
|
||||
|
||||
def request(self, method, url='/', body=None, headers={}):
|
||||
"""Send a complete request to the server."""
|
||||
|
||||
self.putrequest(method, url)
|
||||
|
||||
if body:
|
||||
self.putheader('Content-Length', str(len(body)))
|
||||
for hdr, value in headers.items():
|
||||
self.putheader(hdr, value)
|
||||
self.endheaders()
|
||||
|
||||
if body:
|
||||
self.send(body)
|
||||
|
||||
def getreply(self):
|
||||
"""Get a reply from the server.
|
||||
|
||||
Returns a tuple consisting of:
|
||||
- server response code (e.g. '200' if all goes well)
|
||||
- server response string corresponding to response code
|
||||
- any RFC822 headers in the response from the server
|
||||
|
||||
"""
|
||||
file = self.sock.makefile('rb')
|
||||
line = file.readline()
|
||||
try:
|
||||
[ver, code, msg] = string.split(line, None, 2)
|
||||
except ValueError:
|
||||
try:
|
||||
[ver, code] = string.split(line, None, 1)
|
||||
msg = ""
|
||||
except ValueError:
|
||||
self.close()
|
||||
return -1, line, file
|
||||
if ver[:5] != 'HTTP/':
|
||||
self.close()
|
||||
return -1, line, file
|
||||
errcode = int(code)
|
||||
errmsg = string.strip(msg)
|
||||
response = self.response_class(file, ver, errcode)
|
||||
if response.will_close:
|
||||
# this effectively passes the connection to the response
|
||||
self.close()
|
||||
else:
|
||||
# remember this, so we can tell when it is complete
|
||||
self.response = response
|
||||
return errcode, errmsg, response
|
||||
|
||||
|
||||
class HTTP(HTTPConnection):
|
||||
"Compatibility class with httplib.py from 1.5."
|
||||
|
||||
_http_vsn = 10
|
||||
_http_vsn_str = 'HTTP/1.0'
|
||||
|
||||
def __init__(self, host='', port=None):
|
||||
"Provide a default host, since the superclass requires one."
|
||||
|
||||
# Note that we may pass an empty string as the host; this will throw
|
||||
# an error when we attempt to connect. Presumably, the client code
|
||||
# will call connect before then, with a proper host.
|
||||
HTTPConnection.__init__(self, host, port)
|
||||
self.debuglevel=0
|
||||
|
||||
def connect(self, host=None, port=None):
|
||||
"Accept arguments to set the host/port, since the superclass doesn't."
|
||||
|
||||
if host:
|
||||
self._set_hostport(host, port)
|
||||
HTTPConnection.connect(self)
|
||||
|
||||
def set_debuglevel(self, debuglevel):
|
||||
self.debuglevel=debuglevel
|
||||
|
||||
def getfile(self):
|
||||
"Provide a getfile, since the superclass' use of HTTP/1.1 prevents it."
|
||||
return self.file
|
||||
|
||||
def putheader(self, header, *values):
|
||||
"The superclass allows only one value argument."
|
||||
HTTPConnection.putheader(self, header, string.joinfields(values,'\r\n\t'))
|
||||
|
||||
def getreply(self):
|
||||
"Compensate for an instance attribute shuffling."
|
||||
errcode, errmsg, response = HTTPConnection.getreply(self)
|
||||
if errcode == -1:
|
||||
self.file = response # response is the "file" when errcode==-1
|
||||
self.headers = None
|
||||
return -1, errmsg, None
|
||||
|
||||
self.headers = response
|
||||
self.file = response.fp
|
||||
return errcode, errmsg, response
|
||||
|
||||
def _test():
|
||||
h = HTTP('www.siemens.de')
|
||||
h.putrequest("GET")
|
||||
h.putheader("Host", 'www.siemens.de')
|
||||
h.endheaders()
|
||||
status,text,reply = h.getreply()
|
||||
print status,text,reply
|
||||
|
||||
if __name__=='__main__':
|
||||
_test()
|
||||
170
httpslib.py
Normal file
170
httpslib.py
Normal file
|
|
@ -0,0 +1,170 @@
|
|||
# @(#)httpslib.py 1.1 VMS-99/01/30 https support
|
||||
|
||||
import ssl,httplib,string,socket,mimetools
|
||||
|
||||
HTTP_PREF = 'HTTP/'
|
||||
HTTPS_PORT = 443
|
||||
|
||||
class HTTPS(httplib.HTTP):
|
||||
|
||||
def connect (self, host, port = 0):
|
||||
"""Connect to a host on a given port.
|
||||
|
||||
Note: This method is automatically invoked by __init__,
|
||||
if a host is specified during instantiation.
|
||||
|
||||
"""
|
||||
if not port:
|
||||
i = string.find(host, ':')
|
||||
if i >= 0:
|
||||
host, port = host[:i], host[i+1:]
|
||||
try: port = string.atoi(port)
|
||||
except string.atoi_error:
|
||||
raise socket.error, "nonnumeric port"
|
||||
if not port: port = HTTPS_PORT
|
||||
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
if self.debuglevel > 0: print 'connect:', (host, port)
|
||||
self.sock.connect(host, port)
|
||||
self.ssl = ssl.ssl(self.sock.fileno())
|
||||
|
||||
def send (self, str):
|
||||
if self.debuglevel > 0: print 'send:', `str`
|
||||
self.ssl.write(str,len(str))
|
||||
|
||||
def makefile (self, mode='r', bufsize=-1):
|
||||
return _fileobject(self.sock,self.ssl,mode,bufsize)
|
||||
|
||||
def getreply (self):
|
||||
self.file = self.makefile('rb')
|
||||
# self.sock = None
|
||||
line = self.file.readline()
|
||||
if self.debuglevel > 0: print 'reply:',`line`
|
||||
try:
|
||||
[ver,code,msg] = string.split(line,None,2)
|
||||
except ValueError:
|
||||
try:
|
||||
[ver,code] = string.split(line,None,1)
|
||||
msg = ""
|
||||
except ValueError:
|
||||
ver = ""
|
||||
if ver[:len(HTTP_PREF)] != HTTP_PREF:
|
||||
self.headers = None
|
||||
return -1, line, self.headers
|
||||
self.headers = mimetools.Message(self.file,0)
|
||||
return string.atoi(code), string.strip(msg), self.headers
|
||||
|
||||
def close (self):
|
||||
if self.file:
|
||||
self.file.close()
|
||||
self.file = self.sock = self.ssl = None
|
||||
|
||||
class _fileobject:
|
||||
|
||||
def __init__ (self, sock, ssl, mode, bufsize):
|
||||
import string
|
||||
self._sock = sock
|
||||
self._ssl = ssl
|
||||
self._mode = mode
|
||||
if bufsize < 0:
|
||||
bufsize = 512
|
||||
self._rbufsize = max(1,bufsize)
|
||||
self._wbufsize = bufsize
|
||||
self._wbuf = self._rbuf = ""
|
||||
|
||||
def close (self):
|
||||
try:
|
||||
if self._sock:
|
||||
self.flush()
|
||||
finally:
|
||||
self._sock = None
|
||||
|
||||
def __del__ (self):
|
||||
self.close()
|
||||
|
||||
def flush (self):
|
||||
if self._wbuf:
|
||||
self._sock.write(self._wbuf,len(self._wbuf))
|
||||
self._wbuf = ""
|
||||
|
||||
def fileno (self):
|
||||
return self._sock.fileno()
|
||||
|
||||
def write (self, data):
|
||||
self._wbuf = self._wbuf + data
|
||||
if self._wbufsize == 1:
|
||||
if '\n' in data:
|
||||
self.flush()
|
||||
else:
|
||||
if len(self._wbuf) >= self._wbufsize:
|
||||
self.flush()
|
||||
|
||||
def writelines (self, lst):
|
||||
filter(self._sock.send,lst)
|
||||
self.flush()
|
||||
|
||||
def read (self, n=-1):
|
||||
if n >= 0:
|
||||
while len(self._rbuf) < n:
|
||||
new = self._ssl.read(self._rbufsize)
|
||||
if not new: break
|
||||
self._rbuf = self._rbuf + new
|
||||
data,self._rbuf = self._rbuf[:n],self._rbuf[n:]
|
||||
return data
|
||||
while 1:
|
||||
new = self._ssl.read(self._rbufsize)
|
||||
if not new: break
|
||||
self._rbuf = self._rbuf + new
|
||||
data,self._rbuf = self._rbuf,""
|
||||
return data
|
||||
|
||||
def readline (self):
|
||||
data = ""
|
||||
i = string.find(self._rbuf,'\n')
|
||||
while i < 0:
|
||||
new = self._ssl.read(self._rbufsize)
|
||||
if not new: break
|
||||
i = string.find(new,'\n')
|
||||
if i >= 0: i = i + len(self._rbuf)
|
||||
self._rbuf = self._rbuf + new
|
||||
if i < 0: i = len(self._rbuf)
|
||||
else: i = i+1
|
||||
data,self._rbuf = self._rbuf[:i],self._rbuf[i:]
|
||||
return data
|
||||
|
||||
def readlines (self):
|
||||
l = []
|
||||
while 1:
|
||||
line = self.readline()
|
||||
if not line: break
|
||||
l.append(line)
|
||||
return l
|
||||
|
||||
def _test():
|
||||
import sys
|
||||
import getopt
|
||||
opts, args = getopt.getopt(sys.argv[1:], 'd')
|
||||
dl = 0
|
||||
for o, a in opts:
|
||||
if o == '-d': dl = dl + 1
|
||||
if args[0:]: host = args[0]
|
||||
if args[1:]: selector = args[1]
|
||||
h = HTTPS()
|
||||
host = 'synergy.as.cmu.edu'
|
||||
selector = '/~geek/'
|
||||
# host = 'tls.cryptsoft.com'
|
||||
# selector = '/'
|
||||
h.set_debuglevel(dl)
|
||||
h.connect(host)
|
||||
h.putrequest('GET', selector)
|
||||
h.endheaders()
|
||||
errcode, errmsg, headers = h.getreply()
|
||||
print 'errcode =', errcode
|
||||
print 'errmsg =', errmsg
|
||||
print "\tHEADERS:"
|
||||
if headers:
|
||||
for header in headers.headers: print string.strip(header)
|
||||
print "\tTEXT:"
|
||||
print h.getfile().read()
|
||||
|
||||
if __name__ == '__main__':
|
||||
_test()
|
||||
189
po/msgfmt.py
Executable file
189
po/msgfmt.py
Executable file
|
|
@ -0,0 +1,189 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
# Written by Martin v. Löwis <loewis@informatik.hu-berlin.de>
|
||||
|
||||
"""Generate binary message catalog from textual translation description.
|
||||
|
||||
This program converts a textual Uniforum-style message catalog (.po file) into
|
||||
a binary GNU catalog (.mo file). This is essentially the same function as the
|
||||
GNU msgfmt program, however, it is a simpler implementation.
|
||||
|
||||
Usage: msgfmt.py [OPTIONS] filename.po
|
||||
|
||||
Options:
|
||||
-h
|
||||
--help
|
||||
Print this message and exit.
|
||||
|
||||
-V
|
||||
--version
|
||||
Display version information and exit.
|
||||
|
||||
"""
|
||||
|
||||
import sys, getopt, struct, array, string
|
||||
|
||||
__version__ = "1.0"
|
||||
MESSAGES = {}
|
||||
|
||||
|
||||
|
||||
def usage(code, msg=''):
|
||||
sys.stderr.write(__doc__)
|
||||
if msg:
|
||||
sys.stderr.write(msg)
|
||||
sys.exit(code)
|
||||
|
||||
|
||||
|
||||
def add(id, str, fuzzy):
|
||||
"Add a non-fuzzy translation to the dictionary."
|
||||
global MESSAGES
|
||||
if not fuzzy and str:
|
||||
MESSAGES[id] = str
|
||||
|
||||
|
||||
|
||||
def generate():
|
||||
"Return the generated output."
|
||||
global MESSAGES
|
||||
keys = MESSAGES.keys()
|
||||
# the keys are sorted in the .mo file
|
||||
keys.sort()
|
||||
offsets = []
|
||||
ids = strs = ''
|
||||
for id in keys:
|
||||
# For each string, we need size and file offset. Each string is NUL
|
||||
# terminated; the NUL does not count into the size.
|
||||
offsets.append((len(ids), len(id), len(strs), len(MESSAGES[id])))
|
||||
ids = ids + id + '\0'
|
||||
strs = strs + MESSAGES[id] + '\0'
|
||||
output = ''
|
||||
# The header is 7 32-bit unsigned integers. We don't use hash tables, so
|
||||
# the keys start right after the index tables.
|
||||
# translated string.
|
||||
keystart = 7*4+16*len(keys)
|
||||
# and the values start after the keys
|
||||
valuestart = keystart + len(ids)
|
||||
koffsets = []
|
||||
voffsets = []
|
||||
# The string table first has the list of keys, then the list of values.
|
||||
# Each entry has first the size of the string, then the file offset.
|
||||
for o1, l1, o2, l2 in offsets:
|
||||
koffsets = koffsets + [l1, o1+keystart]
|
||||
voffsets = voffsets + [l2, o2+valuestart]
|
||||
offsets = koffsets + voffsets
|
||||
output = struct.pack("iiiiiii",
|
||||
0x950412de, # Magic
|
||||
0, # Version
|
||||
len(keys), # # of entries
|
||||
7*4, # start of key index
|
||||
7*4+len(keys)*8, # start of value index
|
||||
0, 0) # size and offset of hash table
|
||||
output = output + array.array("i", offsets).tostring()
|
||||
output = output + ids
|
||||
output = output + strs
|
||||
return output
|
||||
|
||||
|
||||
|
||||
def make(filename):
|
||||
ID = 1
|
||||
STR = 2
|
||||
|
||||
# Compute .mo name from .po name
|
||||
if filename[-3:] == '.po':
|
||||
infile = filename
|
||||
outfile = filename[:-2] + 'mo'
|
||||
else:
|
||||
infile = filename + '.po'
|
||||
outfile = filename + '.mo'
|
||||
try:
|
||||
lines = open(infile).readlines()
|
||||
except IOError, msg:
|
||||
sys.stderr.write(msg)
|
||||
sys.exit(1)
|
||||
|
||||
section = None
|
||||
fuzzy = 0
|
||||
|
||||
# Parse the catalog
|
||||
lno = 0
|
||||
for l in lines:
|
||||
lno = lno + 1
|
||||
# If we get a comment line after a msgstr, this is a new entry
|
||||
if l[0] == '#' and section == STR:
|
||||
add(msgid, msgstr, fuzzy)
|
||||
section = None
|
||||
fuzzy = 0
|
||||
# Record a fuzzy mark
|
||||
if l[:2] == '#,' and string.find(l, 'fuzzy') != -1:
|
||||
fuzzy = 1
|
||||
# Skip comments
|
||||
if l[0] == '#':
|
||||
continue
|
||||
# Now we are in a msgid section, output previous section
|
||||
if l[:5] == 'msgid':
|
||||
if section == STR:
|
||||
add(msgid, msgstr, fuzzy)
|
||||
section = ID
|
||||
l = l[5:]
|
||||
msgid = msgstr = ''
|
||||
# Now we are in a msgstr section
|
||||
elif l[:6] == 'msgstr':
|
||||
section = STR
|
||||
l = l[6:]
|
||||
# Skip empty lines
|
||||
l = string.strip(l)
|
||||
if not l:
|
||||
continue
|
||||
# XXX: Does this always follow Python escape semantics?
|
||||
l = eval(l)
|
||||
if section == ID:
|
||||
msgid = msgid + l
|
||||
elif section == STR:
|
||||
msgstr = msgstr + l
|
||||
else:
|
||||
sys.stderr.write('Syntax error on %s:%d\n'
|
||||
'before: %s\n' % (infile, lno, l))
|
||||
sys.exit(1)
|
||||
# Add last entry
|
||||
if section == STR:
|
||||
add(msgid, msgstr, fuzzy)
|
||||
|
||||
# Compute output
|
||||
output = generate()
|
||||
|
||||
# Save output
|
||||
try:
|
||||
open(outfile,"wb").write(output)
|
||||
except IOError,msg:
|
||||
sys.stderr.write(msg)
|
||||
|
||||
|
||||
|
||||
def main():
|
||||
try:
|
||||
opts, args = getopt.getopt(sys.argv[1:], 'hV', ['help','version'])
|
||||
except getopt.error, msg:
|
||||
usage(1, msg)
|
||||
|
||||
# parse options
|
||||
for opt, arg in opts:
|
||||
if opt in ('-h', '--help'):
|
||||
usage(0)
|
||||
elif opt in ('-V', '--version'):
|
||||
sys.stderr.write("msgfmt.py %s" % __version__)
|
||||
sys.exit(0)
|
||||
# do it
|
||||
if not args:
|
||||
sys.stderr.write('No input file given\n')
|
||||
sys.stderr.write("Try `msgfmt --help' for more information.\n")
|
||||
return
|
||||
|
||||
for filename in args:
|
||||
make(filename)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
446
po/pygettext.py
Executable file
446
po/pygettext.py
Executable file
|
|
@ -0,0 +1,446 @@
|
|||
#!/usr/bin/env python
|
||||
# Originally written by Barry Warsaw <bwarsaw@python.org>
|
||||
#
|
||||
# minimally patched to make it even more xgettext compatible
|
||||
# by Peter Funk <pf@artcom-gmbh.de>
|
||||
|
||||
# for selftesting
|
||||
try:
|
||||
import fintl
|
||||
_ = fintl.gettext
|
||||
except ImportError:
|
||||
def _(s): return s
|
||||
|
||||
|
||||
__doc__ = _("""pygettext -- Python equivalent of xgettext(1)
|
||||
|
||||
Many systems (Solaris, Linux, Gnu) provide extensive tools that ease the
|
||||
internationalization of C programs. Most of these tools are independent of
|
||||
the programming language and can be used from within Python programs. Martin
|
||||
von Loewis' work[1] helps considerably in this regard.
|
||||
|
||||
There's one problem though; xgettext is the program that scans source code
|
||||
looking for message strings, but it groks only C (or C++). Python introduces
|
||||
a few wrinkles, such as dual quoting characters, triple quoted strings, and
|
||||
raw strings. xgettext understands none of this.
|
||||
|
||||
Enter pygettext, which uses Python's standard tokenize module to scan Python
|
||||
source code, generating .pot files identical to what GNU xgettext[2] generates
|
||||
for C and C++ code. From there, the standard GNU tools can be used.
|
||||
|
||||
A word about marking Python strings as candidates for translation. GNU
|
||||
xgettext recognizes the following keywords: gettext, dgettext, dcgettext, and
|
||||
gettext_noop. But those can be a lot of text to include all over your code.
|
||||
C and C++ have a trick: they use the C preprocessor. Most internationalized C
|
||||
source includes a #define for gettext() to _() so that what has to be written
|
||||
in the source is much less. Thus these are both translatable strings:
|
||||
|
||||
gettext("Translatable String")
|
||||
_("Translatable String")
|
||||
|
||||
Python of course has no preprocessor so this doesn't work so well. Thus,
|
||||
pygettext searches only for _() by default, but see the -k/--keyword flag
|
||||
below for how to augment this.
|
||||
|
||||
[1] http://www.python.org/workshops/1997-10/proceedings/loewis.html
|
||||
[2] http://www.gnu.org/software/gettext/gettext.html
|
||||
|
||||
NOTE: pygettext attempts to be option and feature compatible with GNU xgettext
|
||||
where ever possible. However some options are still missing or are not fully
|
||||
implemented. Also, xgettext's use of command line switches with option
|
||||
arguments is broken, and in these cases, pygettext just defines additional
|
||||
switches.
|
||||
|
||||
Usage: pygettext [options] inputfile ...
|
||||
|
||||
Options:
|
||||
|
||||
-a
|
||||
--extract-all
|
||||
Extract all strings
|
||||
|
||||
-d name
|
||||
--default-domain=name
|
||||
Rename the default output file from messages.pot to name.pot
|
||||
|
||||
-E
|
||||
--escape
|
||||
replace non-ASCII characters with octal escape sequences.
|
||||
|
||||
-h
|
||||
--help
|
||||
print this help message and exit
|
||||
|
||||
-k word
|
||||
--keyword=word
|
||||
Keywords to look for in addition to the default set, which are:
|
||||
%(DEFAULTKEYWORDS)s
|
||||
|
||||
You can have multiple -k flags on the command line.
|
||||
|
||||
-K
|
||||
--no-default-keywords
|
||||
Disable the default set of keywords (see above). Any keywords
|
||||
explicitly added with the -k/--keyword option are still recognized.
|
||||
|
||||
--no-location
|
||||
Do not write filename/lineno location comments.
|
||||
|
||||
-n
|
||||
--add-location
|
||||
Write filename/lineno location comments indicating where each
|
||||
extracted string is found in the source. These lines appear before
|
||||
each msgid. The style of comments is controlled by the -S/--style
|
||||
option. This is the default.
|
||||
|
||||
-S stylename
|
||||
--style stylename
|
||||
Specify which style to use for location comments. Two styles are
|
||||
supported:
|
||||
|
||||
Solaris # File: filename, line: line-number
|
||||
GNU #: filename:line
|
||||
|
||||
The style name is case insensitive. GNU style is the default.
|
||||
|
||||
-o filename
|
||||
--output=filename
|
||||
Rename the default output file from messages.pot to filename. If
|
||||
filename is `-' then the output is sent to standard out.
|
||||
|
||||
-p dir
|
||||
--output-dir=dir
|
||||
Output files will be placed in directory dir.
|
||||
|
||||
-v
|
||||
--verbose
|
||||
Print the names of the files being processed.
|
||||
|
||||
-V
|
||||
--version
|
||||
Print the version of pygettext and exit.
|
||||
|
||||
-w columns
|
||||
--width=columns
|
||||
Set width of output to columns.
|
||||
|
||||
-x filename
|
||||
--exclude-file=filename
|
||||
Specify a file that contains a list of strings that are not be
|
||||
extracted from the input files. Each string to be excluded must
|
||||
appear on a line by itself in the file.
|
||||
|
||||
If `inputfile' is -, standard input is read.
|
||||
|
||||
""")
|
||||
|
||||
import os, sys, time, getopt, tokenize, string
|
||||
|
||||
__version__ = '1.1'
|
||||
default_keywords = ['_']
|
||||
DEFAULTKEYWORDS = string.join(default_keywords, ', ')
|
||||
EMPTYSTRING = ''
|
||||
|
||||
|
||||
# The normal pot-file header. msgmerge and EMACS' po-mode work better if
|
||||
# it's there.
|
||||
pot_header = _('''\
|
||||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR ORGANIZATION
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\\n"
|
||||
"PO-Revision-Date: %(time)s\\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\\n"
|
||||
"MIME-Version: 1.0\\n"
|
||||
"Content-Type: text/plain; charset=CHARSET\\n"
|
||||
"Content-Transfer-Encoding: ENCODING\\n"
|
||||
"Generated-By: pygettext.py %(version)s\\n"
|
||||
|
||||
''')
|
||||
|
||||
|
||||
def usage(code, msg=''):
|
||||
print __doc__ % globals()
|
||||
if msg:
|
||||
print msg
|
||||
sys.exit(code)
|
||||
|
||||
|
||||
|
||||
escapes = []
|
||||
|
||||
def make_escapes(pass_iso8859):
|
||||
global escapes
|
||||
if pass_iso8859:
|
||||
# Allow iso-8859 characters to pass through so that e.g. 'msgid
|
||||
# "Höhe"' would result not result in 'msgid "H\366he"'. Otherwise we
|
||||
# escape any character outside the 32..126 range.
|
||||
mod = 128
|
||||
else:
|
||||
mod = 256
|
||||
for i in range(256):
|
||||
if 32 <= (i % mod) <= 126:
|
||||
escapes.append(chr(i))
|
||||
else:
|
||||
escapes.append("\\%03o" % i)
|
||||
escapes[ord('\\')] = '\\\\'
|
||||
escapes[ord('\t')] = '\\t'
|
||||
escapes[ord('\r')] = '\\r'
|
||||
escapes[ord('\n')] = '\\n'
|
||||
escapes[ord('\"')] = '\\"'
|
||||
|
||||
|
||||
def escape(s):
|
||||
global escapes
|
||||
s = list(s)
|
||||
for i in range(len(s)):
|
||||
s[i] = escapes[ord(s[i])]
|
||||
return string.join(s, EMPTYSTRING)
|
||||
|
||||
|
||||
def safe_eval(s):
|
||||
# unwrap quotes, safely
|
||||
return eval(s, {'__builtins__':{}}, {})
|
||||
|
||||
|
||||
def normalize(s):
|
||||
# This converts the various Python string types into a format that is
|
||||
# appropriate for .po files, namely much closer to C style.
|
||||
lines = string.split(s, '\n')
|
||||
if len(lines) == 1:
|
||||
s = '"' + escape(s) + '"'
|
||||
else:
|
||||
if not lines[-1]:
|
||||
del lines[-1]
|
||||
lines[-1] = lines[-1] + '\n'
|
||||
for i in range(len(lines)):
|
||||
lines[i] = escape(lines[i])
|
||||
lineterm = '\\n"\n"'
|
||||
s = '""\n"' + string.join(lines, lineterm) + '"'
|
||||
return s
|
||||
|
||||
|
||||
|
||||
class TokenEater:
|
||||
def __init__(self, options):
|
||||
self.__options = options
|
||||
self.__messages = {}
|
||||
self.__state = self.__waiting
|
||||
self.__data = []
|
||||
self.__lineno = -1
|
||||
|
||||
def __call__(self, ttype, tstring, stup, etup, line):
|
||||
# dispatch
|
||||
self.__state(ttype, tstring, stup[0])
|
||||
|
||||
def __waiting(self, ttype, tstring, lineno):
|
||||
if ttype == tokenize.NAME and tstring in self.__options.keywords:
|
||||
self.__state = self.__keywordseen
|
||||
|
||||
def __keywordseen(self, ttype, tstring, lineno):
|
||||
if ttype == tokenize.OP and tstring == '(':
|
||||
self.__data = []
|
||||
self.__lineno = lineno
|
||||
self.__state = self.__openseen
|
||||
else:
|
||||
self.__state = self.__waiting
|
||||
|
||||
def __openseen(self, ttype, tstring, lineno):
|
||||
if ttype == tokenize.OP and tstring == ')':
|
||||
# We've seen the last of the translatable strings. Record the
|
||||
# line number of the first line of the strings and update the list
|
||||
# of messages seen. Reset state for the next batch. If there
|
||||
# were no strings inside _(), then just ignore this entry.
|
||||
if self.__data:
|
||||
msg = string.join(self.__data, EMPTYSTRING)
|
||||
if not msg in self.__options.toexclude:
|
||||
entry = (self.__curfile, self.__lineno)
|
||||
linenos = self.__messages.get(msg)
|
||||
if linenos is None:
|
||||
self.__messages[msg] = [entry]
|
||||
else:
|
||||
linenos.append(entry)
|
||||
self.__state = self.__waiting
|
||||
elif ttype == tokenize.STRING:
|
||||
self.__data.append(safe_eval(tstring))
|
||||
# TBD: should we warn if we seen anything else?
|
||||
|
||||
def set_filename(self, filename):
|
||||
self.__curfile = filename
|
||||
|
||||
def write(self, fp):
|
||||
options = self.__options
|
||||
timestamp = time.ctime(time.time())
|
||||
# common header
|
||||
try:
|
||||
sys.stdout = fp
|
||||
# The time stamp in the header doesn't have the same format
|
||||
# as that generated by xgettext...
|
||||
print pot_header % {'time': timestamp, 'version': __version__}
|
||||
for k, v in self.__messages.items():
|
||||
if not options.writelocations:
|
||||
pass
|
||||
# location comments are different b/w Solaris and GNU:
|
||||
elif options.locationstyle == options.SOLARIS:
|
||||
for filename, lineno in v:
|
||||
d = {'filename': filename, 'lineno': lineno}
|
||||
print _('# File: %(filename)s, line: %(lineno)d') % d
|
||||
elif options.locationstyle == options.GNU:
|
||||
# fit as many locations on one line, as long as the
|
||||
# resulting line length doesn't exceeds 'options.width'
|
||||
locline = '#:'
|
||||
for filename, lineno in v:
|
||||
d = {'filename': filename, 'lineno': lineno}
|
||||
s = _(' %(filename)s:%(lineno)d') % d
|
||||
if len(locline) + len(s) <= options.width:
|
||||
locline = locline + s
|
||||
else:
|
||||
print locline
|
||||
locline = "#:" + s
|
||||
if len(locline) > 2:
|
||||
print locline
|
||||
# TBD: sorting, normalizing
|
||||
print 'msgid', normalize(k)
|
||||
print 'msgstr ""\n'
|
||||
finally:
|
||||
sys.stdout = sys.__stdout__
|
||||
|
||||
|
||||
def main():
|
||||
global default_keywords
|
||||
try:
|
||||
opts, args = getopt.getopt(
|
||||
sys.argv[1:],
|
||||
'ad:Ehk:Kno:p:S:Vvw:x:',
|
||||
['extract-all', 'default-domain=', 'escape', 'help',
|
||||
'keyword=', 'no-default-keywords',
|
||||
'add-location', 'no-location', 'output=', 'output-dir=',
|
||||
'style=', 'verbose', 'version', 'width=', 'exclude-file=',
|
||||
])
|
||||
except getopt.error, msg:
|
||||
usage(1, msg)
|
||||
|
||||
# for holding option values
|
||||
class Options:
|
||||
# constants
|
||||
GNU = 1
|
||||
SOLARIS = 2
|
||||
# defaults
|
||||
extractall = 0 # FIXME: currently this option has no effect at all.
|
||||
escape = 0
|
||||
keywords = []
|
||||
outpath = ''
|
||||
outfile = 'messages.pot'
|
||||
writelocations = 1
|
||||
locationstyle = GNU
|
||||
verbose = 0
|
||||
width = 78
|
||||
excludefilename = ''
|
||||
|
||||
options = Options()
|
||||
locations = {'gnu' : options.GNU,
|
||||
'solaris' : options.SOLARIS,
|
||||
}
|
||||
|
||||
# parse options
|
||||
for opt, arg in opts:
|
||||
if opt in ('-h', '--help'):
|
||||
usage(0)
|
||||
elif opt in ('-a', '--extract-all'):
|
||||
options.extractall = 1
|
||||
elif opt in ('-d', '--default-domain'):
|
||||
options.outfile = arg + '.pot'
|
||||
elif opt in ('-E', '--escape'):
|
||||
options.escape = 1
|
||||
elif opt in ('-k', '--keyword'):
|
||||
options.keywords.append(arg)
|
||||
elif opt in ('-K', '--no-default-keywords'):
|
||||
default_keywords = []
|
||||
elif opt in ('-n', '--add-location'):
|
||||
options.writelocations = 1
|
||||
elif opt in ('--no-location',):
|
||||
options.writelocations = 0
|
||||
elif opt in ('-S', '--style'):
|
||||
options.locationstyle = locations.get(arg.lower())
|
||||
if options.locationstyle is None:
|
||||
usage(1, _('Invalid value for --style: %s') % arg)
|
||||
elif opt in ('-o', '--output'):
|
||||
options.outfile = arg
|
||||
elif opt in ('-p', '--output-dir'):
|
||||
options.outpath = arg
|
||||
elif opt in ('-v', '--verbose'):
|
||||
options.verbose = 1
|
||||
elif opt in ('-V', '--version'):
|
||||
print _('pygettext.py (xgettext for Python) %s') % __version__
|
||||
sys.exit(0)
|
||||
elif opt in ('-w', '--width'):
|
||||
try:
|
||||
options.width = int(arg)
|
||||
except ValueError:
|
||||
usage(1, _('--width argument must be an integer: %s') % arg)
|
||||
elif opt in ('-x', '--exclude-file'):
|
||||
options.excludefilename = arg
|
||||
|
||||
# calculate escapes
|
||||
make_escapes(options.escape)
|
||||
|
||||
# calculate all keywords
|
||||
options.keywords.extend(default_keywords)
|
||||
|
||||
# initialize list of strings to exclude
|
||||
if options.excludefilename:
|
||||
try:
|
||||
fp = open(options.excludefilename)
|
||||
options.toexclude = fp.readlines()
|
||||
fp.close()
|
||||
except IOError:
|
||||
sys.stderr.write(_("Can't read --exclude-file: %s") %
|
||||
options.excludefilename)
|
||||
sys.exit(1)
|
||||
else:
|
||||
options.toexclude = []
|
||||
|
||||
# slurp through all the files
|
||||
eater = TokenEater(options)
|
||||
for filename in args:
|
||||
if filename == '-':
|
||||
if options.verbose:
|
||||
print _('Reading standard input')
|
||||
fp = sys.stdin
|
||||
closep = 0
|
||||
else:
|
||||
if options.verbose:
|
||||
print _('Working on %s') % filename
|
||||
fp = open(filename)
|
||||
closep = 1
|
||||
try:
|
||||
eater.set_filename(filename)
|
||||
tokenize.tokenize(fp.readline, eater)
|
||||
finally:
|
||||
if closep:
|
||||
fp.close()
|
||||
|
||||
# write the output
|
||||
if options.outfile == '-':
|
||||
fp = sys.stdout
|
||||
closep = 0
|
||||
else:
|
||||
if options.outpath:
|
||||
options.outfile = os.path.join(options.outpath, options.outfile)
|
||||
fp = open(options.outfile, 'w')
|
||||
closep = 1
|
||||
try:
|
||||
eater.write(fp)
|
||||
finally:
|
||||
if closep:
|
||||
fp.close()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
# some more test strings
|
||||
#_(u'a unicode string')
|
||||
415
ssl.c
Normal file
415
ssl.c
Normal file
|
|
@ -0,0 +1,415 @@
|
|||
/* @(#)ssl.c 1.1 VMS-99/01/30 python wrapper for SSLeay https
|
||||
*/
|
||||
|
||||
#include "Python.h"
|
||||
#if defined(WITH_THREAD) && !defined(HAVE_GETHOSTBYNAME_R) &&\
|
||||
!defined(MS_WINDOWS)
|
||||
#include "thread.h"
|
||||
#endif
|
||||
|
||||
#include <sys/types.h>
|
||||
#ifndef MS_WINDOWS
|
||||
#include <sys/socket.h>
|
||||
#else
|
||||
#include <winsock.h>
|
||||
#endif
|
||||
|
||||
#if defined(PYOS_OS2)
|
||||
#define INCL_DOS
|
||||
#define INCL_DOSERRORS
|
||||
#define INCL_NOPMAPI
|
||||
#include <os2.h>
|
||||
#endif
|
||||
|
||||
#include "ssl.h"
|
||||
#include "err.h"
|
||||
|
||||
/*
|
||||
some hacks to choose between K&R or ANSI style function
|
||||
definitions. For NT to build this as an extension module (ie, DLL)
|
||||
it must be compiled by the C++ compiler, as it takes the address of
|
||||
a static data item exported from the main Python DLL.
|
||||
*/
|
||||
#ifdef MS_WINDOWS
|
||||
#define FORCE_ANSI_FUNC_DEFS
|
||||
#endif
|
||||
|
||||
#if defined(PYOS_OS2)
|
||||
#define FORCE_ANSI_FUNC_DEFS
|
||||
#endif
|
||||
|
||||
#ifdef FORCE_ANSI_FUNC_DEFS
|
||||
#define BUILD_FUNC_DEF_1( fnname, arg1type, arg1name ) \
|
||||
fnname( arg1type arg1name )
|
||||
|
||||
#define BUILD_FUNC_DEF_2( fnname, arg1type, arg1name, arg2type, arg2name ) \
|
||||
fnname( arg1type arg1name, arg2type arg2name )
|
||||
|
||||
#else /* !FORCE_ANSI_FN_DEFS */
|
||||
#define BUILD_FUNC_DEF_1( fnname, arg1type, arg1name ) \
|
||||
fnname( arg1name ) \
|
||||
arg1type arg1name;
|
||||
|
||||
#define BUILD_FUNC_DEF_2( fnname, arg1type, arg1name, arg2type, arg2name ) \
|
||||
fnname( arg1name, arg2name ) \
|
||||
arg1type arg1name; \
|
||||
arg2type arg2name;
|
||||
#endif /* !FORCE_ANSI_FN_DEFS */
|
||||
|
||||
/* Global variable holding the exception type for errors detected
|
||||
by this module (but not argument type or memory errors, etc.). */
|
||||
|
||||
static PyObject *PySslError;
|
||||
|
||||
typedef struct {
|
||||
PyObject_HEAD
|
||||
int sock_fd;
|
||||
PyObject *x_attr; /* attributes dictionary */
|
||||
SSL_CTX *ctx;
|
||||
SSL *ssl;
|
||||
X509 *server_cert;
|
||||
BIO *sbio;
|
||||
char server[256];
|
||||
char issuer[256];
|
||||
} PySslObject;
|
||||
|
||||
staticforward PyTypeObject SSL_Type;
|
||||
#define PySslObject_Check(v) ((v)->ob_type == &SSL_Type)
|
||||
|
||||
/*
|
||||
* raise an error according to errno, return NULL
|
||||
*/
|
||||
static PyObject *
|
||||
PySsl_errno ()
|
||||
{
|
||||
#ifdef MS_WINDOWS
|
||||
if (WSAGetLastError()) {
|
||||
PyObject *v = Py_BuildValue("(is)",WSAGetLastError(),"winsock error");
|
||||
|
||||
if (v) {
|
||||
PyErr_SetObject(PySslError,v);
|
||||
Py_DECREF(v);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
return PyErr_SetFromErrno(PySslError);
|
||||
}
|
||||
|
||||
/*
|
||||
* format SSl error string
|
||||
*/
|
||||
static int
|
||||
BUILD_FUNC_DEF_2 (PySsl_err_str, unsigned long, e, char *, buf)
|
||||
{
|
||||
unsigned long l = ERR_GET_LIB(e);
|
||||
unsigned long f = ERR_GET_FUNC(e);
|
||||
unsigned long r = ERR_GET_REASON(e);
|
||||
char* ls = (char*)ERR_lib_error_string(e);
|
||||
char* fs = (char*)ERR_func_error_string(e);
|
||||
char* rs = (char*)ERR_reason_error_string(e);
|
||||
char* bp = buf + 2; /* skip two initial blanks */
|
||||
|
||||
(void)strcpy(buf," none:"); /* initialize buffer */
|
||||
bp += (ls) ? sprintf(bp,"%s:",ls) :
|
||||
((l) ? sprintf(bp,"lib %lu:",l) : 0);
|
||||
bp += (fs) ? sprintf(bp,"%s ",fs) :
|
||||
((f) ? sprintf(bp,"func %lu:",f) : 0);
|
||||
bp += (rs) ? sprintf(bp,"%s:",rs) :
|
||||
((r) ? sprintf(bp,"reason(%lu):",r) : 0);
|
||||
*bp-- = 0; /* suppress last divider (:) */
|
||||
return (bp - buf);
|
||||
}
|
||||
|
||||
/*
|
||||
* report SSL core errors
|
||||
*/
|
||||
static PySslObject *
|
||||
PySsl_errors ()
|
||||
{
|
||||
#define PY_SSL_ERR_MAX 256
|
||||
|
||||
unsigned long e;
|
||||
char buf[2 * PY_SSL_ERR_MAX];
|
||||
char *bf = buf;
|
||||
|
||||
while (((bf - buf) < PY_SSL_ERR_MAX) && (e = ERR_get_error()))
|
||||
bf += PySsl_err_str(e,bf);
|
||||
{
|
||||
PyObject *v = Py_BuildValue("(sss)", "ssl","core",buf+2);
|
||||
if (v != NULL) {
|
||||
PyErr_SetObject(PySslError,v);
|
||||
Py_DECREF(v);
|
||||
}
|
||||
}
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* report SSL application layer errors
|
||||
*/
|
||||
static PySslObject *
|
||||
BUILD_FUNC_DEF_2 (PySsl_app_errors, SSL *, s, int, ret)
|
||||
{
|
||||
int err = SSL_get_error(s,ret);
|
||||
char *str;
|
||||
|
||||
switch (err) {
|
||||
case SSL_ERROR_SSL:
|
||||
return (PySsl_errors());
|
||||
case SSL_ERROR_SYSCALL:
|
||||
return ((PySslObject *)PySsl_errno());
|
||||
case SSL_ERROR_ZERO_RETURN:
|
||||
str = "End of data";
|
||||
break;
|
||||
case SSL_ERROR_WANT_READ:
|
||||
str = "Want read";
|
||||
break;
|
||||
case SSL_ERROR_WANT_WRITE:
|
||||
str = "Want write";
|
||||
break;
|
||||
case SSL_ERROR_WANT_X509_LOOKUP:
|
||||
str = "Want x509 lookup";
|
||||
break;
|
||||
case SSL_ERROR_WANT_CONNECT:
|
||||
str = "Want connect";
|
||||
break;
|
||||
default:
|
||||
str = "Unknown";
|
||||
break;
|
||||
}
|
||||
{
|
||||
PyObject *v = Py_BuildValue("(sis)", "ssl",err, str);
|
||||
if (v != NULL) {
|
||||
PyErr_SetObject(PySslError,v);
|
||||
Py_DECREF(v);
|
||||
}
|
||||
}
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/* ssl.read(len) method */
|
||||
|
||||
static PyObject *
|
||||
BUILD_FUNC_DEF_2 (PySslObj_read, PySslObject *, self, PyObject *, args)
|
||||
{
|
||||
int len, n;
|
||||
PyObject *buf;
|
||||
|
||||
if (!PyArg_ParseTuple(args,"i",&len))
|
||||
return (NULL);
|
||||
if (!(buf = PyString_FromStringAndSize((char *)0,len)))
|
||||
return (NULL);
|
||||
Py_BEGIN_ALLOW_THREADS
|
||||
|
||||
n = SSL_read(self->ssl,PyString_AsString(buf),len);
|
||||
|
||||
Py_END_ALLOW_THREADS
|
||||
|
||||
switch (SSL_get_error(self->ssl,n)) {
|
||||
case SSL_ERROR_NONE: /* good return value */
|
||||
break;
|
||||
case SSL_ERROR_ZERO_RETURN:
|
||||
case SSL_ERROR_SYSCALL:
|
||||
if (!n) /* fix SSL_ERROR_SYCSALL errno=0 case */
|
||||
break;
|
||||
/* fall thru here */
|
||||
default:
|
||||
Py_DECREF(buf);
|
||||
(void)PySsl_app_errors(self->ssl,n);
|
||||
return (NULL);
|
||||
}
|
||||
if ((n != len) && (_PyString_Resize(&buf,n) < 0))
|
||||
return (NULL);
|
||||
return (buf);
|
||||
}
|
||||
|
||||
/* ssl.write(data,len) method */
|
||||
|
||||
static PyObject *
|
||||
BUILD_FUNC_DEF_2 (PySslObj_write, PySslObject *, self, PyObject *, args)
|
||||
{
|
||||
char *buf;
|
||||
int len, n;
|
||||
if (!PyArg_ParseTuple(args, "si", &buf, &len))
|
||||
return NULL;
|
||||
|
||||
/* Note: flags are ignored */
|
||||
|
||||
Py_BEGIN_ALLOW_THREADS
|
||||
|
||||
n = SSL_write(self->ssl,buf,len);
|
||||
|
||||
Py_END_ALLOW_THREADS
|
||||
if (n < 0)
|
||||
return (PySsl_errno());
|
||||
return (PyInt_FromLong((long)n));
|
||||
}
|
||||
|
||||
/* ssl.server() method */
|
||||
|
||||
static PyObject *
|
||||
BUILD_FUNC_DEF_2 (PySslObj_server, PySslObject *, self, PyObject *, args)
|
||||
{
|
||||
if (!PyArg_NoArgs(args))
|
||||
return (NULL);
|
||||
return (PyString_FromString(self->server));
|
||||
}
|
||||
|
||||
/* ssl.issuer() method */
|
||||
|
||||
static PyObject *
|
||||
BUILD_FUNC_DEF_2 (PySslObj_issuer, PySslObject *, self, PyObject *, args)
|
||||
{
|
||||
if (!PyArg_NoArgs(args))
|
||||
return (NULL);
|
||||
return (PyString_FromString(self->issuer));
|
||||
}
|
||||
|
||||
/* SSL object methods */
|
||||
|
||||
static PyMethodDef PySslObj_methods[] = {
|
||||
{"read", (PyCFunction)PySslObj_read,1},
|
||||
{"write", (PyCFunction)PySslObj_write,1},
|
||||
{"server", (PyCFunction)PySslObj_server},
|
||||
{"issuer", (PyCFunction)PySslObj_issuer},
|
||||
{ NULL, NULL}
|
||||
};
|
||||
|
||||
static void
|
||||
BUILD_FUNC_DEF_1 (PySsl_dealloc, PySslObject *, self)
|
||||
{
|
||||
if (self->server_cert) /* possible not to have one? */
|
||||
X509_free(self->server_cert);
|
||||
SSL_CTX_free(self->ctx);
|
||||
SSL_free(self->ssl);
|
||||
Py_XDECREF(self->x_attr);
|
||||
PyMem_DEL(self);
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
BUILD_FUNC_DEF_2 (PySsl_getattr, PySslObject *, self, char *, name)
|
||||
{
|
||||
return (Py_FindMethod(PySslObj_methods,(PyObject *)self,name));
|
||||
}
|
||||
|
||||
staticforward PyTypeObject SSL_Type = {
|
||||
PyObject_HEAD_INIT(&PyType_Type)
|
||||
0, /*ob_size*/
|
||||
"SSL", /*tp_name*/
|
||||
sizeof(PySslObject), /*tp_basicsize*/
|
||||
0, /*tp_itemsize*/
|
||||
/* methods */
|
||||
(destructor)PySsl_dealloc, /*tp_dealloc*/
|
||||
0, /*tp_print*/
|
||||
(getattrfunc)PySsl_getattr, /*tp_getattr*/
|
||||
0, /*tp_setattr*/
|
||||
0, /*tp_compare*/
|
||||
0, /*tp_repr*/
|
||||
0, /*tp_as_number*/
|
||||
0, /*tp_as_sequence*/
|
||||
0, /*tp_as_mapping*/
|
||||
0, /*tp_hash*/
|
||||
};
|
||||
|
||||
/*
|
||||
* C function called for new object initialization
|
||||
* Note: SSL protocol version 2, 3, or 2+3 set at compile time
|
||||
*/
|
||||
static PySslObject *
|
||||
BUILD_FUNC_DEF_1 (newPySslObject, int, sock_fd)
|
||||
{
|
||||
PySslObject *self;
|
||||
SSL_METHOD *meth;
|
||||
int ret;
|
||||
|
||||
#if 0
|
||||
meth=SSLv3_client_method();
|
||||
meth=SSLv23_client_method();
|
||||
#endif
|
||||
|
||||
meth=SSLv2_client_method();
|
||||
|
||||
if (!(self = PyObject_NEW(PySslObject,&SSL_Type))) /* create new object */
|
||||
return (NULL);
|
||||
(void)memset(self->server,0,sizeof(self->server));
|
||||
(void)memset(self->issuer,0,sizeof(self->issuer));
|
||||
|
||||
self->x_attr = PyDict_New();
|
||||
if (!(self->ctx = SSL_CTX_new(meth))) { /* set up context */
|
||||
PyMem_DEL(self);
|
||||
return (PySsl_errors());
|
||||
}
|
||||
#if 0 /* Note: set this for v23, Netscape server */
|
||||
SSL_CTX_set_options(self->ctx,SSL_OP_ALL);
|
||||
#endif
|
||||
self->ssl = SSL_new(self->ctx); /* new ssl struct */
|
||||
if (!(ret = SSL_set_fd(self->ssl,sock_fd))) { /* set the socket for SSL */
|
||||
PyMem_DEL(self);
|
||||
return (PySsl_app_errors(self->ssl,ret));
|
||||
}
|
||||
SSL_CTX_set_verify(self->ctx,SSL_VERIFY_NONE,NULL); /* set verify lvl */
|
||||
SSL_set_connect_state(self->ssl);
|
||||
|
||||
if ((ret = SSL_connect(self->ssl)) < 0) { /* negotiate SSL connection */
|
||||
PyMem_DEL(self);
|
||||
return (PySsl_app_errors(self->ssl,ret));
|
||||
}
|
||||
self->ssl->debug = 1;
|
||||
|
||||
if ((self->server_cert = SSL_get_peer_certificate(self->ssl))) {
|
||||
X509_NAME_oneline(X509_get_subject_name(self->server_cert),
|
||||
self->server,sizeof(self->server));
|
||||
X509_NAME_oneline(X509_get_issuer_name(self->server_cert),
|
||||
self->issuer, sizeof(self->issuer));
|
||||
}
|
||||
self->x_attr = NULL;
|
||||
self->sock_fd = sock_fd;
|
||||
return (self);
|
||||
}
|
||||
|
||||
/*
|
||||
* Python function called for new object initialization
|
||||
*/
|
||||
static PyObject *
|
||||
BUILD_FUNC_DEF_2 (PySsl_ssl_new, PyObject *, self, PyObject *, args)
|
||||
{
|
||||
int sock_fd;
|
||||
if (!PyArg_ParseTuple(args, "i", &sock_fd))
|
||||
return (NULL);
|
||||
return ((PyObject *)newPySslObject(sock_fd));
|
||||
}
|
||||
|
||||
/* List of functions exported by this module. */
|
||||
|
||||
static PyMethodDef PySsl_methods[] = {
|
||||
{"ssl", (PyCFunction)PySsl_ssl_new, 1},
|
||||
{NULL, NULL} /* sentinel */
|
||||
|
||||
};
|
||||
|
||||
/*
|
||||
* Initialize this module, called when the first 'import ssl' is done
|
||||
*/
|
||||
void
|
||||
initssl ()
|
||||
{
|
||||
PyObject *m, *d;
|
||||
m = Py_InitModule("ssl", PySsl_methods);
|
||||
d = PyModule_GetDict(m);
|
||||
|
||||
SSL_load_error_strings();
|
||||
SSLeay_add_ssl_algorithms();
|
||||
|
||||
/* *** Python 1.5 ***
|
||||
if (!(PySssl_Error = PyErr_NewException("ssl.error",NULL,NULL)))
|
||||
return;
|
||||
*/
|
||||
|
||||
if (!(PySslError = PyString_FromString("ssl.error")) ||
|
||||
PyDict_SetItemString(d,"error",PySslError))
|
||||
Py_FatalError("can't define ssl.error");
|
||||
if (PyDict_SetItemString(d,"SSLType",(PyObject *)&SSL_Type))
|
||||
return;
|
||||
}
|
||||
|
||||
Loading…
Reference in a new issue