mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-06-23 15:30:45 -04:00
sync with main
This commit is contained in:
commit
8f08dc92b8
@ -20,3 +20,6 @@ src/calibre/gui2/pictureflow/pictureflow_resource.rc
|
||||
src/calibre/gui2/pictureflow/release/
|
||||
src/calibre/translations/compiled.py
|
||||
installer/windows/calibre/build.log
|
||||
src/calibre/translations/.errors
|
||||
src/calibre/plugins/*
|
||||
src/calibre/gui2/pictureflow/.build
|
||||
|
27
Makefile
27
Makefile
@ -1,11 +1,6 @@
|
||||
PYTHON = python
|
||||
|
||||
all : plugins gui2 translations resources
|
||||
|
||||
plugins : src/calibre/plugins pictureflow lzx
|
||||
|
||||
src/calibre/plugins:
|
||||
mkdir -p src/calibre/plugins
|
||||
all : gui2 translations resources
|
||||
|
||||
clean :
|
||||
cd src/calibre/gui2 && ${PYTHON} make.py clean
|
||||
@ -25,26 +20,6 @@ resources:
|
||||
manual:
|
||||
make -C src/calibre/manual clean html
|
||||
|
||||
pictureflow :
|
||||
mkdir -p src/calibre/plugins && rm -f src/calibre/plugins/*pictureflow* && \
|
||||
cd src/calibre/gui2/pictureflow && rm -f *.o && \
|
||||
mkdir -p .build && cd .build && rm -f * && \
|
||||
qmake ../pictureflow.pro && make staticlib && \
|
||||
cd ../PyQt && \
|
||||
mkdir -p .build && \
|
||||
cd .build && rm -f * && \
|
||||
${PYTHON} ../configure.py && make && \
|
||||
cd ../../../../../.. && \
|
||||
cp src/calibre/gui2/pictureflow/PyQt/.build/pictureflow.so src/calibre/plugins/ && \
|
||||
rm -rf src/calibre/gui2/pictureflow/.build rm -rf src/calibre/gui2/pictureflow/PyQt/.build
|
||||
|
||||
lzx :
|
||||
mkdir -p src/calibre/plugins && rm -f src/calibre/plugins/lzx.so && \
|
||||
cd src/calibre/utils/lzx && \
|
||||
${PYTHON} setup.py build --build-base=.build && cd - && \
|
||||
cp src/calibre/utils/lzx/.build/lib*/lzx.so src/calibre/plugins/ && \
|
||||
rm -rf src/calibre/utils/lzx/.build/
|
||||
|
||||
pot :
|
||||
cd src/calibre/translations && ${PYTHON} __init__.py pot
|
||||
|
||||
|
@ -6,7 +6,7 @@ __docformat__ = 'restructuredtext en'
|
||||
'''
|
||||
Create linux binary.
|
||||
'''
|
||||
import glob, sys, subprocess, tarfile, os, re, py_compile
|
||||
import glob, sys, subprocess, tarfile, os, re, py_compile, shutil
|
||||
HOME = '/home/kovid'
|
||||
PYINSTALLER = os.path.expanduser('~/build/pyinstaller')
|
||||
CALIBREPREFIX = '___'
|
||||
@ -16,6 +16,9 @@ LIBUNRAR = '/usr/lib/libunrar.so'
|
||||
QTDIR = '/usr/lib/qt4'
|
||||
QTDLLS = ('QtCore', 'QtGui', 'QtNetwork', 'QtSvg', 'QtXml')
|
||||
EXTRAS = ('/usr/lib/python2.5/site-packages/PIL', os.path.expanduser('~/ipython/IPython'))
|
||||
SQLITE = '/usr/lib/libsqlite3.so.0'
|
||||
DBUS = '/usr/lib/libdbus-1.so.3'
|
||||
LIBMNG = '/usr/lib/libmng.so.1'
|
||||
|
||||
|
||||
CALIBRESRC = os.path.join(CALIBREPREFIX, 'src')
|
||||
@ -33,7 +36,6 @@ open(os.path.join(PYINSTALLER, 'hooks', 'hook-calibre.parallel.py'), 'wb').write
|
||||
def run_pyinstaller(args=sys.argv):
|
||||
subprocess.check_call(('/usr/bin/sudo', 'chown', '-R', 'kovid:users', glob.glob('/usr/lib/python*/site-packages/')[-1]))
|
||||
subprocess.check_call('rm -rf %(py)s/dist/* %(py)s/build/*'%dict(py=PYINSTALLER), shell=True)
|
||||
subprocess.check_call('make plugins', shell=True)
|
||||
cp = HOME+'/build/'+os.path.basename(os.getcwd())
|
||||
spec = open(os.path.join(PYINSTALLER, 'calibre', 'calibre.spec'), 'wb')
|
||||
raw = re.sub(r'CALIBREPREFIX\s+=\s+\'___\'', 'CALIBREPREFIX = '+repr(cp),
|
||||
@ -41,12 +43,14 @@ def run_pyinstaller(args=sys.argv):
|
||||
spec.write(raw)
|
||||
spec.close()
|
||||
os.chdir(PYINSTALLER)
|
||||
shutil.rmtree('calibre/dist')
|
||||
os.mkdir('calibre/dist')
|
||||
subprocess.check_call('python -OO Build.py calibre/calibre.spec', shell=True)
|
||||
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == '__main__' and 'linux_installer.py' in __file__:
|
||||
if __name__ == '__main__' and 'freeze.py' in __file__:
|
||||
sys.exit(run_pyinstaller())
|
||||
|
||||
|
||||
@ -59,7 +63,7 @@ os.chdir(os.environ.get("ORIGWD", "."))
|
||||
sys.path.insert(0, os.path.join(sys.frozen_path, "library.pyz"))
|
||||
sys.path.insert(0, sys.frozen_path)
|
||||
from PyQt4.QtCore import QCoreApplication
|
||||
QCoreApplication.setLibraryPaths([sys.frozen_path, os.path.join(sys.frozen_path, "plugins")])
|
||||
QCoreApplication.setLibraryPaths([sys.frozen_path, os.path.join(sys.frozen_path, "qtplugins")])
|
||||
''')
|
||||
excludes = ['gtk._gtk', 'gtk.glade', 'qt', 'matplotlib.nxutils', 'matplotlib._cntr',
|
||||
'matplotlib.ttconv', 'matplotlib._image', 'matplotlib.ft2font',
|
||||
@ -80,7 +84,7 @@ for entry in entry_points['console_scripts'] + entry_points['gui_scripts']:
|
||||
scripts.append(os.path.join(CALIBRESRC, *map(lambda x: x.strip(), fields[1].split(':')[0].split('.')))+'.py')
|
||||
|
||||
analyses = [Analysis([os.path.join(HOMEPATH,'support/_mountzlib.py'), os.path.join(HOMEPATH,'support/useUnicode.py'), loader, script],
|
||||
pathex=[PYINSTALLER, CALIBRESRC, CALIBREPLUGINS], excludes=excludes) for script in scripts]
|
||||
pathex=[PYINSTALLER, CALIBRESRC], excludes=excludes) for script in scripts]
|
||||
|
||||
pyz = TOC()
|
||||
binaries = TOC()
|
||||
@ -104,11 +108,18 @@ for script, exe, a in zip(scripts, executables, analyses):
|
||||
|
||||
print 'Adding plugins...'
|
||||
for f in glob.glob(os.path.join(CALIBREPLUGINS, '*.so')):
|
||||
binaries += [('plugins/'+os.path.basename(f), f, 'BINARY')]
|
||||
for f in glob.glob(os.path.join(CALIBREPLUGINS, '*.so.*')):
|
||||
binaries += [(os.path.basename(f), f, 'BINARY')]
|
||||
|
||||
print 'Adding external programs...'
|
||||
binaries += [('clit', CLIT, 'BINARY'), ('pdftohtml', PDFTOHTML, 'BINARY'),
|
||||
('libunrar.so', LIBUNRAR, 'BINARY')]
|
||||
|
||||
print 'Adding external libraries...'
|
||||
binaries += [ (os.path.basename(x), x, 'BINARY') for x in (SQLITE, DBUS, LIBMNG)]
|
||||
|
||||
|
||||
qt = []
|
||||
for dll in QTDLLS:
|
||||
path = os.path.join(QTDIR, 'lib'+dll+'.so.4')
|
||||
@ -121,7 +132,7 @@ for dirpath, dirnames, filenames in os.walk(plugdir):
|
||||
for f in filenames:
|
||||
if not f.endswith('.so') or 'designer' in dirpath or 'codcs' in dirpath or 'sqldrivers' in dirpath : continue
|
||||
f = os.path.join(dirpath, f)
|
||||
plugins.append(('plugins/'+f.replace(plugdir, ''), f, 'BINARY'))
|
||||
plugins.append(('qtplugins/'+f.replace(plugdir, ''), f, 'BINARY'))
|
||||
binaries += plugins
|
||||
|
||||
manifest = '/tmp/manifest'
|
@ -4,7 +4,14 @@ __copyright__ = '2008, Kovid Goyal <kovid at kovidgoyal.net>'
|
||||
''' Create an OSX installer '''
|
||||
|
||||
import sys, re, os, shutil, subprocess, stat, glob, zipfile
|
||||
from setup import VERSION, APPNAME, scripts, main_modules, basenames, main_functions
|
||||
l = {}
|
||||
exec open('setup.py').read() in l
|
||||
VERSION = l['VERSION']
|
||||
APPNAME = l['APPNAME']
|
||||
scripts = l['scripts']
|
||||
basenames = l['basenames']
|
||||
main_functions = l['main_functions']
|
||||
main_modules = l['main_modules']
|
||||
from setuptools import setup
|
||||
from py2app.build_app import py2app
|
||||
from modulegraph.find_modules import find_modules
|
||||
@ -40,6 +47,8 @@ loader.close()
|
||||
os.chmod(loader_path, 0700)
|
||||
os.environ['PYTHONHOME'] = resources_dir
|
||||
os.environ['FC_CONFIG_DIR'] = os.path.join(resources_dir, 'fonts')
|
||||
os.environ['MAGICK_HOME'] = os.path.join(frameworks_dir, 'ImageMagick')
|
||||
os.environ['DYLD_LIBRARY_PATH'] = os.path.join(frameworks_dir, 'ImageMagick', 'lib')
|
||||
os.execv(loader_path, sys.argv)
|
||||
'''
|
||||
CHECK_SYMLINKS_PRESCRIPT = \
|
||||
@ -170,64 +179,46 @@ _check_symlinks_prescript()
|
||||
for f in files:
|
||||
subprocess.check_call(['/usr/bin/install_name_tool', '-change', '/Library/Frameworks/Python.framework/Versions/2.5/Python', '@executable_path/../Frameworks/Python.framework/Versions/2.5/Python', f])
|
||||
|
||||
def fix_misc_dependencies(self, files):
|
||||
for path in files:
|
||||
frameworks_dir = os.path.join(self.dist_dir, APPNAME + '.app', 'Contents', 'Frameworks')
|
||||
pipe = subprocess.Popen('/usr/bin/otool -L '+path, shell=True, stdout=subprocess.PIPE).stdout
|
||||
for l in pipe.readlines():
|
||||
match = re.search(r'\s+(.*?)\s+\(', l)
|
||||
if match:
|
||||
dep = match.group(1)
|
||||
name = os.path.basename(dep)
|
||||
if not name:
|
||||
name = dep
|
||||
bundle = os.path.join(frameworks_dir, name)
|
||||
if os.path.exists(bundle):
|
||||
subprocess.check_call(['/usr/bin/install_name_tool', '-change', dep,
|
||||
'@executable_path/../Frameworks/'+name, path])
|
||||
|
||||
def build_distutils_plugins(self):
|
||||
plugins = [
|
||||
('lzx', os.path.join('utils', 'lzx')),
|
||||
]
|
||||
files = []
|
||||
env = {'PATH':os.environ['PATH']}
|
||||
for name, path in plugins:
|
||||
print 'Building plugin', name
|
||||
path = os.path.abspath(os.path.join('src', 'calibre', path))
|
||||
cwd = os.getcwd()
|
||||
os.chdir(path)
|
||||
try:
|
||||
if os.path.exists('.build'):
|
||||
shutil.rmtree('.build')
|
||||
subprocess.check_call((sys.executable, 'setup.py', 'build', '--build-base', '.build'),
|
||||
env=env)
|
||||
plugin = os.path.abspath(glob.glob('.build/lib*/%s.so'%name)[0])
|
||||
files.append([plugin, os.path.basename(plugin)])
|
||||
finally:
|
||||
os.chdir(cwd)
|
||||
return files
|
||||
|
||||
def build_plugins(self):
|
||||
cwd = os.getcwd()
|
||||
qmake = '/Users/kovid/qt/bin/qmake'
|
||||
files = []
|
||||
try:
|
||||
print 'Building pictureflow'
|
||||
os.chdir('src/calibre/gui2/pictureflow')
|
||||
if not os.path.exists('.build'):
|
||||
os.mkdir('.build')
|
||||
os.chdir('.build')
|
||||
for f in glob.glob('*'): os.unlink(f)
|
||||
subprocess.check_call([qmake, '../pictureflow.pro'])
|
||||
subprocess.check_call(['make'])
|
||||
files.append((os.path.abspath(os.path.realpath('libpictureflow.dylib')), 'libpictureflow.dylib'))
|
||||
os.chdir('../PyQt')
|
||||
if not os.path.exists('.build'):
|
||||
os.mkdir('.build')
|
||||
os.chdir('.build')
|
||||
for f in glob.glob('*'): os.unlink(f)
|
||||
subprocess.check_call([PYTHON, '../configure.py'])
|
||||
subprocess.check_call(['/usr/bin/make'])
|
||||
files.append((os.path.abspath('pictureflow.so'), 'pictureflow.so'))
|
||||
subprocess.check_call(['/usr/bin/install_name_tool', '-change', 'libpictureflow.0.dylib', '@executable_path/../Frameworks/libpictureflow.dylib', 'pictureflow.so'])
|
||||
self.fix_python_dependencies((files[0][0], files[1][0]))
|
||||
for i in range(2):
|
||||
deps = BuildAPP.qt_dependencies(files[i][0])
|
||||
BuildAPP.fix_qt_dependencies(files[i][0], deps)
|
||||
def add_plugins(self):
|
||||
self.add_qt_plugins()
|
||||
frameworks_dir = os.path.join(self.dist_dir, APPNAME + '.app', 'Contents', 'Frameworks')
|
||||
plugins_dir = os.path.join(frameworks_dir, 'plugins')
|
||||
if not os.path.exists(plugins_dir):
|
||||
os.mkdir(plugins_dir)
|
||||
|
||||
return files
|
||||
finally:
|
||||
os.chdir(cwd)
|
||||
maps = {}
|
||||
for f in glob.glob('src/calibre/plugins/*'):
|
||||
tgt = plugins_dir
|
||||
if f.endswith('.dylib'):
|
||||
tgt = frameworks_dir
|
||||
maps[f] = os.path.join(tgt, os.path.basename(f))
|
||||
deps = []
|
||||
for src, dst in maps.items():
|
||||
shutil.copyfile(src, dst)
|
||||
self.fix_qt_dependencies(dst, self.qt_dependencies(dst))
|
||||
deps.append(dst)
|
||||
self.fix_python_dependencies(deps)
|
||||
self.fix_misc_dependencies(deps)
|
||||
|
||||
|
||||
def run(self):
|
||||
plugin_files = self.build_distutils_plugins()
|
||||
py2app.run(self)
|
||||
resource_dir = os.path.join(self.dist_dir,
|
||||
APPNAME + '.app', 'Contents', 'Resources')
|
||||
@ -249,8 +240,8 @@ _check_symlinks_prescript()
|
||||
f.close()
|
||||
os.chmod(path, stat.S_IXUSR|stat.S_IXGRP|stat.S_IXOTH|stat.S_IREAD\
|
||||
|stat.S_IWUSR|stat.S_IROTH|stat.S_IRGRP)
|
||||
self.add_qt_plugins()
|
||||
plugin_files += self.build_plugins()
|
||||
self.add_plugins()
|
||||
|
||||
|
||||
print
|
||||
print 'Adding clit'
|
||||
@ -264,13 +255,8 @@ _check_symlinks_prescript()
|
||||
print 'Adding plugins'
|
||||
module_dir = os.path.join(resource_dir, 'lib', 'python2.5', 'lib-dynload')
|
||||
print 'Adding fontconfig'
|
||||
for f in glob.glob(os.path.expanduser('~/fontconfig2/*')):
|
||||
for f in glob.glob(os.path.expanduser('~/fontconfig-bundled/*')):
|
||||
os.link(f, os.path.join(frameworks_dir, os.path.basename(f)))
|
||||
for src, dest in plugin_files:
|
||||
if 'dylib' in dest:
|
||||
os.link(src, os.path.join(frameworks_dir, dest))
|
||||
else:
|
||||
os.link(src, os.path.join(module_dir, dest))
|
||||
dst = os.path.join(resource_dir, 'fonts')
|
||||
if os.path.exists(dst):
|
||||
shutil.rmtree(dst)
|
||||
@ -281,6 +267,15 @@ _check_symlinks_prescript()
|
||||
dst = os.path.join(resource_dir, 'lib', 'python2.5', 'IPython')
|
||||
if os.path.exists(dst): shutil.rmtree(dst)
|
||||
shutil.copytree(os.path.expanduser('~/build/ipython/IPython'), dst)
|
||||
|
||||
print
|
||||
print 'Adding ImageMagick'
|
||||
dest = os.path.join(frameworks_dir, 'ImageMagick')
|
||||
if os.path.exists(dest):
|
||||
sutil.rmtree(dest)
|
||||
shutil.copytree(os.path.expanduser('~/ImageMagick'), dest, True)
|
||||
shutil.copyfile('/usr/local/lib/libpng12.0.dylib', os.path.join(dest, 'lib', 'libpng12.0.dylib'))
|
||||
|
||||
print
|
||||
print 'Installing prescipt'
|
||||
sf = [os.path.basename(s) for s in all_names]
|
||||
@ -341,6 +336,8 @@ def main():
|
||||
'NSHumanReadableCopyright':'Copyright 2008, Kovid Goyal',
|
||||
'LSEnvironment':{
|
||||
'FC_CONFIG_DIR':'@executable_path/../Resources/fonts',
|
||||
'MAGICK_HOME':'@executable_path/../Frameworks/ImageMagick',
|
||||
'DYLD_LIBRARY_PATH':'@executable_path/../Frameworks/ImageMagick/lib',
|
||||
}
|
||||
},
|
||||
},
|
@ -240,7 +240,6 @@ File ::B145A772-C20C-A6F2-E872-ACC229FFE1C7 -name fb2-meta.exe -parent 6CCF3F71-
|
||||
File ::168973D9-DEE6-7307-9A2E-746EB9456311 -name txt2lrf.exe.local -parent 6CCF3F71-74BB-ED69-D0E6-9F12348ABDD3
|
||||
File ::BD39D6F0-5125-F3A3-043F-E8FD1C87A823 -name isbndb.exe -parent 6CCF3F71-74BB-ED69-D0E6-9F12348ABDD3
|
||||
File ::6C294A11-52D4-C567-64F7-1DCF21AB06D7 -name epub2lrf.exe -parent 6CCF3F71-74BB-ED69-D0E6-9F12348ABDD3
|
||||
File ::BBE8D78B-6646-5327-563C-7F8EE5842D7B -name pictureflow.pyd -parent 6CCF3F71-74BB-ED69-D0E6-9F12348ABDD3
|
||||
File ::A9BB9531-5BC4-92C1-F614-B84B93F8698F -name pywintypes25.dll -parent 6CCF3F71-74BB-ED69-D0E6-9F12348ABDD3
|
||||
File ::AA725BD8-5FFA-B426-733F-5A1264A30DA2 -name Qt.pyd -parent 6CCF3F71-74BB-ED69-D0E6-9F12348ABDD3
|
||||
File ::B48D9BFD-326D-1C92-4D94-C17F9ACD9207 -name epub2lrf.exe.local -parent 6CCF3F71-74BB-ED69-D0E6-9F12348ABDD3
|
||||
@ -264,7 +263,6 @@ File ::2AABAB06-38EF-6F8C-3675-575D8B044E0C -name calibredb.exe -parent 6CCF3F71
|
||||
File ::A7EA318A-0542-FBB8-5C93-A39B364A51D9 -name epub-meta.exe.local -parent 6CCF3F71-74BB-ED69-D0E6-9F12348ABDD3
|
||||
File ::4CD878C5-1487-1FFD-99A1-EDFC90892F0A -name win32security.pyd -parent 6CCF3F71-74BB-ED69-D0E6-9F12348ABDD3
|
||||
File ::ADFDF202-EED8-0319-0D69-DF1C44AE465B -name librarything.exe.local -parent 6CCF3F71-74BB-ED69-D0E6-9F12348ABDD3
|
||||
File ::B522E7CC-3C9B-325B-B0BA-3CAFD0228B6D -name pictureflow0.dll -parent 6CCF3F71-74BB-ED69-D0E6-9F12348ABDD3
|
||||
File ::0E83E956-FF8D-27AB-9BE9-A24C57F8886A -name pythoncom25.dll -parent 6CCF3F71-74BB-ED69-D0E6-9F12348ABDD3
|
||||
File ::F8DAAE4E-9BF0-F75A-78BD-81E0F4BD1F99 -name epub-meta.exe -parent 6CCF3F71-74BB-ED69-D0E6-9F12348ABDD3
|
||||
File ::E2982BD3-D0BB-70B4-0BF8-18B2B68C9918 -name QtWebKit4.dll -parent 6CCF3F71-74BB-ED69-D0E6-9F12348ABDD3
|
||||
@ -351,6 +349,12 @@ File ::92701E8F-1D91-A796-C899-2A266029F61D -name _socket.pyd -parent 6CCF3F71-7
|
||||
File ::45BD27B5-B910-7633-C827-37E82E89C27C -name w9xpopen.exe.local -parent 6CCF3F71-74BB-ED69-D0E6-9F12348ABDD3
|
||||
File ::45C27909-D761-787F-84B2-66596E5C4E99 -name bz2.pyd -parent 6CCF3F71-74BB-ED69-D0E6-9F12348ABDD3
|
||||
File ::7B2DE5D8-17A6-B167-ABC7-799AEBCC1C02 -name clit.exe -parent 6CCF3F71-74BB-ED69-D0E6-9F12348ABDD3
|
||||
File ::36E8EEAC-F54D-5DE9-02D8-ECDFEBB4B5E2 -type dir -name plugins -parent 6CCF3F71-74BB-ED69-D0E6-9F12348ABDD3
|
||||
File ::71930E14-A27B-C23C-8D94-C7E97ADB8723 -name pictureflow.pyd -parent 36E8EEAC-F54D-5DE9-02D8-ECDFEBB4B5E2
|
||||
File ::293E6ABE-17C9-5E53-1B44-C27029C8C061 -name winutil.pyd -parent 36E8EEAC-F54D-5DE9-02D8-ECDFEBB4B5E2
|
||||
File ::A5737158-18DF-7F20-2BDF-2DF615663891 -name lzx.pyd -parent 36E8EEAC-F54D-5DE9-02D8-ECDFEBB4B5E2
|
||||
File ::CA9E098C-2931-9781-1303-213C242F9A5E -name lit2oeb.exe -parent 6CCF3F71-74BB-ED69-D0E6-9F12348ABDD3
|
||||
File ::16B5A447-066C-C93E-F63D-8BC0D57CA544 -name lit2oeb.exe.local -parent 6CCF3F71-74BB-ED69-D0E6-9F12348ABDD3
|
||||
Component ::F6829AB7-9F66-4CEE-CA0E-21F54C6D3609 -setup Install -active Yes -platforms {AIX-ppc FreeBSD-4-x86 FreeBSD-x86 HPUX-hppa Linux-x86 Solaris-sparc Windows} -name Main -parent Components
|
||||
SetupType ::D9ADE41C-B744-690C-2CED-CF826BF03D2E -setup Install -active Yes -platforms {AIX-ppc FreeBSD-4-x86 FreeBSD-x86 HPUX-hppa Linux-x86 Solaris-sparc Windows} -name Typical -parent SetupTypes
|
||||
|
||||
|
@ -50,58 +50,16 @@ class BuildEXE(py2exe.build_exe.py2exe):
|
||||
</trustInfo>
|
||||
</assembly>
|
||||
'''
|
||||
def build_distutil_plugins(self):
|
||||
plugins = [
|
||||
('lzx', os.path.join('utils', 'lzx')),
|
||||
]
|
||||
for name, path in plugins:
|
||||
print 'Building plugin', name
|
||||
path = os.path.abspath(os.path.join('src', 'calibre', path))
|
||||
cwd = os.getcwd()
|
||||
dd = os.path.join(cwd, self.dist_dir)
|
||||
os.chdir(path)
|
||||
try:
|
||||
if os.path.exists('.build'):
|
||||
shutil.rmtree('.build')
|
||||
subprocess.check_call(('python', 'setup.py', 'build', '--build-base', '.build'))
|
||||
plugin = os.path.abspath(glob.glob('.build\\lib*\\%s.pyd'%name)[0])
|
||||
shutil.copyfile(plugin, os.path.join(dd, os.path.basename(plugin)))
|
||||
finally:
|
||||
os.chdir(cwd)
|
||||
|
||||
def build_plugins(self):
|
||||
cwd = os.getcwd()
|
||||
dd = os.path.join(cwd, self.dist_dir)
|
||||
try:
|
||||
os.chdir(os.path.join('src', 'calibre', 'gui2', 'pictureflow'))
|
||||
if os.path.exists('.build'):
|
||||
shutil.rmtree('.build')
|
||||
os.mkdir('.build')
|
||||
os.chdir('.build')
|
||||
subprocess.check_call(['qmake', '../pictureflow.pro'])
|
||||
subprocess.check_call(['mingw32-make', '-f', 'Makefile.Release'])
|
||||
shutil.copyfile('release\\pictureflow0.dll', os.path.join(dd, 'pictureflow0.dll'))
|
||||
os.chdir('..\\PyQt')
|
||||
if not os.path.exists('.build'):
|
||||
os.mkdir('.build')
|
||||
os.chdir('.build')
|
||||
subprocess.check_call(['python', '..\\configure.py'])
|
||||
subprocess.check_call(['mingw32-make', '-f', 'Makefile'])
|
||||
shutil.copyfile('pictureflow.pyd', os.path.join(dd, 'pictureflow.pyd'))
|
||||
os.chdir('..')
|
||||
shutil.rmtree('.build', True)
|
||||
os.chdir('..')
|
||||
shutil.rmtree('.build', True)
|
||||
finally:
|
||||
os.chdir(cwd)
|
||||
|
||||
def run(self):
|
||||
if not os.path.exists(self.dist_dir):
|
||||
os.makedirs(self.dist_dir)
|
||||
print 'Building custom plugins...'
|
||||
self.build_distutil_plugins()
|
||||
self.build_plugins()
|
||||
py2exe.build_exe.py2exe.run(self)
|
||||
print 'Adding plugins...'
|
||||
tgt = os.path.join(self.dist_dir, 'plugins')
|
||||
if not os.path.exists(tgt):
|
||||
os.mkdir(tgt)
|
||||
for f in glob.glob(os.path.join(BASE_DIR, 'src', 'calibre', 'plugins', '*.dll')):
|
||||
shutil.copyfile(f, os.path.join(self.dist_dir, os.path.basename(f)))
|
||||
for f in glob.glob(os.path.join(BASE_DIR, 'src', 'calibre', 'plugins', '*.pyd')):
|
||||
shutil.copyfile(f, os.path.join(tgt, os.path.basename(f)))
|
||||
qtsvgdll = None
|
||||
for other in self.other_depends:
|
||||
if 'qtsvg4.dll' in other.lower():
|
||||
@ -116,7 +74,7 @@ class BuildEXE(py2exe.build_exe.py2exe):
|
||||
print 'Adding', qtxmldll
|
||||
shutil.copyfile(qtxmldll,
|
||||
os.path.join(self.dist_dir, os.path.basename(qtxmldll)))
|
||||
print 'Adding plugins...',
|
||||
print 'Adding Qt plugins...',
|
||||
qt_prefix = QT_DIR
|
||||
if qtsvgdll:
|
||||
qt_prefix = os.path.dirname(os.path.dirname(qtsvgdll))
|
||||
@ -152,7 +110,8 @@ class BuildEXE(py2exe.build_exe.py2exe):
|
||||
print '\tAdding pdftohtml'
|
||||
shutil.copyfile(PDFTOHTML, os.path.join(PY2EXE_DIR, os.path.basename(PDFTOHTML)))
|
||||
print '\tAdding ImageMagick'
|
||||
shutil.copytree(IMAGEMAGICK_DIR, os.path.join(PY2EXE_DIR, 'ImageMagick'))
|
||||
for f in os.listdir(IMAGEMAGICK_DIR):
|
||||
shutil.copyfile(os.path.join(IMAGEMAGICK_DIR, f), os.path.join(PY2EXE_DIR, f))
|
||||
print '\tCopying fontconfig'
|
||||
for f in glob.glob(os.path.join(FONTCONFIG_DIR, '*')):
|
||||
tgt = os.path.join(PY2EXE_DIR, os.path.basename(f))
|
||||
|
61
setup.py
61
setup.py
@ -4,7 +4,9 @@ __copyright__ = '2008, Kovid Goyal <kovid at kovidgoyal.net>'
|
||||
|
||||
import sys, re, os, shutil
|
||||
sys.path.append('src')
|
||||
islinux = not ('win32' in sys.platform or 'win64' in sys.platform or 'darwin' in sys.platform)
|
||||
iswindows = re.search('win(32|64)', sys.platform)
|
||||
isosx = 'darwin' in sys.platform
|
||||
islinux = not isosx and not iswindows
|
||||
src = open('src/calibre/__init__.py', 'rb').read()
|
||||
VERSION = re.search(r'__version__\s+=\s+[\'"]([^\'"]+)[\'"]', src).group(1)
|
||||
APPNAME = re.search(r'__appname__\s+=\s+[\'"]([^\'"]+)[\'"]', src).group(1)
|
||||
@ -44,10 +46,64 @@ main_functions = {
|
||||
}
|
||||
|
||||
if __name__ == '__main__':
|
||||
from setuptools import setup, find_packages
|
||||
from setuptools import setup, find_packages, Extension
|
||||
import subprocess, glob
|
||||
|
||||
entry_points['console_scripts'].append('calibre_postinstall = calibre.linux:post_install')
|
||||
ext_modules = [Extension('calibre.plugins.lzx',
|
||||
sources=['src/calibre/utils/lzx/lzxmodule.c',
|
||||
'src/calibre/utils/lzx/lzxd.c'],
|
||||
include_dirs=['src/calibre/utils/lzx']),
|
||||
Extension('calibre.plugins.msdes',
|
||||
sources=['src/calibre/utils/msdes/msdesmodule.c',
|
||||
'src/calibre/utils/msdes/des.c'],
|
||||
include_dirs=['src/calibre/utils/msdes'])]
|
||||
if iswindows:
|
||||
ext_modules.append(Extension('calibre.plugins.winutil',
|
||||
sources=['src/calibre/utils/windows/winutil.c'],
|
||||
libraries=['shell32', 'setupapi'],
|
||||
include_dirs=['C:/WinDDK/6001.18001/inc/api/'])
|
||||
)
|
||||
if isosx:
|
||||
ext_modules.append(Extension('calibre.plugins.usbobserver',
|
||||
sources=['src/calibre/devices/usbobserver/usbobserver.c'])
|
||||
)
|
||||
|
||||
def build_PyQt_extension(path):
|
||||
pro = glob.glob(os.path.join(path, '*.pro'))[0]
|
||||
raw = open(pro).read()
|
||||
base = qtplugin = re.search(r'TARGET\s*=\s*(.*)', raw).group(1)
|
||||
ver = re.search(r'VERSION\s*=\s*(\d+)', raw).group(1)
|
||||
cwd = os.getcwd()
|
||||
os.chdir(os.path.dirname(pro))
|
||||
try:
|
||||
if not os.path.exists('.build'):
|
||||
os.mkdir('.build')
|
||||
os.chdir('.build')
|
||||
subprocess.check_call(( (os.path.expanduser('~/qt/bin/qmake') if isosx else 'qmake'), '..'+os.sep+os.path.basename(pro)))
|
||||
subprocess.check_call(['mingw32-make' if iswindows else 'make'])
|
||||
os.chdir(os.path.join('..', 'PyQt'))
|
||||
if not os.path.exists('.build'):
|
||||
os.mkdir('.build')
|
||||
os.chdir('.build')
|
||||
python = '/Library/Frameworks/Python.framework/Versions/Current/bin/python' if isosx else 'python'
|
||||
subprocess.check_call([python, '..'+os.sep+'configure.py'])
|
||||
subprocess.check_call(['mingw32-make' if iswindows else 'make'])
|
||||
ext = '.pyd' if iswindows else '.so'
|
||||
plugin = glob.glob(base+ext)[0]
|
||||
shutil.copyfile(plugin, os.path.join(cwd, 'src', 'calibre', 'plugins', plugin))
|
||||
finally:
|
||||
os.chdir(cwd)
|
||||
if islinux or isosx:
|
||||
for f in glob.glob(os.path.join('src', 'calibre', 'plugins', '*')):
|
||||
try:
|
||||
os.readlink(f)
|
||||
os.unlink(f)
|
||||
except:
|
||||
continue
|
||||
|
||||
for path in [(os.path.join('src', 'calibre', 'gui2', 'pictureflow'))]:
|
||||
build_PyQt_extension(path)
|
||||
|
||||
setup(
|
||||
name=APPNAME,
|
||||
@ -62,6 +118,7 @@ if __name__ == '__main__':
|
||||
entry_points = entry_points,
|
||||
zip_safe = False,
|
||||
options = { 'bdist_egg' : {'exclude_source_files': True,}, },
|
||||
ext_modules=ext_modules,
|
||||
description =
|
||||
'''
|
||||
E-book management application.
|
||||
|
@ -1,7 +1,7 @@
|
||||
''' E-book management software'''
|
||||
__license__ = 'GPL v3'
|
||||
__copyright__ = '2008, Kovid Goyal <kovid at kovidgoyal.net>'
|
||||
__version__ = '0.4.79'
|
||||
__version__ = '0.4.80'
|
||||
__docformat__ = "epytext"
|
||||
__author__ = "Kovid Goyal <kovid at kovidgoyal.net>"
|
||||
__appname__ = 'calibre'
|
||||
@ -20,7 +20,7 @@ from PyQt4.QtGui import QDesktopServices
|
||||
|
||||
from calibre.translations.msgfmt import make
|
||||
from calibre.ebooks.chardet import detect
|
||||
from calibre.terminfo import TerminalController
|
||||
from calibre.utils.terminfo import TerminalController
|
||||
|
||||
terminal_controller = TerminalController(sys.stdout)
|
||||
iswindows = 'win32' in sys.platform.lower() or 'win64' in sys.platform.lower()
|
||||
@ -43,6 +43,41 @@ try:
|
||||
except:
|
||||
preferred_encoding = 'utf-8'
|
||||
|
||||
if getattr(sys, 'frozen', False):
|
||||
if iswindows:
|
||||
plugin_path = os.path.join(os.path.dirname(sys.executable), 'plugins')
|
||||
elif isosx:
|
||||
plugin_path = os.path.join(getattr(sys, 'frameworks_dir'), 'plugins')
|
||||
elif islinux:
|
||||
plugin_path = os.path.join(getattr(sys, 'frozen_path'), 'plugins')
|
||||
sys.path.insert(0, plugin_path)
|
||||
else:
|
||||
import pkg_resources
|
||||
plugins = getattr(pkg_resources, 'resource_filename')(__appname__, 'plugins')
|
||||
sys.path.insert(0, plugins)
|
||||
|
||||
if iswindows and getattr(sys, 'frozen', False):
|
||||
sys.path.insert(1, os.path.dirname(sys.executable))
|
||||
|
||||
|
||||
plugins = {}
|
||||
for plugin in ['pictureflow', 'lzx', 'msdes'] + \
|
||||
(['winutil'] if iswindows else []) + \
|
||||
(['usbobserver'] if isosx else []):
|
||||
try:
|
||||
p, err = __import__(plugin), ''
|
||||
except Exception, err:
|
||||
p = None
|
||||
err = str(err)
|
||||
plugins[plugin] = (p, err)
|
||||
|
||||
if iswindows:
|
||||
winutil, winutilerror = plugins['winutil']
|
||||
if not winutil:
|
||||
raise RuntimeError('Failed to load the winutil plugin: %s'%winutilerror)
|
||||
sys.argv[1:] = winutil.argv()[1:]
|
||||
|
||||
|
||||
_abspath = os.path.abspath
|
||||
def my_abspath(path, encoding=sys.getfilesystemencoding()):
|
||||
'''
|
||||
@ -268,10 +303,10 @@ def filename_to_utf8(name):
|
||||
def extract(path, dir):
|
||||
ext = os.path.splitext(path)[1][1:].lower()
|
||||
extractor = None
|
||||
if ext == 'zip':
|
||||
if ext in ['zip', 'cbz', 'epub']:
|
||||
from calibre.libunzip import extract as zipextract
|
||||
extractor = zipextract
|
||||
elif ext == 'rar':
|
||||
elif ext in ['cbr', 'rar']:
|
||||
from calibre.libunrar import extract as rarextract
|
||||
extractor = rarextract
|
||||
if extractor is None:
|
||||
@ -605,23 +640,3 @@ if isosx:
|
||||
for font in fonts:
|
||||
exec 'from calibre.ebooks.lrf.fonts.liberation.'+font+' import font_data'
|
||||
open(os.path.join(fdir, font+'.ttf'), 'wb').write(font_data)
|
||||
|
||||
if islinux and not getattr(sys, 'frozen', False):
|
||||
import pkg_resources
|
||||
plugins = pkg_resources.resource_filename(__appname__, 'plugins')
|
||||
sys.path.insert(1, plugins)
|
||||
|
||||
if iswindows and getattr(sys, 'frozen', False):
|
||||
sys.path.insert(1, os.path.dirname(sys.executable))
|
||||
|
||||
|
||||
plugins = {}
|
||||
for plugin in ['pictureflow', 'lzx']:
|
||||
try:
|
||||
p, err = __import__(plugin), ''
|
||||
except Exception, err:
|
||||
p = None
|
||||
err = str(err)
|
||||
plugins[plugin] = (p, err)
|
||||
|
||||
|
||||
|
@ -23,6 +23,10 @@ Run an embedded python interpreter.
|
||||
return parser
|
||||
|
||||
def update_zipfile(zipfile, mod, path):
|
||||
if 'win32' in sys.platform:
|
||||
print 'WARNING: On Windows Vista you must run this from a console that has been started in Administrator mode.'
|
||||
print 'Press Enter to continue or Ctrl-C to Cancel'
|
||||
raw_input()
|
||||
pat = re.compile(mod.replace('.', '/')+r'\.py[co]*')
|
||||
name = mod.replace('.', '/') + os.path.splitext(path)[-1]
|
||||
update(zipfile, [pat], [path], [name])
|
||||
|
@ -133,31 +133,7 @@ class KINDLE(Device):
|
||||
|
||||
|
||||
def open_windows(self):
|
||||
drives = []
|
||||
import wmi
|
||||
c = wmi.WMI()
|
||||
for drive in c.Win32_DiskDrive():
|
||||
'''print drive.PNPDeviceID'''
|
||||
if self.__class__.is_device(drive.PNPDeviceID):
|
||||
if drive.Partitions == 0:
|
||||
continue
|
||||
try:
|
||||
partition = drive.associators("Win32_DiskDriveToDiskPartition")[0]
|
||||
logical_disk = partition.associators('Win32_LogicalDiskToPartition')[0]
|
||||
prefix = logical_disk.DeviceID+os.sep
|
||||
drives.append((drive.Index, prefix))
|
||||
except IndexError:
|
||||
continue
|
||||
|
||||
|
||||
if not drives:
|
||||
print self.__class__.__name__
|
||||
raise DeviceError('Unable to find %s. Is it connected?'%(self.__class__.__name__,))
|
||||
|
||||
drives.sort(cmp=lambda a, b: cmp(a[0], b[0]))
|
||||
self._main_prefix = drives[0][1]
|
||||
if len(drives) > 1:
|
||||
self._card_prefix = drives[1][1]
|
||||
raise NotImplementedError
|
||||
|
||||
|
||||
def open_linux(self):
|
||||
|
@ -20,7 +20,8 @@ MIME_MAP = {
|
||||
'lrx' : 'application/x-sony-bbeb',
|
||||
"rtf" : "application/rtf",
|
||||
"pdf" : "application/pdf",
|
||||
"txt" : "text/plain"
|
||||
"txt" : "text/plain" ,
|
||||
'epub': 'application/epub+zip',
|
||||
}
|
||||
|
||||
def uuid():
|
||||
|
@ -31,6 +31,7 @@ class PRS505(Device):
|
||||
PRODUCT_ID = 0x031e #: Product Id for the PRS-505
|
||||
PRODUCT_NAME = 'PRS-505'
|
||||
VENDOR_NAME = 'SONY'
|
||||
FORMATS = ["lrf", 'epub', "rtf", "pdf", "txt"]
|
||||
|
||||
MEDIA_XML = 'database/cache/media.xml'
|
||||
CACHE_XML = 'Sony Reader/database/cache.xml'
|
||||
|
@ -7,59 +7,42 @@ manner.
|
||||
|
||||
import sys
|
||||
|
||||
from calibre import iswindows, isosx
|
||||
from calibre import iswindows, isosx, plugins
|
||||
from calibre.devices import libusb
|
||||
|
||||
osx_scanner = None
|
||||
try:
|
||||
import usbobserver
|
||||
osx_scanner = usbobserver.get_devices
|
||||
except ImportError:
|
||||
pass
|
||||
osx_scanner = win_scanner = linux_scanner = None
|
||||
|
||||
linux_scanner = libusb.get_devices
|
||||
if iswindows:
|
||||
try:
|
||||
win_scanner = plugins['winutil'][0].get_usb_devices
|
||||
except:
|
||||
raise RuntimeError('Failed to load the winutil plugin: %s'%plugins['winutil'][1])
|
||||
elif isosx:
|
||||
try:
|
||||
osx_scanner = plugins['usbobserver'][0].get_usb_devices
|
||||
except:
|
||||
raise RuntimeError('Failed to load the usbobserver plugin: %s'%plugins['usbobserver'][1])
|
||||
else:
|
||||
linux_scanner = libusb.get_devices
|
||||
|
||||
class DeviceScanner(object):
|
||||
|
||||
def __init__(self, wmi=None):
|
||||
self.wmi = wmi
|
||||
if iswindows and wmi is None:
|
||||
raise RuntimeError('You must pass a wmi instance to DeviceScanner on windows.')
|
||||
def __init__(self, *args):
|
||||
if isosx and osx_scanner is None:
|
||||
raise RuntimeError('The Python extension usbobserver must be available on OS X.')
|
||||
if not (isosx or iswindows) and not libusb.has_library():
|
||||
raise RuntimeError('DeviceScanner requires libusb to work.')
|
||||
|
||||
self.scanner = win_scanner if iswindows else osx_scanner if isosx else linux_scanner
|
||||
self.devices = []
|
||||
|
||||
def get_devices(self):
|
||||
if iswindows:
|
||||
devices = []
|
||||
for c in self.wmi.USBControllerDevice():
|
||||
devices.append(c.Dependent.DeviceID.upper())
|
||||
return devices
|
||||
if isosx:
|
||||
return osx_scanner()
|
||||
return linux_scanner()
|
||||
|
||||
def scan(self):
|
||||
try: # Windows WMI occasionally and temporarily barfs
|
||||
self.devices = self.get_devices()
|
||||
except Exception, e:
|
||||
if not iswindows and e:
|
||||
raise e
|
||||
|
||||
'''Fetch list of connected USB devices from operating system'''
|
||||
self.devices = self.scanner()
|
||||
|
||||
def is_device_connected(self, device):
|
||||
if iswindows:
|
||||
for device_id in self.devices:
|
||||
if 'VEN_'+device.VENDOR_NAME in device_id and \
|
||||
'PROD_'+device.PRODUCT_NAME in device_id:
|
||||
return True
|
||||
vid, pid = hex(device.VENDOR_ID)[2:], hex(device.PRODUCT_ID)[2:]
|
||||
if len(vid) < 4: vid = '0'+vid
|
||||
if len(pid) < 4: pid = '0'+pid
|
||||
vid, pid = 'VID_'+vid.upper(), 'PID_'+pid.upper()
|
||||
vid, pid = 'vid_%4.4x'%device.VENDOR_ID, 'pid_%4.4x'%device.PRODUCT_ID
|
||||
if vid in device_id and pid in device_id:
|
||||
return True
|
||||
return False
|
||||
|
@ -29,7 +29,7 @@
|
||||
|
||||
|
||||
static PyObject *
|
||||
usbobserver_get_devices(PyObject *self, PyObject *args) {
|
||||
usbobserver_get_usb_devices(PyObject *self, PyObject *args) {
|
||||
|
||||
mach_port_t masterPort;
|
||||
CFMutableDictionaryRef matchingDict;
|
||||
@ -62,7 +62,7 @@ usbobserver_get_devices(PyObject *self, PyObject *args) {
|
||||
PyObject *devices, *device;
|
||||
devices = PyList_New(0);
|
||||
if (devices == NULL) {
|
||||
PyErr_SetString(PyExc_RuntimeError, "Out of memory allocating list");
|
||||
PyErr_NoMemory();
|
||||
mach_port_deallocate(mach_task_self(), masterPort);
|
||||
return NULL;
|
||||
}
|
||||
@ -112,7 +112,7 @@ usbobserver_get_devices(PyObject *self, PyObject *args) {
|
||||
}
|
||||
|
||||
static PyMethodDef usbobserver_methods[] = {
|
||||
{"get_devices", usbobserver_get_devices, METH_VARARGS,
|
||||
{"get_usb_devices", usbobserver_get_usb_devices, METH_VARARGS,
|
||||
"Get list of connected USB devices. Returns a list of tuples. Each tuple is of the form (vendor_id, product_id)."
|
||||
},
|
||||
{NULL, NULL, 0, NULL}
|
||||
|
@ -1,489 +0,0 @@
|
||||
# Re-modified for use in MS LIT decryption. Un-reversed the bytebit[] array.
|
||||
# Substituted Microsoft's absurd modified S-boxes. Modified the
|
||||
# encrypt/decrypt methods to handle more than one block at a time. Added a few
|
||||
# speed-ups supported by modern versions of Python. Added option 'psyco' use.
|
||||
#
|
||||
# And lo, all the previous notices follow:
|
||||
|
||||
# Modified DES encryption for VNC password authentication.
|
||||
# Ported from realvnc's java viewer by <cliechti@gmx.net>
|
||||
# I chose this package name because it is not compatible with the
|
||||
# original DES algorithm, e.g. found pycrypto.
|
||||
#
|
||||
# (C) 2003 chris <cliechti@gmx.net>
|
||||
# Released as free software under the Python License.
|
||||
#
|
||||
# You're free to use it for commercial and noncommercial
|
||||
# application, modify and redistribute it as long as the
|
||||
# copyright notices are intact. There are no warranties, not
|
||||
# even that it does what it says to do ;-)
|
||||
#
|
||||
# Original notice following:
|
||||
|
||||
# This DES class has been extracted from package Acme.Crypto for use in VNC.
|
||||
# The bytebit[] array has been reversed so that the most significant bit
|
||||
# in each byte of the key is ignored, not the least significant. Also the
|
||||
# unnecessary odd parity code has been removed.
|
||||
#
|
||||
# These changes are:
|
||||
# Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved.
|
||||
#
|
||||
# This software is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
#
|
||||
|
||||
# DesCipher - the DES encryption method
|
||||
#
|
||||
# The meat of this code is by Dave Zimmerman <dzimm@widget.com>, and is:
|
||||
#
|
||||
# Copyright (c) 1996 Widget Workshop, Inc. All Rights Reserved.
|
||||
#
|
||||
# Permission to use, copy, modify, and distribute this software
|
||||
# and its documentation for NON-COMMERCIAL or COMMERCIAL purposes and
|
||||
# without fee is hereby granted, provided that this copyright notice is kept
|
||||
# intact.
|
||||
#
|
||||
# WIDGET WORKSHOP MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY
|
||||
# OF THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
|
||||
# TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
# PARTICULAR PURPOSE, OR NON-INFRINGEMENT. WIDGET WORKSHOP SHALL NOT BE LIABLE
|
||||
# FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
|
||||
# DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.
|
||||
#
|
||||
# THIS SOFTWARE IS NOT DESIGNED OR INTENDED FOR USE OR RESALE AS ON-LINE
|
||||
# CONTROL EQUIPMENT IN HAZARDOUS ENVIRONMENTS REQUIRING FAIL-SAFE
|
||||
# PERFORMANCE, SUCH AS IN THE OPERATION OF NUCLEAR FACILITIES, AIRCRAFT
|
||||
# NAVIGATION OR COMMUNICATION SYSTEMS, AIR TRAFFIC CONTROL, DIRECT LIFE
|
||||
# SUPPORT MACHINES, OR WEAPONS SYSTEMS, IN WHICH THE FAILURE OF THE
|
||||
# SOFTWARE COULD LEAD DIRECTLY TO DEATH, PERSONAL INJURY, OR SEVERE
|
||||
# PHYSICAL OR ENVIRONMENTAL DAMAGE ("HIGH RISK ACTIVITIES"). WIDGET WORKSHOP
|
||||
# SPECIFICALLY DISCLAIMS ANY EXPRESS OR IMPLIED WARRANTY OF FITNESS FOR
|
||||
# HIGH RISK ACTIVITIES.
|
||||
#
|
||||
#
|
||||
# The rest is:
|
||||
#
|
||||
# Copyright (C) 1996 by Jef Poskanzer <jef@acme.com>. All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
# SUCH DAMAGE.
|
||||
#
|
||||
# Visit the ACME Labs Java page for up-to-date versions of this and other
|
||||
# fine Java utilities: http://www.acme.com/java/
|
||||
|
||||
|
||||
#/ The DES encryption method.
|
||||
# <P>
|
||||
# This is surprisingly fast, for pure Java. On a SPARC 20, wrapped
|
||||
# in Acme.Crypto.EncryptedOutputStream or Acme.Crypto.EncryptedInputStream,
|
||||
# it does around 7000 bytes/second.
|
||||
# <P>
|
||||
# Most of this code is by Dave Zimmerman <dzimm@widget.com>, and is
|
||||
# Copyright (c) 1996 Widget Workshop, Inc. See the source file for details.
|
||||
# <P>
|
||||
# <A HREF="/resources/classes/Acme/Crypto/DesCipher.java">Fetch the software.</A><BR>
|
||||
# <A HREF="/resources/classes/Acme.tar.Z">Fetch the entire Acme package.</A>
|
||||
# <P>
|
||||
# @see Des3Cipher
|
||||
# @see EncryptedOutputStream
|
||||
# @see EncryptedInputStream
|
||||
|
||||
import struct
|
||||
|
||||
class DesCipher:
|
||||
# Constructor, byte-array key.
|
||||
def __init__(self, key):
|
||||
self.setKey(key)
|
||||
|
||||
#/ Set the key.
|
||||
def setKey(self, key):
|
||||
self.encryptKeys = self.deskey([ord(x) for x in key], 1)
|
||||
self.decryptKeys = self.deskey([ord(x) for x in key], 0)
|
||||
|
||||
# Turn an 8-byte key into internal keys.
|
||||
def deskey(self, keyBlock, encrypting):
|
||||
#~ int i, j, l, m, n;
|
||||
pc1m = [0]*56 #new int[56];
|
||||
pcr = [0]*56 #new int[56];
|
||||
kn = [0]*32 #new int[32];
|
||||
|
||||
for j in xrange(56):
|
||||
l = pc1[j]
|
||||
m = l & 07
|
||||
pc1m[j] = ((keyBlock[l >> 3] & bytebit[m]) != 0)
|
||||
for i in xrange(16):
|
||||
if encrypting:
|
||||
m = i << 1
|
||||
else:
|
||||
m = (15-i) << 1
|
||||
n = m + 1
|
||||
kn[m] = kn[n] = 0
|
||||
for j in xrange(28):
|
||||
l = j + totrot[i]
|
||||
if l < 28:
|
||||
pcr[j] = pc1m[l]
|
||||
else:
|
||||
pcr[j] = pc1m[l - 28]
|
||||
for j in xrange(28, 56):
|
||||
l = j + totrot[i]
|
||||
if l < 56:
|
||||
pcr[j] = pc1m[l]
|
||||
else:
|
||||
pcr[j] = pc1m[l - 28]
|
||||
for j in xrange(24):
|
||||
if pcr[pc2[j]] != 0:
|
||||
kn[m] |= bigbyte[j]
|
||||
if pcr[pc2[j+24]] != 0:
|
||||
kn[n] |= bigbyte[j]
|
||||
return self.cookey(kn)
|
||||
|
||||
def cookey(self, raw):
|
||||
#~ int raw0, raw1;
|
||||
#~ int rawi, KnLi;
|
||||
#~ int i;
|
||||
KnL = [0]*32
|
||||
|
||||
rawi = 0
|
||||
KnLi = 0
|
||||
for i in xrange(16):
|
||||
raw0 = raw[rawi]
|
||||
rawi += 1
|
||||
raw1 = raw[rawi]
|
||||
rawi += 1
|
||||
KnL[KnLi] = (raw0 & 0x00fc0000L) << 6
|
||||
KnL[KnLi] |= (raw0 & 0x00000fc0L) << 10
|
||||
KnL[KnLi] |= (raw1 & 0x00fc0000L) >> 10
|
||||
KnL[KnLi] |= (raw1 & 0x00000fc0L) >> 6
|
||||
KnLi += 1
|
||||
KnL[KnLi] = (raw0 & 0x0003f000L) << 12
|
||||
KnL[KnLi] |= (raw0 & 0x0000003fL) << 16
|
||||
KnL[KnLi] |= (raw1 & 0x0003f000L) >> 4
|
||||
KnL[KnLi] |= (raw1 & 0x0000003fL)
|
||||
KnLi += 1
|
||||
return KnL
|
||||
|
||||
# Block encryption routines.
|
||||
|
||||
#/ Encrypt a block of eight bytes.
|
||||
def encrypt(self, clearText):
|
||||
if len(clearText) % 8 != 0:
|
||||
raise TypeError, "length must be multiple of block size"
|
||||
result = []
|
||||
for base in xrange(0, len(clearText), 8):
|
||||
result.append(struct.pack(
|
||||
">LL", *self.des(struct.unpack(">LL", clearText[base:base+8]),
|
||||
self.encryptKeys)))
|
||||
return ''.join(result)
|
||||
|
||||
#/ Decrypt a block of eight bytes.
|
||||
def decrypt(self, cipherText):
|
||||
if len(cipherText) % 8 != 0:
|
||||
raise TypeError, "length must be multiple of block size"
|
||||
result = []
|
||||
for base in xrange(0, len(cipherText), 8):
|
||||
result.append(struct.pack(
|
||||
">LL", *self.des(struct.unpack(">LL", cipherText[base:base+8]),
|
||||
self.decryptKeys)))
|
||||
return ''.join(result)
|
||||
|
||||
# The DES function.
|
||||
def des(self, (leftt, right), keys):
|
||||
#~ int fval, work, right, leftt;
|
||||
#~ int round
|
||||
keysi = 0
|
||||
|
||||
work = ((leftt >> 4) ^ right) & 0x0f0f0f0fL
|
||||
right ^= work
|
||||
leftt ^= (work << 4) & 0xffffffffL
|
||||
|
||||
work = ((leftt >> 16) ^ right) & 0x0000ffffL
|
||||
right ^= work
|
||||
leftt ^= (work << 16) & 0xffffffffL
|
||||
|
||||
work = ((right >> 2) ^ leftt) & 0x33333333L
|
||||
leftt ^= work
|
||||
right ^= (work << 2) & 0xffffffffL
|
||||
|
||||
work = ((right >> 8) ^ leftt) & 0x00ff00ffL
|
||||
leftt ^= work
|
||||
right ^= (work << 8) & 0xffffffffL
|
||||
right = ((right << 1) | ((right >> 31) & 1)) & 0xffffffffL
|
||||
|
||||
work = (leftt ^ right) & 0xaaaaaaaaL
|
||||
leftt ^= work
|
||||
right ^= work
|
||||
leftt = ((leftt << 1) | ((leftt >> 31) & 1)) & 0xffffffffL
|
||||
|
||||
for round in xrange(8):
|
||||
work = ((right << 28) | (right >> 4)) & 0xffffffffL
|
||||
work ^= keys[keysi]
|
||||
keysi += 1
|
||||
fval = SP7[ work & 0x0000003fL ]
|
||||
fval |= SP5[(work >> 8) & 0x0000003fL ]
|
||||
fval |= SP3[(work >> 16) & 0x0000003fL ]
|
||||
fval |= SP1[(work >> 24) & 0x0000003fL ]
|
||||
work = right ^ keys[keysi]
|
||||
keysi += 1
|
||||
fval |= SP8[ work & 0x0000003fL ]
|
||||
fval |= SP6[(work >> 8) & 0x0000003fL ]
|
||||
fval |= SP4[(work >> 16) & 0x0000003fL ]
|
||||
fval |= SP2[(work >> 24) & 0x0000003fL ]
|
||||
leftt ^= fval
|
||||
work = ((leftt << 28) | (leftt >> 4)) & 0xffffffffL
|
||||
work ^= keys[keysi]
|
||||
keysi += 1
|
||||
fval = SP7[ work & 0x0000003fL ]
|
||||
fval |= SP5[(work >> 8) & 0x0000003fL ]
|
||||
fval |= SP3[(work >> 16) & 0x0000003fL ]
|
||||
fval |= SP1[(work >> 24) & 0x0000003fL ]
|
||||
work = leftt ^ keys[keysi]
|
||||
keysi += 1
|
||||
fval |= SP8[ work & 0x0000003fL ]
|
||||
fval |= SP6[(work >> 8) & 0x0000003fL ]
|
||||
fval |= SP4[(work >> 16) & 0x0000003fL ]
|
||||
fval |= SP2[(work >> 24) & 0x0000003fL ]
|
||||
right ^= fval
|
||||
|
||||
right = ((right << 31) | (right >> 1)) & 0xffffffffL
|
||||
work = (leftt ^ right) & 0xaaaaaaaaL
|
||||
leftt ^= work
|
||||
right ^= work
|
||||
leftt = ((leftt << 31) | (leftt >> 1)) & 0xffffffffL
|
||||
work = ((leftt >> 8) ^ right) & 0x00ff00ffL
|
||||
right ^= work
|
||||
leftt ^= (work << 8) & 0xffffffffL
|
||||
work = ((leftt >> 2) ^ right) & 0x33333333L
|
||||
right ^= work
|
||||
leftt ^= (work << 2) & 0xffffffffL
|
||||
work = ((right >> 16) ^ leftt) & 0x0000ffffL
|
||||
leftt ^= work
|
||||
right ^= (work << 16) & 0xffffffffL
|
||||
work = ((right >> 4) ^ leftt) & 0x0f0f0f0fL
|
||||
leftt ^= work
|
||||
right ^= (work << 4) & 0xffffffffL
|
||||
return right, leftt
|
||||
|
||||
# Tables, permutations, S-boxes, etc.
|
||||
|
||||
bytebit = [0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01]
|
||||
|
||||
bigbyte = [
|
||||
0x800000, 0x400000, 0x200000, 0x100000,
|
||||
0x080000, 0x040000, 0x020000, 0x010000,
|
||||
0x008000, 0x004000, 0x002000, 0x001000,
|
||||
0x000800, 0x000400, 0x000200, 0x000100,
|
||||
0x000080, 0x000040, 0x000020, 0x000010,
|
||||
0x000008, 0x000004, 0x000002, 0x000001
|
||||
]
|
||||
|
||||
pc1 = [
|
||||
56, 48, 40, 32, 24, 16, 8,
|
||||
0, 57, 49, 41, 33, 25, 17,
|
||||
9, 1, 58, 50, 42, 34, 26,
|
||||
18, 10, 2, 59, 51, 43, 35,
|
||||
62, 54, 46, 38, 30, 22, 14,
|
||||
6, 61, 53, 45, 37, 29, 21,
|
||||
13, 5, 60, 52, 44, 36, 28,
|
||||
20, 12, 4, 27, 19, 11, 3
|
||||
]
|
||||
|
||||
totrot = [
|
||||
1, 2, 4, 6, 8, 10, 12, 14, 15, 17, 19, 21, 23, 25, 27, 28
|
||||
]
|
||||
|
||||
pc2 = [
|
||||
13, 16, 10, 23, 0, 4,
|
||||
2, 27, 14, 5, 20, 9,
|
||||
22, 18, 11, 3 , 25, 7,
|
||||
15, 6, 26, 19, 12, 1,
|
||||
40, 51, 30, 36, 46, 54,
|
||||
29, 39, 50, 44, 32, 47,
|
||||
43, 48, 38, 55, 33, 52,
|
||||
45, 41, 49, 35, 28, 31,
|
||||
]
|
||||
|
||||
# Microsoft's modified S-boxes for LIT file encryption
|
||||
SP1 = [
|
||||
0x02080800L, 0x00080000L, 0x02000002L, 0x02080802L,
|
||||
0x02000000L, 0x00080802L, 0x00080002L, 0x02000002L,
|
||||
0x00080802L, 0x02080800L, 0x02080000L, 0x00000802L,
|
||||
0x02000802L, 0x02000000L, 0x00000000L, 0x00080002L,
|
||||
0x00080000L, 0x00000002L, 0x02000800L, 0x00080800L,
|
||||
0x02080802L, 0x02080000L, 0x00000802L, 0x02000800L,
|
||||
0x00000002L, 0x00000800L, 0x00080800L, 0x02080002L,
|
||||
0x00000800L, 0x02000802L, 0x02080002L, 0x00000000L,
|
||||
0x00000000L, 0x02080802L, 0x02000800L, 0x00080002L,
|
||||
0x02080800L, 0x00080000L, 0x00000802L, 0x02000800L,
|
||||
0x02080002L, 0x00000800L, 0x00080800L, 0x02000002L,
|
||||
0x00080802L, 0x00000002L, 0x02000002L, 0x02080000L,
|
||||
0x02080802L, 0x00080800L, 0x02080000L, 0x02000802L,
|
||||
0x02000000L, 0x00000802L, 0x00080002L, 0x00000000L,
|
||||
0x00080000L, 0x02000000L, 0x02000802L, 0x02080800L,
|
||||
0x00000002L, 0x02080002L, 0x00000800L, 0x00080802L
|
||||
]
|
||||
SP2 = [
|
||||
0x40108010L, 0x00000000L, 0x00108000L, 0x40100000L,
|
||||
0x40000010L, 0x00008010L, 0x40008000L, 0x00108000L,
|
||||
0x00008000L, 0x40100010L, 0x00000010L, 0x40008000L,
|
||||
0x00100010L, 0x40108000L, 0x40100000L, 0x00000010L,
|
||||
0x00100000L, 0x40008010L, 0x40100010L, 0x00008000L,
|
||||
0x00108010L, 0x40000000L, 0x00000000L, 0x00100010L,
|
||||
0x40008010L, 0x00108010L, 0x40108000L, 0x40000010L,
|
||||
0x40000000L, 0x00100000L, 0x00008010L, 0x40108010L,
|
||||
0x00100010L, 0x40108000L, 0x40008000L, 0x00108010L,
|
||||
0x40108010L, 0x00100010L, 0x40000010L, 0x00000000L,
|
||||
0x40000000L, 0x00008010L, 0x00100000L, 0x40100010L,
|
||||
0x00008000L, 0x40000000L, 0x00108010L, 0x40008010L,
|
||||
0x40108000L, 0x00008000L, 0x00000000L, 0x40000010L,
|
||||
0x00000010L, 0x40108010L, 0x00108000L, 0x40100000L,
|
||||
0x40100010L, 0x00100000L, 0x00008010L, 0x40008000L,
|
||||
0x40008010L, 0x00000010L, 0x40100000L, 0x00108000L
|
||||
]
|
||||
SP3 = [
|
||||
0x04000001L, 0x04040100L, 0x00000100L, 0x04000101L,
|
||||
0x00040001L, 0x04000000L, 0x04000101L, 0x00040100L,
|
||||
0x04000100L, 0x00040000L, 0x04040000L, 0x00000001L,
|
||||
0x04040101L, 0x00000101L, 0x00000001L, 0x04040001L,
|
||||
0x00000000L, 0x00040001L, 0x04040100L, 0x00000100L,
|
||||
0x00000101L, 0x04040101L, 0x00040000L, 0x04000001L,
|
||||
0x04040001L, 0x04000100L, 0x00040101L, 0x04040000L,
|
||||
0x00040100L, 0x00000000L, 0x04000000L, 0x00040101L,
|
||||
0x04040100L, 0x00000100L, 0x00000001L, 0x00040000L,
|
||||
0x00000101L, 0x00040001L, 0x04040000L, 0x04000101L,
|
||||
0x00000000L, 0x04040100L, 0x00040100L, 0x04040001L,
|
||||
0x00040001L, 0x04000000L, 0x04040101L, 0x00000001L,
|
||||
0x00040101L, 0x04000001L, 0x04000000L, 0x04040101L,
|
||||
0x00040000L, 0x04000100L, 0x04000101L, 0x00040100L,
|
||||
0x04000100L, 0x00000000L, 0x04040001L, 0x00000101L,
|
||||
0x04000001L, 0x00040101L, 0x00000100L, 0x04040000L
|
||||
]
|
||||
SP4 = [
|
||||
0x00401008L, 0x10001000L, 0x00000008L, 0x10401008L,
|
||||
0x00000000L, 0x10400000L, 0x10001008L, 0x00400008L,
|
||||
0x10401000L, 0x10000008L, 0x10000000L, 0x00001008L,
|
||||
0x10000008L, 0x00401008L, 0x00400000L, 0x10000000L,
|
||||
0x10400008L, 0x00401000L, 0x00001000L, 0x00000008L,
|
||||
0x00401000L, 0x10001008L, 0x10400000L, 0x00001000L,
|
||||
0x00001008L, 0x00000000L, 0x00400008L, 0x10401000L,
|
||||
0x10001000L, 0x10400008L, 0x10401008L, 0x00400000L,
|
||||
0x10400008L, 0x00001008L, 0x00400000L, 0x10000008L,
|
||||
0x00401000L, 0x10001000L, 0x00000008L, 0x10400000L,
|
||||
0x10001008L, 0x00000000L, 0x00001000L, 0x00400008L,
|
||||
0x00000000L, 0x10400008L, 0x10401000L, 0x00001000L,
|
||||
0x10000000L, 0x10401008L, 0x00401008L, 0x00400000L,
|
||||
0x10401008L, 0x00000008L, 0x10001000L, 0x00401008L,
|
||||
0x00400008L, 0x00401000L, 0x10400000L, 0x10001008L,
|
||||
0x00001008L, 0x10000000L, 0x10000008L, 0x10401000L
|
||||
]
|
||||
SP5 = [
|
||||
0x08000000L, 0x00010000L, 0x00000400L, 0x08010420L,
|
||||
0x08010020L, 0x08000400L, 0x00010420L, 0x08010000L,
|
||||
0x00010000L, 0x00000020L, 0x08000020L, 0x00010400L,
|
||||
0x08000420L, 0x08010020L, 0x08010400L, 0x00000000L,
|
||||
0x00010400L, 0x08000000L, 0x00010020L, 0x00000420L,
|
||||
0x08000400L, 0x00010420L, 0x00000000L, 0x08000020L,
|
||||
0x00000020L, 0x08000420L, 0x08010420L, 0x00010020L,
|
||||
0x08010000L, 0x00000400L, 0x00000420L, 0x08010400L,
|
||||
0x08010400L, 0x08000420L, 0x00010020L, 0x08010000L,
|
||||
0x00010000L, 0x00000020L, 0x08000020L, 0x08000400L,
|
||||
0x08000000L, 0x00010400L, 0x08010420L, 0x00000000L,
|
||||
0x00010420L, 0x08000000L, 0x00000400L, 0x00010020L,
|
||||
0x08000420L, 0x00000400L, 0x00000000L, 0x08010420L,
|
||||
0x08010020L, 0x08010400L, 0x00000420L, 0x00010000L,
|
||||
0x00010400L, 0x08010020L, 0x08000400L, 0x00000420L,
|
||||
0x00000020L, 0x00010420L, 0x08010000L, 0x08000020L
|
||||
]
|
||||
SP6 = [
|
||||
0x80000040L, 0x00200040L, 0x00000000L, 0x80202000L,
|
||||
0x00200040L, 0x00002000L, 0x80002040L, 0x00200000L,
|
||||
0x00002040L, 0x80202040L, 0x00202000L, 0x80000000L,
|
||||
0x80002000L, 0x80000040L, 0x80200000L, 0x00202040L,
|
||||
0x00200000L, 0x80002040L, 0x80200040L, 0x00000000L,
|
||||
0x00002000L, 0x00000040L, 0x80202000L, 0x80200040L,
|
||||
0x80202040L, 0x80200000L, 0x80000000L, 0x00002040L,
|
||||
0x00000040L, 0x00202000L, 0x00202040L, 0x80002000L,
|
||||
0x00002040L, 0x80000000L, 0x80002000L, 0x00202040L,
|
||||
0x80202000L, 0x00200040L, 0x00000000L, 0x80002000L,
|
||||
0x80000000L, 0x00002000L, 0x80200040L, 0x00200000L,
|
||||
0x00200040L, 0x80202040L, 0x00202000L, 0x00000040L,
|
||||
0x80202040L, 0x00202000L, 0x00200000L, 0x80002040L,
|
||||
0x80000040L, 0x80200000L, 0x00202040L, 0x00000000L,
|
||||
0x00002000L, 0x80000040L, 0x80002040L, 0x80202000L,
|
||||
0x80200000L, 0x00002040L, 0x00000040L, 0x80200040L,
|
||||
]
|
||||
SP7 = [
|
||||
0x00004000L, 0x00000200L, 0x01000200L, 0x01000004L,
|
||||
0x01004204L, 0x00004004L, 0x00004200L, 0x00000000L,
|
||||
0x01000000L, 0x01000204L, 0x00000204L, 0x01004000L,
|
||||
0x00000004L, 0x01004200L, 0x01004000L, 0x00000204L,
|
||||
0x01000204L, 0x00004000L, 0x00004004L, 0x01004204L,
|
||||
0x00000000L, 0x01000200L, 0x01000004L, 0x00004200L,
|
||||
0x01004004L, 0x00004204L, 0x01004200L, 0x00000004L,
|
||||
0x00004204L, 0x01004004L, 0x00000200L, 0x01000000L,
|
||||
0x00004204L, 0x01004000L, 0x01004004L, 0x00000204L,
|
||||
0x00004000L, 0x00000200L, 0x01000000L, 0x01004004L,
|
||||
0x01000204L, 0x00004204L, 0x00004200L, 0x00000000L,
|
||||
0x00000200L, 0x01000004L, 0x00000004L, 0x01000200L,
|
||||
0x00000000L, 0x01000204L, 0x01000200L, 0x00004200L,
|
||||
0x00000204L, 0x00004000L, 0x01004204L, 0x01000000L,
|
||||
0x01004200L, 0x00000004L, 0x00004004L, 0x01004204L,
|
||||
0x01000004L, 0x01004200L, 0x01004000L, 0x00004004L,
|
||||
]
|
||||
SP8 = [
|
||||
0x20800080L, 0x20820000L, 0x00020080L, 0x00000000L,
|
||||
0x20020000L, 0x00800080L, 0x20800000L, 0x20820080L,
|
||||
0x00000080L, 0x20000000L, 0x00820000L, 0x00020080L,
|
||||
0x00820080L, 0x20020080L, 0x20000080L, 0x20800000L,
|
||||
0x00020000L, 0x00820080L, 0x00800080L, 0x20020000L,
|
||||
0x20820080L, 0x20000080L, 0x00000000L, 0x00820000L,
|
||||
0x20000000L, 0x00800000L, 0x20020080L, 0x20800080L,
|
||||
0x00800000L, 0x00020000L, 0x20820000L, 0x00000080L,
|
||||
0x00800000L, 0x00020000L, 0x20000080L, 0x20820080L,
|
||||
0x00020080L, 0x20000000L, 0x00000000L, 0x00820000L,
|
||||
0x20800080L, 0x20020080L, 0x20020000L, 0x00800080L,
|
||||
0x20820000L, 0x00000080L, 0x00800080L, 0x20020000L,
|
||||
0x20820080L, 0x00800000L, 0x20800000L, 0x20000080L,
|
||||
0x00820000L, 0x00020080L, 0x20020080L, 0x20800000L,
|
||||
0x00000080L, 0x20820000L, 0x00820080L, 0x00000000L,
|
||||
0x20000000L, 0x20800080L, 0x00020000L, 0x00820080L,
|
||||
]
|
||||
|
||||
def new(key):
|
||||
return DesCipher(key)
|
||||
|
||||
block_size = 8
|
||||
key_size = 8
|
||||
|
||||
try:
|
||||
import psyco
|
||||
psyco.bind(DesCipher.deskey)
|
||||
psyco.bind(DesCipher.cookey)
|
||||
psyco.bind(DesCipher.des)
|
||||
except ImportError:
|
||||
pass
|
||||
|
||||
#test only:
|
||||
if __name__ == '__main__':
|
||||
des = DesCipher("\x01\x23\x45\x67\x89\xab\xcd\xef")
|
||||
print ''.join(
|
||||
"%02x" % ord(x) for x in des.encrypt("Now is t"))
|
||||
|
@ -9,12 +9,13 @@ __copyright__ = '2008, Kovid Goyal <kovid at kovidgoyal.net> ' \
|
||||
|
||||
import sys, struct, cStringIO, os
|
||||
import functools
|
||||
import re
|
||||
from calibre.ebooks.lit import LitError
|
||||
from calibre.ebooks.lit.maps import OPF_MAP, HTML_MAP
|
||||
import calibre.ebooks.lit.mssha1 as mssha1
|
||||
import calibre.ebooks.lit.msdes as msdes
|
||||
from calibre import plugins
|
||||
lzx, lxzerror = plugins['lzx']
|
||||
msdes, msdeserror = plugins['msdes']
|
||||
|
||||
OPF_DECL = """<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<!DOCTYPE package
|
||||
@ -84,7 +85,7 @@ def read_utf8_char(bytes, pos):
|
||||
if elsize + pos > len(bytes):
|
||||
raise LitError('Invalid UTF8 character: %s' % repr(bytes[pos]))
|
||||
c &= (mask - 1)
|
||||
for i in range(1, elsize):
|
||||
for i in xrange(1, elsize):
|
||||
b = ord(bytes[pos+i])
|
||||
if (b & 0xC0) != 0x80:
|
||||
raise LitError(
|
||||
@ -92,34 +93,32 @@ def read_utf8_char(bytes, pos):
|
||||
c = (c << 6) | (b & 0x3F)
|
||||
return unichr(c), pos+elsize
|
||||
|
||||
def consume_sized_utf8_string(bytes, zpad=False):
|
||||
result = []
|
||||
slen, pos = read_utf8_char(bytes, 0)
|
||||
for i in xrange(ord(slen)):
|
||||
char, pos = read_utf8_char(bytes, pos)
|
||||
result.append(char)
|
||||
if zpad and bytes[pos] == '\000':
|
||||
pos += 1
|
||||
return u''.join(result), bytes[pos:]
|
||||
|
||||
class UnBinary(object):
|
||||
AMPERSAND_RE = re.compile(
|
||||
r'&(?!(?:#[0-9]+|#x[0-9a-fA-F]+|[a-zA-Z_:][a-zA-Z0-9.-_:]+);)')
|
||||
|
||||
def __init__(self, bin, manifest, map=OPF_MAP):
|
||||
self.manifest = manifest
|
||||
self.tag_map, self.attr_map, self.tag_to_attr_map = map
|
||||
self.opf = map is OPF_MAP
|
||||
self.bin = bin
|
||||
self.buf = cStringIO.StringIO()
|
||||
self.ampersands = []
|
||||
self.binary_to_text()
|
||||
self.raw = self.buf.getvalue().lstrip().decode('utf-8')
|
||||
self.escape_ampersands()
|
||||
|
||||
def escape_ampersands(self):
|
||||
offset = 0
|
||||
for pos in self.ampersands:
|
||||
test = self.raw[pos+offset:pos+offset+6]
|
||||
if test.startswith('&#') and ';' in test:
|
||||
continue
|
||||
escape = True
|
||||
for ent in XML_ENTITIES:
|
||||
if test.startswith(ent):
|
||||
escape = False
|
||||
break
|
||||
if not escape:
|
||||
continue
|
||||
self.raw = '&'.join(
|
||||
(self.raw[:pos+offset], self.raw[pos+offset+1:]))
|
||||
offset += 4
|
||||
self.raw = self.AMPERSAND_RE.sub('&', self.raw)
|
||||
|
||||
def item_path(self, internal_id):
|
||||
try:
|
||||
@ -148,8 +147,6 @@ class UnBinary(object):
|
||||
continue
|
||||
elif c == '\v':
|
||||
c = '\n'
|
||||
elif c == '&':
|
||||
self.ampersands.append(self.buf.tell()-1)
|
||||
self.buf.write(c.encode('utf-8'))
|
||||
|
||||
elif state == 'get flags':
|
||||
@ -328,8 +325,11 @@ class ManifestItem(object):
|
||||
self.offset = offset
|
||||
self.root = root
|
||||
self.state = state
|
||||
# Some LIT files have Windows-style paths
|
||||
path = original.replace('\\', '/')
|
||||
if path[1:3] == ':/': path = path[2:]
|
||||
# Some paths in Fictionwise "multiformat" LIT files contain '..' (!?)
|
||||
path = os.path.normpath(original).replace('\\', '/')
|
||||
path = os.path.normpath(path).replace('\\', '/')
|
||||
while path.startswith('../'): path = path[3:]
|
||||
self.path = path
|
||||
|
||||
@ -475,7 +475,7 @@ class LitReader(object):
|
||||
|
||||
def _read_header_pieces(self):
|
||||
src = self.header[self.hdr_len:]
|
||||
for i in range(self.num_pieces):
|
||||
for i in xrange(self.num_pieces):
|
||||
piece = src[i * self.PIECE_SIZE:(i + 1) * self.PIECE_SIZE]
|
||||
if u32(piece[4:]) != 0 or u32(piece[12:]) != 0:
|
||||
raise LitError('Piece %s has 64bit value' % repr(piece))
|
||||
@ -525,7 +525,7 @@ class LitReader(object):
|
||||
raise LitError('Directory entry had 64bit name length.')
|
||||
if namelen > remaining - 3:
|
||||
raise LitError('Read past end of directory chunk')
|
||||
name, chunk = chunk[:namelen], chunk[namelen:]
|
||||
name, chunk = chunk[:namelen].decode('utf-8'), chunk[namelen:]
|
||||
section, chunk, remaining = encint(chunk, remaining)
|
||||
offset, chunk, remaining = encint(chunk, remaining)
|
||||
size, chunk, remaining = encint(chunk, remaining)
|
||||
@ -542,7 +542,7 @@ class LitReader(object):
|
||||
self.num_sections = u16(raw[2:pos])
|
||||
self.section_names = [""]*self.num_sections
|
||||
self.section_data = [None]*self.num_sections
|
||||
for section in range(self.num_sections):
|
||||
for section in xrange(self.num_sections):
|
||||
size = u16(raw[pos:pos+2])
|
||||
pos += 2
|
||||
size = size*2 + 2
|
||||
@ -570,15 +570,15 @@ class LitReader(object):
|
||||
if len(raw) < 5:
|
||||
raise LitError('Truncated manifest')
|
||||
offset, raw = u32(raw), raw[4:]
|
||||
slen, raw = ord(raw[0]), raw[1:]
|
||||
internal, raw = raw[:slen].decode('utf8'), raw[slen:]
|
||||
slen, raw = ord(raw[0]), raw[1:]
|
||||
original, raw = raw[:slen].decode('utf8'), raw[slen:]
|
||||
slen, raw = ord(raw[0]), raw[1:]
|
||||
mime_type, raw = raw[:slen].decode('utf8'), raw[slen+1:]
|
||||
internal, raw = consume_sized_utf8_string(raw)
|
||||
original, raw = consume_sized_utf8_string(raw)
|
||||
# Is this last one UTF-8 or ASCIIZ?
|
||||
mime_type, raw = consume_sized_utf8_string(raw, zpad=True)
|
||||
self.manifest[internal] = ManifestItem(
|
||||
original, internal, mime_type, offset, root, state)
|
||||
mlist = self.manifest.values()
|
||||
# Remove any common path elements
|
||||
if len(mlist) > 1:
|
||||
shared = mlist[0].path
|
||||
for item in mlist[1:]:
|
||||
path = item.path
|
||||
@ -591,6 +591,10 @@ class LitReader(object):
|
||||
slen = len(shared)
|
||||
for item in mlist:
|
||||
item.path = item.path[slen:]
|
||||
# Fix any straggling absolute paths
|
||||
for item in mlist:
|
||||
if item.path[0] == '/':
|
||||
item.path = os.path.basename(item.path)
|
||||
|
||||
def _read_meta(self):
|
||||
raw = self.get_file('/meta')
|
||||
@ -614,8 +618,8 @@ class LitReader(object):
|
||||
self.drmlevel = 1
|
||||
else:
|
||||
return
|
||||
des = msdes.new(self._calculate_deskey())
|
||||
bookkey = des.decrypt(self.get_file('/DRMStorage/DRMSealed'))
|
||||
msdes.deskey(self._calculate_deskey(), msdes.DE1)
|
||||
bookkey = msdes.des(self.get_file('/DRMStorage/DRMSealed'))
|
||||
if bookkey[0] != '\000':
|
||||
raise LitError('Unable to decrypt title key!')
|
||||
self.bookkey = bookkey[1:9]
|
||||
@ -690,7 +694,8 @@ class LitReader(object):
|
||||
def _decrypt(self, content):
|
||||
if self.drmlevel == 5:
|
||||
raise LitError('Cannot extract content from a DRM protected ebook')
|
||||
return msdes.new(self.bookkey).decrypt(content)
|
||||
msdes.deskey(self.bookkey, msdes.DE1)
|
||||
return msdes.des(content)
|
||||
|
||||
def _decompress(self, content, control, reset_table):
|
||||
if len(control) < 32 or control[CONTROL_TAG:CONTROL_TAG+4] != "LZXC":
|
||||
@ -792,5 +797,12 @@ def main(args=sys.argv):
|
||||
print _('OEB ebook created in'), opts.output_dir
|
||||
return 0
|
||||
|
||||
try:
|
||||
import psyco
|
||||
psyco.bind(read_utf8_char)
|
||||
psyco.bind(UnBinary.binary_to_text)
|
||||
except ImportError:
|
||||
pass
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.exit(main())
|
||||
|
16
src/calibre/ebooks/lrf/comic/__init__.py
Normal file
16
src/calibre/ebooks/lrf/comic/__init__.py
Normal file
@ -0,0 +1,16 @@
|
||||
#!/usr/bin/env python
|
||||
__license__ = 'GPL v3'
|
||||
__copyright__ = '2008, Kovid Goyal kovid@kovidgoyal.net'
|
||||
__docformat__ = 'restructuredtext en'
|
||||
|
||||
'''
|
||||
Convert CBR/CBZ files to LRF.
|
||||
'''
|
||||
|
||||
import sys
|
||||
|
||||
def main(args=sys.argv):
|
||||
return 0
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.exit(main())
|
321
src/calibre/ebooks/lrf/comic/convert_from.py
Executable file
321
src/calibre/ebooks/lrf/comic/convert_from.py
Executable file
@ -0,0 +1,321 @@
|
||||
#!/usr/bin/env python
|
||||
__license__ = 'GPL v3'
|
||||
__copyright__ = '2008, Kovid Goyal kovid@kovidgoyal.net'
|
||||
__docformat__ = 'restructuredtext en'
|
||||
|
||||
'''
|
||||
Based on ideas from comiclrf created by FangornUK.
|
||||
'''
|
||||
|
||||
import os, sys, traceback, shutil
|
||||
from uuid import uuid4
|
||||
|
||||
from calibre import extract, OptionParser, detect_ncpus, terminal_controller, \
|
||||
__appname__, __version__
|
||||
from calibre.ptempfile import PersistentTemporaryDirectory
|
||||
from calibre.utils.threadpool import ThreadPool, WorkRequest
|
||||
from calibre.utils.terminfo import ProgressBar
|
||||
from calibre.ebooks.lrf.pylrs.pylrs import Book, BookSetting, ImageStream, ImageBlock
|
||||
try:
|
||||
from calibre.utils.PythonMagickWand import \
|
||||
NewMagickWand, NewPixelWand, \
|
||||
MagickSetImageBorderColor, \
|
||||
MagickReadImage, MagickRotateImage, \
|
||||
MagickTrimImage, \
|
||||
MagickNormalizeImage, MagickGetImageWidth, \
|
||||
MagickGetImageHeight, \
|
||||
MagickResizeImage, MagickSetImageType, \
|
||||
GrayscaleType, CatromFilter, MagickSetImagePage, \
|
||||
MagickBorderImage, MagickSharpenImage, \
|
||||
MagickQuantizeImage, RGBColorspace, \
|
||||
MagickWriteImage, DestroyPixelWand, \
|
||||
DestroyMagickWand, CloneMagickWand, \
|
||||
MagickThumbnailImage, MagickCropImage, initialize, finalize
|
||||
_imagemagick_loaded = True
|
||||
except:
|
||||
_imagemagick_loaded = False
|
||||
|
||||
PROFILES = {
|
||||
'prs500':(584, 754),
|
||||
}
|
||||
|
||||
def extract_comic(path_to_comic_file):
|
||||
'''
|
||||
Un-archive the comic file.
|
||||
'''
|
||||
tdir = PersistentTemporaryDirectory(suffix='comic_extract')
|
||||
extract(path_to_comic_file, tdir)
|
||||
return tdir
|
||||
|
||||
def find_pages(dir, sort_on_mtime=False, verbose=False):
|
||||
'''
|
||||
Find valid comic pages in a previously un-archived comic.
|
||||
|
||||
:param dir: Directory in which extracted comic lives
|
||||
:param sort_on_mtime: If True sort pages based on their last modified time.
|
||||
Otherwise, sort alphabetically.
|
||||
'''
|
||||
extensions = ['jpeg', 'jpg', 'gif', 'png']
|
||||
pages = []
|
||||
for datum in os.walk(dir):
|
||||
for name in datum[-1]:
|
||||
path = os.path.join(datum[0], name)
|
||||
for ext in extensions:
|
||||
if path.lower().endswith('.'+ext):
|
||||
pages.append(path)
|
||||
break
|
||||
if sort_on_mtime:
|
||||
comparator = lambda x, y : cmp(os.stat(x).st_mtime, os.stat(y).st_mtime)
|
||||
else:
|
||||
comparator = lambda x, y : cmp(os.path.basename(x), os.path.basename(y))
|
||||
|
||||
pages.sort(cmp=comparator)
|
||||
if verbose:
|
||||
print 'Found comic pages...'
|
||||
print '\t'+'\n\t'.join([os.path.basename(p) for p in pages])
|
||||
return pages
|
||||
|
||||
class PageProcessor(list):
|
||||
'''
|
||||
Contains the actual image rendering logic. See :method:`__call__` and
|
||||
:method:`process_pages`.
|
||||
'''
|
||||
|
||||
def __init__(self, path_to_page, dest, opts, num):
|
||||
self.path_to_page = path_to_page
|
||||
self.opts = opts
|
||||
self.num = num
|
||||
self.dest = dest
|
||||
self.rotate = False
|
||||
list.__init__(self)
|
||||
|
||||
def __call__(self):
|
||||
try:
|
||||
img = NewMagickWand()
|
||||
if img < 0:
|
||||
raise RuntimeError('Cannot create wand.')
|
||||
if not MagickReadImage(img, self.path_to_page):
|
||||
raise IOError('Failed to read image from: %'%self.path_to_page)
|
||||
width = MagickGetImageWidth(img)
|
||||
height = MagickGetImageHeight(img)
|
||||
|
||||
if self.num == 0: # First image so create a thumbnail from it
|
||||
thumb = CloneMagickWand(img)
|
||||
if thumb < 0:
|
||||
raise RuntimeError('Cannot create wand.')
|
||||
MagickThumbnailImage(thumb, 60, 80)
|
||||
MagickWriteImage(thumb, os.path.join(self.dest, 'thumbnail.png'))
|
||||
DestroyMagickWand(thumb)
|
||||
|
||||
self.pages = [img]
|
||||
|
||||
if width > height:
|
||||
if self.opts.landscape:
|
||||
self.rotate = True
|
||||
else:
|
||||
split1, split2 = map(CloneMagickWand, (img, img))
|
||||
if split1 < 0 or split2 < 0:
|
||||
raise RuntimeError('Cannot create wand.')
|
||||
DestroyMagickWand(img)
|
||||
MagickCropImage(split1, (width/2)-1, height, 0, 0)
|
||||
MagickCropImage(split2, (width/2)-1, height, width/2, 0 )
|
||||
self.pages = [split1, split2]
|
||||
|
||||
self.process_pages()
|
||||
except Exception, err:
|
||||
print 'Failed to process page: %s'%os.path.basename(self.path_to_page)
|
||||
print 'Error:', err
|
||||
if self.opts.verbose:
|
||||
traceback.print_exc()
|
||||
|
||||
def process_pages(self):
|
||||
for i, wand in enumerate(self.pages):
|
||||
pw = NewPixelWand()
|
||||
if pw < 0:
|
||||
raise RuntimeError('Cannot create wand.')
|
||||
#flag = PixelSetColor(pw, 'white')
|
||||
|
||||
MagickSetImageBorderColor(wand, pw)
|
||||
|
||||
if self.rotate:
|
||||
MagickRotateImage(wand, pw, -90)
|
||||
|
||||
# 25 percent fuzzy trim?
|
||||
MagickTrimImage(wand, 25*65535/100)
|
||||
MagickSetImagePage(wand, 0,0,0,0) #Clear page after trim, like a "+repage"
|
||||
|
||||
# Do the Photoshop "Auto Levels" equivalent
|
||||
if self.opts.normalize:
|
||||
MagickNormalizeImage(wand)
|
||||
|
||||
sizex = MagickGetImageWidth(wand)
|
||||
sizey = MagickGetImageHeight(wand)
|
||||
|
||||
SCRWIDTH, SCRHEIGHT = PROFILES[self.opts.profile]
|
||||
|
||||
if self.opts.keep_aspect_ratio:
|
||||
# Preserve the aspect ratio by adding border
|
||||
aspect = float(sizex) / float(sizey)
|
||||
if aspect <= (float(SCRWIDTH) / float(SCRHEIGHT)):
|
||||
newsizey = SCRHEIGHT
|
||||
newsizex = int(newsizey * aspect)
|
||||
deltax = (SCRWIDTH - newsizex) / 2
|
||||
deltay = 0
|
||||
else:
|
||||
newsizex = SCRWIDTH
|
||||
newsizey = int(newsizex / aspect)
|
||||
deltax = 0
|
||||
deltay = (SCRHEIGHT - newsizey) / 2
|
||||
|
||||
MagickResizeImage(wand, newsizex, newsizey, CatromFilter, 1.0)
|
||||
MagickSetImageBorderColor(wand, pw)
|
||||
MagickBorderImage(wand, pw, deltax, deltay)
|
||||
else:
|
||||
MagickResizeImage(wand, SCRWIDTH, SCRHEIGHT, CatromFilter, 1.0)
|
||||
|
||||
if self.opts.sharpen:
|
||||
MagickSharpenImage(wand, 0.0, 1.0)
|
||||
|
||||
MagickSetImageType(wand, GrayscaleType)
|
||||
MagickQuantizeImage(wand, self.opts.colors, RGBColorspace, 0, 1, 0)
|
||||
dest = '%d_%d%s'%(self.num, i, os.path.splitext(self.path_to_page)[-1])
|
||||
dest = os.path.join(self.dest, dest)
|
||||
MagickWriteImage(wand, dest)
|
||||
self.append(dest)
|
||||
|
||||
DestroyPixelWand(pw)
|
||||
wand = DestroyMagickWand(wand)
|
||||
|
||||
class Progress(object):
|
||||
|
||||
def __init__(self, total, update):
|
||||
self.total = total
|
||||
self.update = update
|
||||
self.done = 0
|
||||
|
||||
def __call__(self, req, res):
|
||||
self.done += 1
|
||||
self.update(float(self.done)/self.total,
|
||||
_('Rendered %s')%os.path.basename(req.callable.path_to_page))
|
||||
|
||||
def process_pages(pages, opts, update):
|
||||
'''
|
||||
Render all identified comic pages.
|
||||
'''
|
||||
if not _imagemagick_loaded:
|
||||
raise RuntimeError('Failed to load ImageMagick')
|
||||
initialize()
|
||||
try:
|
||||
tdir = PersistentTemporaryDirectory('_comic2lrf_pp')
|
||||
processed_pages = [PageProcessor(path, tdir, opts, i) for i, path in enumerate(pages)]
|
||||
tp = ThreadPool(detect_ncpus())
|
||||
update(0, '')
|
||||
notify = Progress(len(pages), update)
|
||||
for pp in processed_pages:
|
||||
tp.putRequest(WorkRequest(pp, callback=notify))
|
||||
tp.wait()
|
||||
ans, failures = [], []
|
||||
|
||||
for pp in processed_pages:
|
||||
if len(pp) == 0:
|
||||
failures.append(os.path.basename(pp.path_to_page()))
|
||||
else:
|
||||
ans += pp
|
||||
return ans, failures, tdir
|
||||
finally:
|
||||
finalize()
|
||||
|
||||
def option_parser():
|
||||
parser = OptionParser(_('''\
|
||||
%prog [options] comic.cb[z|r]
|
||||
|
||||
Convert a comic in a CBZ or CBR file to an LRF ebook.
|
||||
'''))
|
||||
parser.add_option('-t', '--title', help=_('Title for generated ebook. Default is to use the filename.'), default=None)
|
||||
parser.add_option('-a', '--author', help=_('Set the author in the metadata of the generated ebook. Default is %default'), default=_('Unknown'))
|
||||
parser.add_option('-o', '--output', help=_('Path to output LRF file. By default a file is created in the current directory.'), default=None)
|
||||
parser.add_option('-c', '--colors', type='int', default=64,
|
||||
help=_('Number of colors for Grayscale image conversion. Default: %default'))
|
||||
parser.add_option('-n', '--disable-normalize', dest='normalize', default=True, action='store_false',
|
||||
help=_('Disable normalize (improve contrast) color range for pictures. Default: False'))
|
||||
parser.add_option('-r', '--keep-aspect-ratio', action='store_true', default=False,
|
||||
help=_('Maintain picture aspect ratio. Default is to fill the screen.'))
|
||||
parser.add_option('-s', '--disable-sharpen', default=True, action='store_false', dest='sharpen',
|
||||
help=_('Disable sharpening.'))
|
||||
parser.add_option('-l', '--landscape', default=False, action='store_true',
|
||||
help=_("Don't split landscape images into two portrait images"))
|
||||
parser.add_option('--no-sort', default=False, action='store_true',
|
||||
help=_("Don't sort the files found in the comic alphabetically by name. Instead use the order they were added to the comic."))
|
||||
parser.add_option('-p', '--profile', default='prs500', dest='profile', type='choice',
|
||||
choices=PROFILES.keys(), help=_('Choose a profile for the device you are generating this LRF for. The default is the SONY PRS-500 with a screen size of 584x754 pixels. Choices are %s')%PROFILES.keys())
|
||||
parser.add_option('--verbose', default=False, action='store_true',
|
||||
help=_('Be verbose, useful for debugging'))
|
||||
parser.add_option('--no-progress-bar', default=False, action='store_true',
|
||||
help=_("Don't show progress bar."))
|
||||
return parser
|
||||
|
||||
def create_lrf(pages, profile, opts, thumbnail=None):
|
||||
width, height = PROFILES[profile]
|
||||
ps = {}
|
||||
ps['topmargin'] = 0
|
||||
ps['evensidemargin'] = 0
|
||||
ps['oddsidemargin'] = 0
|
||||
ps['textwidth'] = width
|
||||
ps['textheight'] = height
|
||||
book = Book(title=opts.title, author=opts.author,
|
||||
bookid=uuid4().hex,
|
||||
publisher='%s %s'%(__appname__, __version__), thumbnail=thumbnail,
|
||||
category='Comic', pagestyledefault=ps,
|
||||
booksetting=BookSetting(screenwidth=width, screenheight=height))
|
||||
for page in pages:
|
||||
imageStream = ImageStream(page)
|
||||
_page = book.create_page()
|
||||
_page.append(ImageBlock(refstream=imageStream,
|
||||
blockwidth=width, blockheight=height, xsize=width,
|
||||
ysize=height, x1=width, y1=height))
|
||||
book.append(_page)
|
||||
|
||||
book.renderLrf(open(opts.output, 'wb'))
|
||||
|
||||
|
||||
|
||||
def main(args=sys.argv, notification=None):
|
||||
parser = option_parser()
|
||||
opts, args = parser.parse_args(args)
|
||||
if len(args) < 2:
|
||||
parser.print_help()
|
||||
print '\nYou must specify a file to convert'
|
||||
return 1
|
||||
|
||||
if not callable(notification):
|
||||
pb = ProgressBar(terminal_controller, _('Rendering comic pages...'),
|
||||
no_progress_bar=opts.no_progress_bar)
|
||||
notification = pb.update
|
||||
|
||||
source = os.path.abspath(args[1])
|
||||
if not opts.title:
|
||||
opts.title = os.path.splitext(os.path.basename(source))
|
||||
if not opts.output:
|
||||
opts.output = os.path.abspath(os.path.splitext(os.path.basename(source))[0]+'.lrf')
|
||||
|
||||
tdir = extract_comic(source)
|
||||
pages = find_pages(tdir, sort_on_mtime=opts.no_sort, verbose=opts.verbose)
|
||||
if not pages:
|
||||
raise ValueError('Could not find any pages in the comic: %s'%source)
|
||||
pages, failures, tdir2 = process_pages(pages, opts, notification)
|
||||
if not pages:
|
||||
raise ValueError('Could not find any valid pages in the comic: %s'%source)
|
||||
if failures:
|
||||
print 'Could not process the following pages (run with --verbose to see why):'
|
||||
for f in failures:
|
||||
print '\t', f
|
||||
thumbnail = os.path.join(tdir2, 'thumbnail.png')
|
||||
if not os.access(thumbnail, os.R_OK):
|
||||
thumbnail = None
|
||||
create_lrf(pages, opts.profile, opts, thumbnail=thumbnail)
|
||||
shutil.rmtree(tdir)
|
||||
shutil.rmtree(tdir2)
|
||||
return 0
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.exit(main())
|
@ -1327,7 +1327,7 @@ class HTMLConverter(object, LoggingInterface):
|
||||
bls, ls = int(self.book.defaultTextStyle.attrs['baselineskip']), \
|
||||
int(self.book.defaultTextStyle.attrs['linespace'])
|
||||
try: # See if line-height is a unitless number
|
||||
val = int(float(tag_css['line-height'].strip()) * (bls+ls))
|
||||
val = int(float(tag_css['line-height'].strip()) * (ls))
|
||||
fp['linespace'] = val
|
||||
except ValueError:
|
||||
val = self.unit_convert(tag_css['line-height'], pts=True, base_length='1pt')
|
||||
@ -1519,7 +1519,8 @@ class HTMLConverter(object, LoggingInterface):
|
||||
css, pcss = self.parse_css(text)
|
||||
ncss.update(css)
|
||||
npcss.update(pcss)
|
||||
elif tag.has_key('type') and tag['type'] == "text/css" \
|
||||
elif tag.has_key('type') \
|
||||
and tag['type'] in ("text/css", "text/x-oeb1-css") \
|
||||
and tag.has_key('href'):
|
||||
path = munge_paths(self.target_prefix, tag['href'])[0]
|
||||
try:
|
||||
|
@ -5,10 +5,11 @@ import os, sys, shutil, glob, logging
|
||||
from tempfile import mkdtemp
|
||||
from subprocess import Popen, PIPE
|
||||
from calibre.ebooks.lrf import option_parser as lrf_option_parser
|
||||
from calibre.ebooks.lit.reader import LitReader
|
||||
from calibre.ebooks import ConversionError
|
||||
from calibre.ebooks.lrf.html.convert_from import process_file as html_process_file
|
||||
from calibre.ebooks.metadata.opf import OPFReader
|
||||
from calibre import isosx, __appname__, setup_cli_handlers, iswindows, islinux
|
||||
from calibre import isosx, __appname__, setup_cli_handlers, islinux
|
||||
|
||||
CLIT = 'clit'
|
||||
if isosx and hasattr(sys, 'frameworks_dir'):
|
||||
@ -17,22 +18,33 @@ if islinux and getattr(sys, 'frozen_path', False):
|
||||
CLIT = os.path.join(getattr(sys, 'frozen_path'), 'clit')
|
||||
|
||||
def option_parser():
|
||||
return lrf_option_parser(
|
||||
parser = lrf_option_parser(
|
||||
_('''Usage: %prog [options] mybook.lit
|
||||
|
||||
|
||||
%prog converts mybook.lit to mybook.lrf''')
|
||||
)
|
||||
parser.add_option('--lit2oeb', default=False, dest='lit2oeb', action='store_true',
|
||||
help='Use the new lit2oeb to convert lit files instead of convertlit.')
|
||||
return parser
|
||||
|
||||
def generate_html2(pathtolit, logger):
|
||||
if not os.access(pathtolit, os.R_OK):
|
||||
raise ConversionError, 'Cannot read from ' + pathtolit
|
||||
tdir = mkdtemp(prefix=__appname__+'_')
|
||||
lr = LitReader(pathtolit)
|
||||
print 'Extracting LIT file to', tdir
|
||||
lr.extract_content(tdir)
|
||||
return tdir
|
||||
|
||||
def generate_html(pathtolit, logger):
|
||||
if not os.access(pathtolit, os.R_OK):
|
||||
raise ConversionError, 'Cannot read from ' + pathtolit
|
||||
tdir = mkdtemp(prefix=__appname__+'_')
|
||||
os.rmdir(tdir)
|
||||
sep = r'\\' if iswindows else os.path.sep
|
||||
cmd = ' '.join([CLIT, '"'+pathtolit+'"', '"%s"'%(tdir+sep,)])
|
||||
logger.debug(cmd)
|
||||
p = Popen(cmd, shell=True, stderr=PIPE, stdout=PIPE)
|
||||
cmd = [CLIT, pathtolit, '%s'%(tdir+os.sep)]
|
||||
logger.debug(repr(cmd))
|
||||
p = Popen(cmd, stderr=PIPE, stdout=PIPE)
|
||||
stdout = p.stdout.read()
|
||||
err = p.stderr.read()
|
||||
logger.info(p.stdout.read())
|
||||
@ -51,7 +63,8 @@ def process_file(path, options, logger=None):
|
||||
logger = logging.getLogger('lit2lrf')
|
||||
setup_cli_handlers(logger, level)
|
||||
lit = os.path.abspath(os.path.expanduser(path))
|
||||
tdir = generate_html(lit, logger)
|
||||
tdir = generate_html2(lit, logger) if getattr(options, 'lit2oeb', False) \
|
||||
else generate_html(lit, logger)
|
||||
try:
|
||||
opf = glob.glob(os.path.join(tdir, '*.opf'))
|
||||
if opf:
|
||||
|
@ -744,10 +744,9 @@ class Text(LRFStream):
|
||||
self.content.append(self.__class__.TextTag(name))
|
||||
|
||||
def empline(self, tag, stream):
|
||||
|
||||
def invalid(op):
|
||||
stream.seek(op)
|
||||
self.simple_container(None, 'EmpLine')
|
||||
#self.simple_container(None, 'EmpLine')
|
||||
|
||||
oldpos = stream.tell()
|
||||
try:
|
||||
@ -770,6 +769,7 @@ class Text(LRFStream):
|
||||
except LRFParseError:
|
||||
stream.seek(oldpos)
|
||||
|
||||
if attrs:
|
||||
self.content.append(self.__class__.TextTag(
|
||||
'EmpLine', attrs=attrs))
|
||||
|
||||
|
@ -65,7 +65,7 @@ class Resource(object):
|
||||
else:
|
||||
pc = url[2]
|
||||
if isinstance(pc, unicode):
|
||||
pc.encode('utf-8')
|
||||
pc = pc.encode('utf-8')
|
||||
pc = unquote(pc).decode('utf-8')
|
||||
self.path = os.path.abspath(os.path.join(basedir, pc.replace('/', os.sep)))
|
||||
self.fragment = unquote(url[-1])
|
||||
|
@ -7,13 +7,13 @@ __copyright__ = '2008, Kovid Goyal <kovid at kovidgoyal.net>'
|
||||
|
||||
import sys, os
|
||||
|
||||
from zipfile import ZipFile, BadZipfile
|
||||
from calibre.utils.zipfile import ZipFile, BadZipfile
|
||||
from cStringIO import StringIO
|
||||
from contextlib import closing
|
||||
|
||||
from calibre.ebooks.BeautifulSoup import BeautifulStoneSoup
|
||||
from calibre.ebooks.metadata.opf import OPF, OPFReader
|
||||
|
||||
from calibre.ebooks.metadata.opf import OPF, OPFReader, OPFCreator
|
||||
from calibre.ebooks.metadata import get_parser, MetaInformation
|
||||
|
||||
class EPubException(Exception):
|
||||
pass
|
||||
@ -71,9 +71,9 @@ class OCFReader(OCF):
|
||||
raise EPubException("missing OPF package file")
|
||||
|
||||
class OCFZipReader(OCFReader):
|
||||
def __init__(self, stream):
|
||||
def __init__(self, stream, mode='r'):
|
||||
try:
|
||||
self.archive = ZipFile(stream, 'r')
|
||||
self.archive = ZipFile(stream, mode)
|
||||
except BadZipfile:
|
||||
raise EPubException("not a ZIP .epub OCF container")
|
||||
self.root = getattr(stream, 'name', os.getcwd())
|
||||
@ -82,6 +82,19 @@ class OCFZipReader(OCFReader):
|
||||
def open(self, name, mode='r'):
|
||||
return StringIO(self.archive.read(name))
|
||||
|
||||
class OCFZipWriter(OCFZipReader):
|
||||
|
||||
def __init__(self, stream):
|
||||
OCFZipReader.__init__(self, stream, mode='a')
|
||||
|
||||
def set_metadata(self, mi):
|
||||
name = self.container[OPF.MIMETYPE]
|
||||
stream = StringIO()
|
||||
opf = OPFCreator(self.root, mi)
|
||||
opf.render(stream)
|
||||
self.archive.delete(name)
|
||||
self.archive.writestr(name, stream.getvalue())
|
||||
|
||||
class OCFDirReader(OCFReader):
|
||||
def __init__(self, path):
|
||||
self.root = path
|
||||
@ -95,13 +108,35 @@ def get_metadata(stream):
|
||||
""" Return metadata as a L{MetaInfo} object """
|
||||
return OCFZipReader(stream).opf
|
||||
|
||||
def main(args=sys.argv):
|
||||
if len(args) != 2 or '--help' in args or '-h' in args:
|
||||
print >>sys.stderr, _('Usage:'), args[0], _('mybook.epub')
|
||||
return 1
|
||||
def set_metadata(stream, mi):
|
||||
OCFZipWriter(stream).set_metadata(mi)
|
||||
|
||||
path = os.path.abspath(os.path.expanduser(args[1]))
|
||||
print unicode(get_metadata(open(path, 'rb')))
|
||||
def option_parser():
|
||||
parser = get_parser('epub')
|
||||
parser.remove_option('--category')
|
||||
parser.add_option('--tags', default=None, help=_('A comma separated list of tags to set'))
|
||||
return parser
|
||||
|
||||
def main(args=sys.argv):
|
||||
parser = option_parser()
|
||||
opts, args = parser.parse_args(args)
|
||||
if len(args) != 2:
|
||||
parser.print_help()
|
||||
return 1
|
||||
stream = open(args[1], 'r+b')
|
||||
mi = MetaInformation(OCFZipReader(stream).opf)
|
||||
if opts.title:
|
||||
mi.title = opts.title
|
||||
if opts.authors:
|
||||
mi.authors = opts.authors.split(',')
|
||||
if opts.tags:
|
||||
mi.tags = opts.tags.split(',')
|
||||
if opts.comment:
|
||||
mi.comments = opts.comment
|
||||
|
||||
set_metadata(stream, mi)
|
||||
|
||||
print unicode(mi)
|
||||
return 0
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
@ -140,7 +140,7 @@ def main(args=sys.argv):
|
||||
return 1
|
||||
|
||||
for book in create_books(opts, args):
|
||||
print unicode(book)
|
||||
print unicode(book).encode('utf-8')
|
||||
|
||||
return 0
|
||||
|
||||
|
@ -14,6 +14,7 @@ from calibre.ebooks.mobi.reader import get_metadata as mobi_metadata
|
||||
from calibre.ebooks.metadata.opf import OPFReader
|
||||
from calibre.ebooks.metadata.rtf import set_metadata as set_rtf_metadata
|
||||
from calibre.ebooks.lrf.meta import set_metadata as set_lrf_metadata
|
||||
from calibre.ebooks.metadata.epub import set_metadata as set_epub_metadata
|
||||
|
||||
from calibre.ebooks.metadata import MetaInformation
|
||||
|
||||
@ -88,6 +89,8 @@ def set_metadata(stream, mi, stream_type='lrf'):
|
||||
if stream_type: stream_type = stream_type.lower()
|
||||
if stream_type == 'lrf':
|
||||
set_lrf_metadata(stream, mi)
|
||||
elif stream_type == 'epub':
|
||||
set_epub_metadata(stream, mi)
|
||||
elif stream_type == 'rtf':
|
||||
set_rtf_metadata(stream, mi)
|
||||
|
||||
|
@ -20,7 +20,7 @@ class NCXSoup(BeautifulStoneSoup):
|
||||
|
||||
class TOC(list):
|
||||
|
||||
def __init__(self, href=None, fragment=None, text=None, parent=None, play_order=1,
|
||||
def __init__(self, href=None, fragment=None, text=None, parent=None, play_order=0,
|
||||
base_path=os.getcwd()):
|
||||
self.href = href
|
||||
self.fragment = fragment
|
||||
@ -30,7 +30,9 @@ class TOC(list):
|
||||
self.play_order = play_order
|
||||
|
||||
def add_item(self, href, fragment, text):
|
||||
self.append(TOC(href=href, fragment=fragment, text=text, parent=self, base_path=self.base_path))
|
||||
play_order = (self[-1].play_order if len(self) else self.play_order) + 1
|
||||
self.append(TOC(href=href, fragment=fragment, text=text, parent=self,
|
||||
base_path=self.base_path, play_order=play_order))
|
||||
return self[-1]
|
||||
|
||||
def top_level_items(self):
|
||||
|
@ -66,6 +66,7 @@ class ConfigDialog(QDialog, Ui_Dialog):
|
||||
single_format = settings.get('save to disk single format', 'lrf')
|
||||
self.single_format.setCurrentIndex(BOOK_EXTENSIONS.index(single_format))
|
||||
self.cover_browse.setValue(settings.get('cover flow queue length', 6))
|
||||
self.confirm_delete.setChecked(settings.get('confirm delete', False))
|
||||
|
||||
def compact(self, toggled):
|
||||
d = Vacuum(self, self.db)
|
||||
@ -95,6 +96,7 @@ class ConfigDialog(QDialog, Ui_Dialog):
|
||||
self.final_columns = [self.columns.item(i).checkState() == Qt.Checked for i in range(self.columns.count())]
|
||||
settings.set('toolbar icon size', self.ICON_SIZES[self.toolbar_button_size.currentIndex()])
|
||||
settings.set('show text in toolbar', bool(self.show_toolbar_text.isChecked()))
|
||||
settings.set('confirm delete', bool(self.confirm_delete.isChecked()))
|
||||
pattern = self.filename_pattern.commit()
|
||||
settings.set('filename pattern', pattern)
|
||||
settings.set('save to disk single format', BOOK_EXTENSIONS[self.single_format.currentIndex()])
|
||||
|
@ -83,7 +83,7 @@
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>595</width>
|
||||
<height>638</height>
|
||||
<height>640</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout" >
|
||||
@ -159,6 +159,13 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="confirm_delete" >
|
||||
<property name="text" >
|
||||
<string>Ask for &confirmation before deleting files</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QGridLayout" name="gridLayout_2" >
|
||||
<item row="0" column="0" >
|
||||
|
@ -126,7 +126,7 @@ class ConversionJob(Job):
|
||||
def formatted_error(self):
|
||||
if self.exception is None:
|
||||
return ''
|
||||
ans = u'<p><b>%s</b>:'%self.exception
|
||||
ans = u'<p><b>%s</b>:'%repr(self.exception)
|
||||
ans += '<h2>Traceback:</h2><pre>%s</pre>'%self.last_traceback
|
||||
return ans
|
||||
|
||||
|
@ -548,6 +548,12 @@ class Main(MainWindow, Ui_MainWindow):
|
||||
rows = view.selectionModel().selectedRows()
|
||||
if not rows or len(rows) == 0:
|
||||
return
|
||||
if Settings().get('confirm delete', False):
|
||||
d = question_dialog(self, _('Confirm delete'),
|
||||
_('Are you sure you want to delete these %d books?')%len(rows))
|
||||
if d.exec_() != QMessageBox.Yes:
|
||||
return
|
||||
|
||||
if self.stack.currentIndex() == 0:
|
||||
view.model().delete_books(rows)
|
||||
else:
|
||||
|
@ -1,46 +0,0 @@
|
||||
TARGET = pictureflow.so
|
||||
OFILES = sippictureflowcmodule.o sippictureflowPictureFlow.o
|
||||
HFILES = sipAPIpictureflow.h
|
||||
|
||||
CC = gcc
|
||||
CXX = g++
|
||||
LINK = g++
|
||||
CPPFLAGS = -DQT_NO_DEBUG -DQT_THREAD_SUPPORT -I. -I/usr/include/python2.5 -I/usr/lib/qt-3.3/mkspecs/default -I/usr/lib/qt-3.3/include
|
||||
CFLAGS = -O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector --param=ssp-buffer-size=4 -m32 -march=i386 -mtune=generic -fasynchronous-unwind-tables -fPIC -Wall -W -D_REENTRANT
|
||||
CXXFLAGS = -O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector --param=ssp-buffer-size=4 -m32 -march=i386 -mtune=generic -fasynchronous-unwind-tables -fPIC -Wall -W -D_REENTRANT
|
||||
LFLAGS = -shared -Wl,--version-script=pictureflow.exp
|
||||
LIBS = -L.. -L/usr/lib/qt-3.3/lib -lpictureflow -lqt-mt -lXext -lX11 -lm -lpthread
|
||||
MOC = /usr/lib/qt-3.3/bin/moc
|
||||
.SUFFIXES: .c .o .cpp .cc .cxx .C
|
||||
|
||||
|
||||
.cpp.o:
|
||||
$(CXX) -c $(CXXFLAGS) $(CPPFLAGS) -o $@ $<
|
||||
|
||||
.cc.o:
|
||||
$(CXX) -c $(CXXFLAGS) $(CPPFLAGS) -o $@ $<
|
||||
|
||||
.cxx.o:
|
||||
$(CXX) -c $(CXXFLAGS) $(CPPFLAGS) -o $@ $<
|
||||
|
||||
.C.o:
|
||||
$(CXX) -c $(CXXFLAGS) $(CPPFLAGS) -o $@ $<
|
||||
|
||||
.c.o:
|
||||
$(CC) -c $(CFLAGS) $(CPPFLAGS) -o $@ $<
|
||||
|
||||
$(TARGET): $(OFILES)
|
||||
@echo '{ global: initpictureflow; local: *; };' > pictureflow.exp
|
||||
$(LINK) $(LFLAGS) -o $(TARGET) $(OFILES) $(LIBS)
|
||||
|
||||
$(OFILES): $(HFILES)
|
||||
|
||||
install: $(TARGET)
|
||||
@test -d $(DESTDIR)/usr/lib/python2.5/site-packages || mkdir -p $(DESTDIR)/usr/lib/python2.5/site-packages
|
||||
cp -f $(TARGET) $(DESTDIR)/usr/lib/python2.5/site-packages/$(TARGET)
|
||||
|
||||
clean:
|
||||
-rm -f $(TARGET)
|
||||
-rm -f sippictureflowcmodule.o
|
||||
-rm -f sippictureflowPictureFlow.o
|
||||
-rm -f pictureflow.exp
|
@ -1,5 +1,4 @@
|
||||
import os, sys, glob, shutil
|
||||
import sipconfig
|
||||
import os, sys, glob
|
||||
if os.environ.get('PYQT4PATH', None):
|
||||
print os.environ['PYQT4PATH']
|
||||
sys.path.insert(0, os.environ['PYQT4PATH'])
|
||||
@ -32,34 +31,22 @@ makefile = pyqtconfig.QtGuiModuleMakefile (
|
||||
qt=1,
|
||||
)
|
||||
|
||||
# Add the library we are wrapping. The name doesn't include any platform
|
||||
# specific prefixes or extensions (e.g. the "lib" prefix on UNIX, or the
|
||||
# ".dll" extension on Windows).
|
||||
if 'linux' in sys.platform:
|
||||
for f in glob.glob('../../.build/libpictureflow.a'):
|
||||
shutil.copyfile(f, os.path.basename(f))
|
||||
makefile.extra_lib_dirs = ['.']
|
||||
else:
|
||||
makefile.extra_lib_dirs = ['..\\..\\.build\\release', '../../.build', '.']
|
||||
makefile.extra_libs = ['pictureflow0' if 'win' in sys.platform and 'darwin' not in sys.platform else "pictureflow"]
|
||||
makefile.extra_cflags = ['-arch i386', '-arch ppc'] if 'darwin' in sys.platform else []
|
||||
makefile.extra_lflags = ['-arch i386', '-arch ppc'] if 'darwin' in sys.platform else []
|
||||
# Setup the platform dependent Makefile parameters
|
||||
d = os.path.dirname
|
||||
if 'darwin' in sys.platform:
|
||||
makefile.extra_cflags += ['-arch i386', '-arch ppc']
|
||||
makefile.extra_lflags += ['-arch i386', '-arch ppc']
|
||||
qtdir = os.path.join(d(d(os.getcwd())), '.build')
|
||||
if 'win32' in sys.platform:
|
||||
qtdir = os.path.join(qtdir, 'release')
|
||||
makefile.extra_lib_dirs += ['C:/Python25/libs']
|
||||
|
||||
# Add the compiled Qt objects
|
||||
qtobjs = map(lambda x:'"'+x+'"', glob.glob(os.path.join(qtdir, '*.o')))
|
||||
makefile.extra_lflags += qtobjs
|
||||
makefile.extra_cxxflags = makefile.extra_cflags
|
||||
|
||||
# Generate the Makefile itself.
|
||||
makefile.generate()
|
||||
|
||||
# Now we create the configuration module. This is done by merging a Python
|
||||
# dictionary (whose values are normally determined dynamically) with a
|
||||
# (static) template.
|
||||
content = {
|
||||
# Publish where the SIP specifications for this module will be
|
||||
# installed.
|
||||
"pictureflow_sip_dir": config.default_sip_dir,
|
||||
}
|
||||
|
||||
# This creates the helloconfig.py module from the helloconfig.py.in
|
||||
# template and the dictionary.
|
||||
sipconfig.create_config_module("pictureflowconfig.py", "../pictureflowconfig.py.in", content)
|
||||
|
||||
|
||||
|
@ -1,22 +0,0 @@
|
||||
from PyQt4 import pyqtconfig
|
||||
|
||||
class Configuration(pyqtconfig.Configuration):
|
||||
|
||||
def __init__(self, sub_cfg=None):
|
||||
"""Initialise an instance of the class.
|
||||
|
||||
sub_cfg is the list of sub-class configurations. It should be None
|
||||
when called normally.
|
||||
"""
|
||||
# This is all standard code to be copied verbatim except for the
|
||||
# name of the module containing the super-class.
|
||||
if sub_cfg:
|
||||
cfg = sub_cfg
|
||||
else:
|
||||
cfg = []
|
||||
|
||||
cfg.append(_pkg_config)
|
||||
|
||||
pyqtconfig.Configuration.__init__(self, cfg)
|
||||
|
||||
|
@ -2,5 +2,5 @@ TARGET = pictureflow
|
||||
TEMPLATE = lib
|
||||
HEADERS = pictureflow.h
|
||||
SOURCES = pictureflow.cpp
|
||||
VERSION = 0.2.0
|
||||
VERSION = 1.0.0
|
||||
CONFIG += x86 ppc
|
||||
|
@ -778,7 +778,7 @@ ALTER TABLE books ADD COLUMN isbn TEXT DEFAULT "" COLLATE NOCASE;
|
||||
isbn
|
||||
FROM books;
|
||||
''')
|
||||
conn.execute('pragma user_version=5')
|
||||
conn.execute('pragma user_version=12')
|
||||
conn.commit()
|
||||
|
||||
def __init__(self, dbpath, row_factory=False):
|
||||
|
@ -3,8 +3,6 @@ __license__ = 'GPL v3'
|
||||
__copyright__ = '2008, Kovid Goyal kovid@kovidgoyal.net'
|
||||
__docformat__ = 'restructuredtext en'
|
||||
|
||||
import os
|
||||
from cStringIO import StringIO
|
||||
from calibre.utils import zipfile
|
||||
|
||||
def update(pathtozip, patterns, filepaths, names, compression=zipfile.ZIP_DEFLATED, verbose=True):
|
||||
@ -42,34 +40,4 @@ def extract(filename, dir):
|
||||
Extract archive C{filename} into directory C{dir}
|
||||
"""
|
||||
zf = zipfile.ZipFile( filename )
|
||||
namelist = zf.namelist()
|
||||
dirlist = filter( lambda x: x.endswith( '/' ), namelist )
|
||||
filelist = filter( lambda x: not x.endswith( '/' ), namelist )
|
||||
# make base
|
||||
pushd = os.getcwd()
|
||||
if not os.path.isdir( dir ):
|
||||
os.mkdir( dir )
|
||||
os.chdir( dir )
|
||||
# create directory structure
|
||||
dirlist.sort()
|
||||
for dirs in dirlist:
|
||||
dirs = dirs.split( '/' )
|
||||
prefix = ''
|
||||
for dir in dirs:
|
||||
dirname = os.path.join( prefix, dir )
|
||||
if dir and not os.path.isdir( dirname ):
|
||||
os.mkdir( dirname )
|
||||
prefix = dirname
|
||||
# extract files
|
||||
for fn in filelist:
|
||||
if os.path.dirname(fn) and not os.path.exists(os.path.dirname(fn)):
|
||||
os.makedirs(os.path.dirname(fn))
|
||||
out = open( fn, 'wb' )
|
||||
buffer = StringIO( zf.read( fn ))
|
||||
buflen = 2 ** 20
|
||||
datum = buffer.read( buflen )
|
||||
while datum:
|
||||
out.write( datum )
|
||||
datum = buffer.read( buflen )
|
||||
out.close()
|
||||
os.chdir( pushd )
|
||||
zf.extractall(dir)
|
@ -47,6 +47,7 @@ entry_points = {
|
||||
'mobi2oeb = calibre.ebooks.mobi.reader:main',
|
||||
'lrf2html = calibre.ebooks.lrf.html.convert_to:main',
|
||||
'lit2oeb = calibre.ebooks.lit.reader:main',
|
||||
'comic2lrf = calibre.ebooks.lrf.comic.convert_from:main',
|
||||
'calibre-debug = calibre.debug:main',
|
||||
'calibredb = calibre.library.cli:main',
|
||||
'calibre-fontconfig = calibre.utils.fontconfig:main',
|
||||
@ -165,6 +166,8 @@ def setup_completion(fatal_errors):
|
||||
from calibre.web.feeds.main import option_parser as feeds2disk
|
||||
from calibre.web.feeds.recipes import titles as feed_titles
|
||||
from calibre.ebooks.lrf.feeds.convert_from import option_parser as feeds2lrf
|
||||
from calibre.ebooks.metadata.epub import option_parser as epub_meta
|
||||
from calibre.ebooks.lrf.comic.convert_from import option_parser as comicop
|
||||
|
||||
f = open_file('/etc/bash_completion.d/libprs500')
|
||||
f.close()
|
||||
@ -192,11 +195,12 @@ def setup_completion(fatal_errors):
|
||||
f.write(opts_and_exts('pdf-meta', metaop, ['pdf']))
|
||||
f.write(opts_and_exts('lit-meta', metaop, ['lit']))
|
||||
f.write(opts_and_exts('opf-meta', metaop, ['opf']))
|
||||
f.write(opts_and_exts('epub-meta', metaop, ['epub']))
|
||||
f.write(opts_and_exts('epub-meta', epub_meta, ['epub']))
|
||||
f.write(opts_and_exts('lrfviewer', lrfviewerop, ['lrf']))
|
||||
f.write(opts_and_exts('pdfrelow', pdfhtmlop, ['pdf']))
|
||||
f.write(opts_and_exts('mobi2oeb', mobioeb, ['mobi', 'prc']))
|
||||
f.write(opts_and_exts('lit2oeb', lit2oeb, ['lit']))
|
||||
f.write(opts_and_exts('comic2lrf', comicop, ['cbz', 'cbr']))
|
||||
f.write(opts_and_words('feeds2disk', feeds2disk, feed_titles))
|
||||
f.write(opts_and_words('feeds2lrf', feeds2lrf, feed_titles))
|
||||
f.write('''
|
||||
|
@ -251,8 +251,14 @@ def download_tarball():
|
||||
except ValueError:
|
||||
print 'Downloading calibre...'
|
||||
pb = None
|
||||
src = urllib2.urlopen(MOBILEREAD+'calibre-%version-i686.tar.bz2')
|
||||
local = 'calibre-test.tar.bz2'
|
||||
src = open(local) if os.access(local, os.R_OK) else urllib2.urlopen(MOBILEREAD+'calibre-%version-i686.tar.bz2')
|
||||
if hasattr(src, 'info'):
|
||||
size = int(src.info()['content-length'])
|
||||
else:
|
||||
src.seek(0, 2)
|
||||
size = src.tell()
|
||||
src.seek(0)
|
||||
f = tempfile.NamedTemporaryFile()
|
||||
while f.tell() < size:
|
||||
f.write(src.read(4*1024))
|
||||
|
@ -131,13 +131,19 @@ Why does |app| show only some of my fonts on OS X?
|
||||
|
||||
The graphical user interface of |app| is not starting on Windows?
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
If you've never used the graphical user interface before, try deleting the file library1.db (it will be somewhere under :file:`C:\\Documents and Settings` on Windows XP and :file:`C:\\Users` on Windows Vista. If that doesn't fix the problem, locate the file calibre.log (in the same places as library1.db) and post its contents in a help message on the `Forums <http://calibre.kovidgoyal.net/discussion>`_. If you can't find either file, try using the windows find feature to search for them. If the files dont exist on your system, try the following:
|
||||
There can be several causes for this:
|
||||
|
||||
Start a command prompt (press the windows key and R and type cmd.exe in the run dialog). At the command prompt type the following command and press Enter::
|
||||
* **Any windows version**: Try running it as Administrator (Right click on the icon ans select "Run as Administrator")
|
||||
* **Any windows version**: Search for the files `calibre2.ini` and `calibre.ini` on your computer and delete them. Search for the file `library1.db` and rename it (this file contains all your converted books so deleting it is not a good idea. Now try again.
|
||||
* **Windows Vista**: If the folder :file:`C:\Users\Your User Name\AppData\Local\VirtualStore\Program Files\calibre` exists, delete it. Uninstall |app|. Reboot. Re-install.
|
||||
* **Any windows version**: Search your computer for a folder named :file:`_ipython`. Delete it and try again.
|
||||
|
||||
If it still wont launch, start a command prompt (press the windows key and R; then type :command:`cmd.exe` in the Run dialog that appears). At the command prompt type the following command and press Enter::
|
||||
|
||||
calibre-debug -c "from calibre.gui2.main import main; main()"
|
||||
|
||||
Post any output you see when asking for help.
|
||||
Post any output you see in a help message on the `Forums <http://calibre.kovidgoyal.net/discussion`_.
|
||||
|
||||
|
||||
I want some feature added to |app|. What can I do?
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
@ -14,7 +14,8 @@
|
||||
|
||||
<div id="content" class="download">
|
||||
<h1><img src="${href.chrome('/dl/images/%s_logo.png'%(distro.img,))}" valign="middle" width="60" height="80"/> $title</h1>
|
||||
See the <a href="/wiki/Changelog">Changelog</a> for the changes in the latest version.
|
||||
See the <a href="/wiki/Changelog">Changelog</a> for the changes in the latest version. <b>Note:</b> As of 0.4.80 this install
|
||||
will not work on 64-bit CPUs. Try the precompiled binary available <a href="/download_binary">here</a> instead.
|
||||
<div py:if="not distro.is_generic">
|
||||
First verify that you have a sufficiently new installation of python
|
||||
<pre class="wiki">python --version</pre> should return at least 2.5.1<br />
|
||||
|
@ -14,7 +14,7 @@
|
||||
|
||||
<div id="content" class="binary">
|
||||
<h1>Download $app for Linux</h1>
|
||||
<p>This binary package is compatible with most recent linux distributions running on Intel 32 bit CPUs.</p>
|
||||
<p>This binary package is compatible with most recent linux distributions running on Intel 32 bit CPUs. It needs testing on 64 bit CPUs. </p>
|
||||
<p>
|
||||
<img width="50" height="50" style="border:1px red solid" src="${href.chrome('/dl/images/binary_logo.png')}" />
|
||||
(Version: $version <a href="/wiki/Changelog">Changelog</a>)
|
||||
|
@ -70,8 +70,22 @@ def import_from_launchpad(url):
|
||||
open(out, 'wb').write(tf.extractfile(next).read())
|
||||
next = tf.next()
|
||||
|
||||
check_for_critical_bugs()
|
||||
return 0
|
||||
|
||||
def check_for_critical_bugs():
|
||||
if os.path.exists('.errors'):
|
||||
shutil.rmtree('.errors')
|
||||
pofilter = ('pofilter', '-i', '.', '-o', '.errors',
|
||||
'-t', 'accelerators', '-t', 'escapes', '-t', 'variables',
|
||||
'-t', 'xmltags')
|
||||
subprocess.check_call(pofilter)
|
||||
errs = os.listdir('.errors')
|
||||
if errs:
|
||||
print 'WARNING: Translation errors detected'
|
||||
print 'See the .errors directory and http://translate.sourceforge.net/wiki/toolkit/using_pofilter'
|
||||
|
||||
|
||||
def main(args=sys.argv):
|
||||
if len(args) > 1:
|
||||
if args[1] == 'pot':
|
||||
|
@ -426,6 +426,7 @@ msgstr ""
|
||||
"Expressión regular utilizada para detectar los títulos de los capítulos. "
|
||||
"Busca las marcas de encabezado (h1-h6). Por defecto: %default"
|
||||
|
||||
# (pofilter) escapes: escapes in original ('"h\d,class,chapter".') don't match escapes in translation ()
|
||||
#: /home/kovid/work/calibre/src/calibre/ebooks/lrf/__init__.py:165
|
||||
msgid ""
|
||||
"Detect a chapter beginning at an element having the specified attribute. The "
|
||||
@ -437,7 +438,7 @@ msgstr ""
|
||||
"especificado. El formato para ésta espresión es tagname regexp, nombre del "
|
||||
"atributo, valor del atributo regexp. Por ejemplo, para encontrar todas las "
|
||||
"etiquetas de cabecera que tienen como attribute class=\"capítulo\" podría "
|
||||
"usar: \"h/d,class,capítulo\". El valor por defecto es: %default"
|
||||
"usar: \"h\\d,class,capítulo\". El valor por defecto es: %default"
|
||||
|
||||
#: /home/kovid/work/calibre/src/calibre/ebooks/lrf/__init__.py:167
|
||||
msgid ""
|
||||
@ -2111,6 +2112,7 @@ msgstr "&Compartir receta"
|
||||
msgid "&Load recipe from file"
|
||||
msgstr "&Cargar receta desde un archivo"
|
||||
|
||||
# (pofilter) xmltags: checks that XML/HTML tags have not been translated
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/user_profiles_ui.py:215
|
||||
msgid ""
|
||||
"<html><head><meta name=\"qrichtext\" content=\"1\" /><style "
|
||||
@ -2124,16 +2126,15 @@ msgid ""
|
||||
"use the \"Advanced mode\" to further customize the fetch "
|
||||
"process.</p></body></html>"
|
||||
msgstr ""
|
||||
"<html><head><meta name=\"qrichtext\" content=\"1\" /><style "
|
||||
"type=\"text/css\">\n"
|
||||
"<html><head><meta name=\"qrichtext\" content=\"1\" /><style type=\"text/css\">\n"
|
||||
"p, li { white-space: pre-wrap; }\n"
|
||||
"</style></head><body style=\" font-family:'DejaVu Sans'; font-size:10pt; "
|
||||
"font-weight:400; font-style:normal;\">\n"
|
||||
"<p style=\" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-"
|
||||
"right:0px; -qt-block-indent:0; text-indent:0px;\">Crear una receta de "
|
||||
"noticias básica, añadiendo un RSS Feed. Para la mayoría de los feeds, "
|
||||
"necesitará utilizar el \"modo avanzado\" para una configuración mas "
|
||||
"detallada del proceso de adquisición de los datos</p></body></html>"
|
||||
"noticias básica, añadiendo un RSS Feed. <br /> Para la mayoría de los feeds, "
|
||||
"necesitará utilizar el \"modo avanzado\" para una configuración mas detallada "
|
||||
"del proceso de adquisición de los datos</p></body></html>"
|
||||
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/user_profiles_ui.py:219
|
||||
msgid "Recipe &title:"
|
||||
@ -2253,9 +2254,10 @@ msgstr "Ninguna coincidencia"
|
||||
msgid "Authors:"
|
||||
msgstr "Autores:"
|
||||
|
||||
# (pofilter) xmltags: checks that XML/HTML tags have not been translated
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/filename_pattern_ui.py:106
|
||||
msgid "Regular expression group name (?P<authors>)"
|
||||
msgstr "Nombre de grupo de expresión regular (?P<authos>)"
|
||||
msgstr "Nombre de grupo de expresión regular (?P<authors>)"
|
||||
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/filename_pattern_ui.py:108
|
||||
msgid "Series:"
|
||||
@ -2348,9 +2350,10 @@ msgstr "Formatos"
|
||||
msgid "Book <font face=\"serif\">%s</font> of %s."
|
||||
msgstr "Libro <font face=\"serif\">%s</font> de %s."
|
||||
|
||||
# (pofilter) xmltags: checks that XML/HTML tags have not been translated
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/library.py:396
|
||||
msgid "Double click to <b>edit</b> me<br><br>"
|
||||
msgstr "Doble click para <b>editarme</b>"
|
||||
msgstr "Doble click para <b>editarme</b><br><br>"
|
||||
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/library.py:406
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/library.py:757
|
||||
@ -2898,14 +2901,15 @@ msgstr "ERROR: Excepción no Contemplada"
|
||||
msgid "Add a custom news source"
|
||||
msgstr "Añadir nueva fuente de noticias"
|
||||
|
||||
# (pofilter) xmltags: checks that XML/HTML tags have not been translated
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/news.py:53
|
||||
msgid ""
|
||||
"<p>Please enter your username and password for %s<br>If you do not have one, "
|
||||
"please subscribe to get access to the articles.<br/> Click OK to proceed."
|
||||
msgstr ""
|
||||
"<p>Por favor, introduzca el nombre de usuario y contraseña para %s<br/> Si "
|
||||
"no tiene uno, por favor dese de alta para obtener acceso a los "
|
||||
"artículos.<br/> Haga click en OK para continuar."
|
||||
"<p>Por favor, introduzca el nombre de usuario y contraseña para %s<br> Si no "
|
||||
"tiene uno, por favor dese de alta para obtener acceso a los artículos.<br/> "
|
||||
"Haga click en OK para continuar."
|
||||
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/news.py:79
|
||||
msgid "Custom news sources"
|
||||
|
@ -1481,6 +1481,7 @@ msgstr "Cambia l'editore di questo libro"
|
||||
msgid "Ta&gs: "
|
||||
msgstr "T&ag: "
|
||||
|
||||
# (pofilter) xmltags: checks that XML/HTML tags have not been translated
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/lrf_single_ui.py:524
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_bulk_ui.py:127
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:271
|
||||
@ -1489,7 +1490,7 @@ msgid ""
|
||||
"<br><br>They can be any words or phrases, separated by commas."
|
||||
msgstr ""
|
||||
"I tag categorizzano un libro. Questo è particolarmente utile durante le "
|
||||
"ricerche. <br>Possono essere qualsiasi parola o frase, separati da una "
|
||||
"ricerche. <br><br>Possono essere qualsiasi parola o frase, separati da una "
|
||||
"virgola"
|
||||
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/lrf_single_ui.py:525
|
||||
@ -2143,6 +2144,7 @@ msgstr ""
|
||||
msgid "Recipe source code (python)"
|
||||
msgstr "Codice sorgente formula (python)"
|
||||
|
||||
# (pofilter) xmltags: checks that XML/HTML tags have not been translated
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/filename_pattern_ui.py:97
|
||||
msgid ""
|
||||
"<p>Set a regular expression pattern to use when trying to guess ebook "
|
||||
@ -2154,7 +2156,7 @@ msgstr ""
|
||||
"<p>Impostare un modello di espressione regolare da usare nel tentativo di "
|
||||
"indovinare i metadati dei libri dal nome del file. <p>È disponibile un <a "
|
||||
"href=\"http://docs.python.org/lib/re-syntax.html\">riferimento</a> sulla "
|
||||
"sintassi delle espressioni regolari. Usare la funzionalità <b>Test</b> "
|
||||
"sintassi delle espressioni regolari.<p> Usare la funzionalità <b>Test</b> "
|
||||
"sottostante per testare le proprie espressioni regolari su una serie di nomi "
|
||||
"di file di esempio."
|
||||
|
||||
@ -2294,9 +2296,10 @@ msgstr "Formati"
|
||||
msgid "Book <font face=\"serif\">%s</font> of %s."
|
||||
msgstr "Libro <font face=\"serif\">%s</font> di %s"
|
||||
|
||||
# (pofilter) xmltags: checks that XML/HTML tags have not been translated
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/library.py:396
|
||||
msgid "Double click to <b>edit</b> me<br><br>"
|
||||
msgstr "Doppio clic per modificarmi"
|
||||
msgstr "Doppio clic per <b>modificarmi</b><br><br>"
|
||||
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/library.py:406
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/library.py:757
|
||||
|
@ -332,6 +332,7 @@ msgstr ""
|
||||
"De reguliere expressie die wordt gebruikt om hoofdstukken te herkennen. Deze "
|
||||
"wordt gezocht in 'heading tags' (h1-h6). Standaard: %default"
|
||||
|
||||
# (pofilter) escapes: escapes in original ('"h\d,class,chapter".') don't match escapes in translation ('"h\d\klasse,hoofdstuk".')
|
||||
#: /home/kovid/work/calibre/src/calibre/ebooks/lrf/__init__.py:165
|
||||
msgid ""
|
||||
"Detect a chapter beginning at an element having the specified attribute. The "
|
||||
@ -342,8 +343,8 @@ msgstr ""
|
||||
"vind het begin van een hoofdstuk bij een element met het gespecificeerde "
|
||||
"attribuut. Het formaat voor deze optie is tagnaam regexp, attribuut naam, "
|
||||
"attribuut waarde regexp. Bijvoorbeeld, om alle kop tags te vinden met de "
|
||||
"attribuut klasse \"hoofstuk\", gebruik \"h\\d\\klasse,hoofdstuk\". Standaard "
|
||||
"is %default"
|
||||
"attribuut klasse \"hoofstuk\", gebruik \"h\\d,klasse,hoofdstuk\". Standaard is "
|
||||
"%default"
|
||||
|
||||
#: /home/kovid/work/calibre/src/calibre/ebooks/lrf/__init__.py:167
|
||||
msgid ""
|
||||
@ -1307,10 +1308,11 @@ msgstr "Je hebt geen permissie om het bestand te lezen: "
|
||||
msgid "Error reading file"
|
||||
msgstr "Fout bij het lezen van bestand"
|
||||
|
||||
# (pofilter) xmltags: checks that XML/HTML tags have not been translated
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/lrf_single.py:183
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single.py:53
|
||||
msgid "<p>There was an error reading from file: <br /><b>"
|
||||
msgstr "<p>Er is een fout opgetreden bij het lezen van bestand: <br></b>"
|
||||
msgstr "<p>Er is een fout opgetreden bij het lezen van bestand: <br /><b>"
|
||||
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/lrf_single.py:189
|
||||
msgid " is not a valid picture"
|
||||
@ -1733,6 +1735,7 @@ msgid "Comma separated list of tags to remove from the books. "
|
||||
msgstr ""
|
||||
"Lijst van tags die moeten worden verwijderd, gescheiden met komma's. "
|
||||
|
||||
# (pofilter) xmltags: checks that XML/HTML tags have not been translated
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single.py:235
|
||||
msgid ""
|
||||
"<p>Enter your username and password for <b>LibraryThing.com</b>. <br/>If you "
|
||||
@ -1740,8 +1743,8 @@ msgid ""
|
||||
"for free!.</p>"
|
||||
msgstr ""
|
||||
"<p>Geef uw gebruikersnaam en wachtwoord voor <b>LibraryThing.com</b>. "
|
||||
"<br>Als u deze niet heeft, dan kunt u er gratis een krijgen door te <a "
|
||||
"href='http://www.librarything.com'>registreren</a>"
|
||||
"<br/>Als u deze niet heeft, dan kunt u er gratis een krijgen door te <a "
|
||||
"href='http://www.librarything.com'>registreren</a>.</p>"
|
||||
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single.py:265
|
||||
msgid "<b>Could not fetch cover.</b><br/>"
|
||||
@ -2181,26 +2184,29 @@ msgstr "Geen overeenkomst"
|
||||
msgid "Authors:"
|
||||
msgstr "Auteurs:"
|
||||
|
||||
# (pofilter) xmltags: checks that XML/HTML tags have not been translated
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/filename_pattern_ui.py:106
|
||||
msgid "Regular expression group name (?P<authors>)"
|
||||
msgstr "Reguliere expressie groep naam (?<auteurs>)"
|
||||
msgstr "Reguliere expressie groep naam (?P<authors>)"
|
||||
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/filename_pattern_ui.py:108
|
||||
msgid "Series:"
|
||||
msgstr "Serie:"
|
||||
|
||||
# (pofilter) xmltags: checks that XML/HTML tags have not been translated
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/filename_pattern_ui.py:109
|
||||
msgid "Regular expression group name (?P<series>)"
|
||||
msgstr "Reguliere expressie groep naam (?<serie>)"
|
||||
msgstr "Reguliere expressie groep naam (?P<series>)"
|
||||
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/filename_pattern_ui.py:111
|
||||
msgid "Series index:"
|
||||
msgstr "Serie Index"
|
||||
|
||||
# (pofilter) xmltags: checks that XML/HTML tags have not been translated
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/filename_pattern_ui.py:112
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/filename_pattern_ui.py:115
|
||||
msgid "Regular expression group name (?P<series_index>)"
|
||||
msgstr "Reguliere expressie groep naam (?<serie_index>)"
|
||||
msgstr "Reguliere expressie groep naam (?P<series_index>)"
|
||||
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/filename_pattern_ui.py:114
|
||||
msgid "ISBN:"
|
||||
@ -2825,13 +2831,14 @@ msgstr "FOUT: Niet-verwerkte uitzondering"
|
||||
msgid "Add a custom news source"
|
||||
msgstr "Voeg een persoonlijke nieuwsbron toe"
|
||||
|
||||
# (pofilter) xmltags: checks that XML/HTML tags have not been translated
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/news.py:53
|
||||
msgid ""
|
||||
"<p>Please enter your username and password for %s<br>If you do not have one, "
|
||||
"please subscribe to get access to the articles.<br/> Click OK to proceed."
|
||||
msgstr ""
|
||||
"<p>Voer uw gebruikersnaam en wachtwoord voor %s in.<br>Als u er geen geeft, "
|
||||
"registreer dan om toegang tot de artikelen te krijgen.<br>Klik op OK om "
|
||||
"registreer dan om toegang tot de artikelen te krijgen.<br/>Klik op OK om "
|
||||
"verder te gaan."
|
||||
|
||||
#: /home/kovid/work/calibre/src/calibre/gui2/news.py:79
|
||||
@ -3447,13 +3454,14 @@ msgstr ""
|
||||
"Maximum aantal level om recursief te zoeken -- de diepte om links te volgen. "
|
||||
"Standaard %default"
|
||||
|
||||
# (pofilter) xmltags: checks that XML/HTML tags have not been translated
|
||||
#: /home/kovid/work/calibre/src/calibre/web/fetch/simple.py:394
|
||||
msgid ""
|
||||
"The maximum number of files to download. This only applies to files from <a "
|
||||
"href> tags. Default is %default"
|
||||
msgstr ""
|
||||
"Het maximum aantal bestanden te downloaden. Dit is alleen van toepassing op "
|
||||
"bestanden in <A HREF> tags. Standaard is %default"
|
||||
"bestanden in <a href> tags. Standaard is %default"
|
||||
|
||||
#: /home/kovid/work/calibre/src/calibre/web/fetch/simple.py:396
|
||||
msgid ""
|
||||
|
File diff suppressed because it is too large
Load Diff
4360
src/calibre/utils/PythonMagickWand.py
Normal file
4360
src/calibre/utils/PythonMagickWand.py
Normal file
File diff suppressed because it is too large
Load Diff
@ -34,12 +34,24 @@ except:
|
||||
|
||||
iswindows = 'win32' in sys.platform or 'win64' in sys.platform
|
||||
isosx = 'darwin' in sys.platform
|
||||
DISABLED = False
|
||||
#if isosx:
|
||||
# libc = ctypes.cdll.LoadLibrary(ctypes.util.find_library('c'))
|
||||
# size = ctypes.c_uint(0)
|
||||
# ok = libc.sysctlbyname("hw.cpu64bit_capable", None, byref(size), None, 0)
|
||||
# if ok != 0:
|
||||
# is64bit = False
|
||||
# else:
|
||||
# buf = ctypes.c_char_p("\0" * size.value)
|
||||
# ok = libc.sysctlbyname("hw.cpu64bit_capable", buf, byref(size), None, 0)
|
||||
# if ok != 0:
|
||||
# is64bit = False
|
||||
# else:
|
||||
# is64bit = '1' in buf.value
|
||||
# DISABLED = is64bit
|
||||
|
||||
def load_library():
|
||||
if isosx:
|
||||
if os.path.exists('/usr/X11/lib/libfontconfig.1.dylib'): # The fontconfig shipped with calibre doesn't work on Leopard
|
||||
lib = '/usr/X11/lib/libfontconfig.1.dylib'
|
||||
else:
|
||||
lib = os.path.join(getattr(sys, 'frameworks_dir'), 'libfontconfig.1.dylib') \
|
||||
if hasattr(sys, 'frameworks_dir') else util.find_library('fontconfig')
|
||||
return cdll.LoadLibrary(lib)
|
||||
@ -159,9 +171,9 @@ class FontScanner(Thread):
|
||||
global _initialized
|
||||
_initialized = True
|
||||
|
||||
|
||||
_scanner = FontScanner()
|
||||
_scanner.start()
|
||||
if not DISABLED:
|
||||
_scanner = FontScanner()
|
||||
_scanner.start()
|
||||
|
||||
def join():
|
||||
_scanner.join(120)
|
||||
@ -177,6 +189,8 @@ def find_font_families(allowed_extensions=['ttf', 'otf']):
|
||||
`allowed_extensions`: A list of allowed extensions for font file types. Defaults to
|
||||
`['ttf', 'otf']`. If it is empty, it is ignored.
|
||||
'''
|
||||
if DISABLED:
|
||||
return []
|
||||
join()
|
||||
allowed_extensions = [i.lower() for i in allowed_extensions]
|
||||
|
||||
@ -219,6 +233,8 @@ def files_for_family(family, normalize=True):
|
||||
they are a tuple (slant, weight) otherwise they are strings from the set
|
||||
`('normal', 'bold', 'italic', 'bi', 'light', 'li')`
|
||||
'''
|
||||
if DISABLED:
|
||||
return {}
|
||||
join()
|
||||
if isinstance(family, unicode):
|
||||
family = family.encode(preferred_encoding)
|
||||
@ -295,6 +311,8 @@ def match(name, sort=False, verbose=False):
|
||||
decreasing closeness of matching.
|
||||
`verbose`: If `True` print debugging information to stdout
|
||||
'''
|
||||
if DISABLED:
|
||||
return []
|
||||
join()
|
||||
if isinstance(name, unicode):
|
||||
name = name.encode(preferred_encoding)
|
||||
|
@ -1,5 +0,0 @@
|
||||
from distutils.core import setup, Extension
|
||||
|
||||
setup(name="lzx", version="1.0",
|
||||
ext_modules=[Extension('lzx', sources=['lzx/lzxmodule.c', 'lzx/lzxd.c'],
|
||||
include_dirs=['lzx'])])
|
@ -1,15 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
__license__ = 'GPL v3'
|
||||
__copyright__ = '2008, Kovid Goyal kovid@kovidgoyal.net'
|
||||
__docformat__ = 'restructuredtext en'
|
||||
|
||||
'''
|
||||
Build the lzx decompressor extension
|
||||
'''
|
||||
from distutils.core import setup, Extension
|
||||
|
||||
setup(name="lzx", version="1.0",
|
||||
ext_modules=[Extension('lzx',
|
||||
sources=['lzxmodule.c', 'lzxd.c'],
|
||||
include_dirs=['.'])])
|
||||
|
156
src/calibre/utils/msdes/d3des.h
Normal file
156
src/calibre/utils/msdes/d3des.h
Normal file
@ -0,0 +1,156 @@
|
||||
/* d3des.h -
|
||||
*
|
||||
* Headers and defines for d3des.c
|
||||
* Graven Imagery, 1992.
|
||||
*
|
||||
* THIS SOFTWARE PLACED IN THE PUBLIC DOMAIN BY THE AUTHOUR
|
||||
* 920825 19:42 EDST
|
||||
*
|
||||
* Copyright (c) 1988,1989,1990,1991,1992 by Richard Outerbridge
|
||||
* (GEnie : OUTER; CIS : [71755,204])
|
||||
*/
|
||||
|
||||
#undef D2_DES
|
||||
#undef D3_DES
|
||||
|
||||
#ifdef D3_DES
|
||||
#ifndef D2_DES
|
||||
#define D2_DES /* D2_DES is needed for D3_DES */
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define EN0 0 /* MODE == encrypt */
|
||||
#define DE1 1 /* MODE == decrypt */
|
||||
|
||||
/* Useful on 68000-ish machines, but NOT USED here. */
|
||||
|
||||
typedef union {
|
||||
unsigned long blok[2];
|
||||
unsigned short word[4];
|
||||
unsigned char byte[8];
|
||||
} M68K;
|
||||
|
||||
typedef union {
|
||||
unsigned long dblok[4];
|
||||
unsigned short dword[8];
|
||||
unsigned char dbyte[16];
|
||||
} M68K2;
|
||||
|
||||
extern void deskey(unsigned char *, short);
|
||||
/* hexkey[8] MODE
|
||||
* Sets the internal key register according to the hexadecimal
|
||||
* key contained in the 8 bytes of hexkey, according to the DES,
|
||||
* for encryption or decryption according to MODE.
|
||||
*/
|
||||
|
||||
extern void usekey(unsigned long *);
|
||||
/* cookedkey[32]
|
||||
* Loads the internal key register with the data in cookedkey.
|
||||
*/
|
||||
|
||||
extern void cpkey(unsigned long *);
|
||||
/* cookedkey[32]
|
||||
* Copies the contents of the internal key register into the storage
|
||||
* located at &cookedkey[0].
|
||||
*/
|
||||
|
||||
extern void des(unsigned char *, unsigned char *);
|
||||
/* from[8] to[8]
|
||||
* Encrypts/Decrypts (according to the key currently loaded in the
|
||||
* internal key register) one block of eight bytes at address 'from'
|
||||
* into the block at address 'to'. They can be the same.
|
||||
*/
|
||||
|
||||
#ifdef D2_DES
|
||||
|
||||
#define desDkey(a,b) des2key((a),(b))
|
||||
extern void des2key(unsigned char *, short);
|
||||
/* hexkey[16] MODE
|
||||
* Sets the internal key registerS according to the hexadecimal
|
||||
* keyS contained in the 16 bytes of hexkey, according to the DES,
|
||||
* for DOUBLE encryption or decryption according to MODE.
|
||||
* NOTE: this clobbers all three key registers!
|
||||
*/
|
||||
|
||||
extern void Ddes(unsigned char *, unsigned char *);
|
||||
/* from[8] to[8]
|
||||
* Encrypts/Decrypts (according to the keyS currently loaded in the
|
||||
* internal key registerS) one block of eight bytes at address 'from'
|
||||
* into the block at address 'to'. They can be the same.
|
||||
*/
|
||||
|
||||
extern void D2des(unsigned char *, unsigned char *);
|
||||
/* from[16] to[16]
|
||||
* Encrypts/Decrypts (according to the keyS currently loaded in the
|
||||
* internal key registerS) one block of SIXTEEN bytes at address 'from'
|
||||
* into the block at address 'to'. They can be the same.
|
||||
*/
|
||||
|
||||
extern void makekey(char *, unsigned char *);
|
||||
/* *password, single-length key[8]
|
||||
* With a double-length default key, this routine hashes a NULL-terminated
|
||||
* string into an eight-byte random-looking key, suitable for use with the
|
||||
* deskey() routine.
|
||||
*/
|
||||
|
||||
#define makeDkey(a,b) make2key((a),(b))
|
||||
extern void make2key(char *, unsigned char *);
|
||||
/* *password, double-length key[16]
|
||||
* With a double-length default key, this routine hashes a NULL-terminated
|
||||
* string into a sixteen-byte random-looking key, suitable for use with the
|
||||
* des2key() routine.
|
||||
*/
|
||||
|
||||
#ifndef D3_DES /* D2_DES only */
|
||||
|
||||
#define useDkey(a) use2key((a))
|
||||
#define cpDkey(a) cp2key((a))
|
||||
|
||||
extern void use2key(unsigned long *);
|
||||
/* cookedkey[64]
|
||||
* Loads the internal key registerS with the data in cookedkey.
|
||||
* NOTE: this clobbers all three key registers!
|
||||
*/
|
||||
|
||||
extern voi cp2key(unsigned long *);
|
||||
/* cookedkey[64]
|
||||
* Copies the contents of the internal key registerS into the storage
|
||||
* located at &cookedkey[0].
|
||||
*/
|
||||
|
||||
#else /* D3_DES too */
|
||||
|
||||
#define useDkey(a) use3key((a))
|
||||
#define cpDkey(a) cp3key((a))
|
||||
|
||||
extern void des3key(unsigned char *, short);
|
||||
/* hexkey[24] MODE
|
||||
* Sets the internal key registerS according to the hexadecimal
|
||||
* keyS contained in the 24 bytes of hexkey, according to the DES,
|
||||
* for DOUBLE encryption or decryption according to MODE.
|
||||
*/
|
||||
|
||||
extern void use3key(unsigned long *);
|
||||
/* cookedkey[96]
|
||||
* Loads the 3 internal key registerS with the data in cookedkey.
|
||||
*/
|
||||
|
||||
extern void cp3key(unsigned long *);
|
||||
/* cookedkey[96]
|
||||
* Copies the contents of the 3 internal key registerS into the storage
|
||||
* located at &cookedkey[0].
|
||||
*/
|
||||
|
||||
extern void make3key(char *, unsigned char *);
|
||||
/* *password, triple-length key[24]
|
||||
* With a triple-length default key, this routine hashes a NULL-terminated
|
||||
* string into a twenty-four-byte random-looking key, suitable for use with
|
||||
* the des3key() routine.
|
||||
*/
|
||||
|
||||
#endif /* D3_DES */
|
||||
#endif /* D2_DES */
|
||||
|
||||
/* d3des.h V5.09 rwo 9208.04 15:06 Graven Imagery
|
||||
********************************************************************/
|
||||
|
693
src/calibre/utils/msdes/des.c
Normal file
693
src/calibre/utils/msdes/des.c
Normal file
@ -0,0 +1,693 @@
|
||||
/* D3DES (V5.09) -
|
||||
*
|
||||
* A portable, public domain, version of the Data Encryption Standard.
|
||||
*
|
||||
* Written with Symantec's THINK (Lightspeed) C by Richard Outerbridge.
|
||||
* Thanks to: Dan Hoey for his excellent Initial and Inverse permutation
|
||||
* code; Jim Gillogly & Phil Karn for the DES key schedule code; Dennis
|
||||
* Ferguson, Eric Young and Dana How for comparing notes; and Ray Lau,
|
||||
* for humouring me on.
|
||||
*
|
||||
* THIS SOFTWARE PLACED IN THE PUBLIC DOMAIN BY THE AUTHOUR
|
||||
* 920825 19:42 EDST
|
||||
*
|
||||
* Copyright (c) 1988,1989,1990,1991,1992 by Richard Outerbridge.
|
||||
* (GEnie : OUTER; CIS : [71755,204]) Graven Imagery, 1992.
|
||||
*/
|
||||
|
||||
#include "d3des.h"
|
||||
|
||||
static void scrunch(unsigned char *, unsigned long *);
|
||||
static void unscrun(unsigned long *, unsigned char *);
|
||||
static void desfunc(unsigned long *, unsigned long *);
|
||||
static void cookey(unsigned long *);
|
||||
|
||||
static unsigned long KnL[32] = { 0L };
|
||||
/*
|
||||
static unsigned long KnR[32] = { 0L };
|
||||
static unsigned long Kn3[32] = { 0L };
|
||||
static unsigned char Df_Key[24] = {
|
||||
0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef,
|
||||
0xfe,0xdc,0xba,0x98,0x76,0x54,0x32,0x10,
|
||||
0x89,0xab,0xcd,0xef,0x01,0x23,0x45,0x67 };
|
||||
*/
|
||||
|
||||
static unsigned short bytebit[8] = {
|
||||
0200, 0100, 040, 020, 010, 04, 02, 01 };
|
||||
|
||||
static unsigned long bigbyte[24] = {
|
||||
0x800000L, 0x400000L, 0x200000L, 0x100000L,
|
||||
0x80000L, 0x40000L, 0x20000L, 0x10000L,
|
||||
0x8000L, 0x4000L, 0x2000L, 0x1000L,
|
||||
0x800L, 0x400L, 0x200L, 0x100L,
|
||||
0x80L, 0x40L, 0x20L, 0x10L,
|
||||
0x8L, 0x4L, 0x2L, 0x1L };
|
||||
|
||||
/* Use the key schedule specified in the Standard (ANSI X3.92-1981). */
|
||||
|
||||
static unsigned char pc1[56] = {
|
||||
56, 48, 40, 32, 24, 16, 8, 0, 57, 49, 41, 33, 25, 17,
|
||||
9, 1, 58, 50, 42, 34, 26, 18, 10, 2, 59, 51, 43, 35,
|
||||
62, 54, 46, 38, 30, 22, 14, 6, 61, 53, 45, 37, 29, 21,
|
||||
13, 5, 60, 52, 44, 36, 28, 20, 12, 4, 27, 19, 11, 3 };
|
||||
|
||||
static unsigned char totrot[16] = {
|
||||
1,2,4,6,8,10,12,14,15,17,19,21,23,25,27,28 };
|
||||
|
||||
static unsigned char pc2[48] = {
|
||||
13, 16, 10, 23, 0, 4, 2, 27, 14, 5, 20, 9,
|
||||
22, 18, 11, 3, 25, 7, 15, 6, 26, 19, 12, 1,
|
||||
40, 51, 30, 36, 46, 54, 29, 39, 50, 44, 32, 47,
|
||||
43, 48, 38, 55, 33, 52, 45, 41, 49, 35, 28, 31 };
|
||||
|
||||
void deskey(key, edf) /* Thanks to James Gillogly & Phil Karn! */
|
||||
unsigned char *key;
|
||||
short edf;
|
||||
{
|
||||
int i, j, l, m, n;
|
||||
unsigned char pc1m[56], pcr[56];
|
||||
unsigned long kn[32];
|
||||
|
||||
for ( j = 0; j < 56; j++ ) {
|
||||
l = pc1[j];
|
||||
m = l & 07;
|
||||
pc1m[j] = (key[l >> 3] & bytebit[m]) ? 1 : 0;
|
||||
}
|
||||
for( i = 0; i < 16; i++ ) {
|
||||
if( edf == DE1 ) m = (15 - i) << 1;
|
||||
else m = i << 1;
|
||||
n = m + 1;
|
||||
kn[m] = kn[n] = 0L;
|
||||
for( j = 0; j < 28; j++ ) {
|
||||
l = j + totrot[i];
|
||||
if( l < 28 ) pcr[j] = pc1m[l];
|
||||
else pcr[j] = pc1m[l - 28];
|
||||
}
|
||||
for( j = 28; j < 56; j++ ) {
|
||||
l = j + totrot[i];
|
||||
if( l < 56 ) pcr[j] = pc1m[l];
|
||||
else pcr[j] = pc1m[l - 28];
|
||||
}
|
||||
for( j = 0; j < 24; j++ ) {
|
||||
if( pcr[pc2[j]] ) kn[m] |= bigbyte[j];
|
||||
if( pcr[pc2[j+24]] ) kn[n] |= bigbyte[j];
|
||||
}
|
||||
}
|
||||
cookey(kn);
|
||||
return;
|
||||
}
|
||||
|
||||
static void cookey(raw1)
|
||||
unsigned long *raw1;
|
||||
{
|
||||
unsigned long *cook, *raw0;
|
||||
unsigned long dough[32];
|
||||
int i;
|
||||
|
||||
cook = dough;
|
||||
for( i = 0; i < 16; i++, raw1++ ) {
|
||||
raw0 = raw1++;
|
||||
*cook = (*raw0 & 0x00fc0000L) << 6;
|
||||
*cook |= (*raw0 & 0x00000fc0L) << 10;
|
||||
*cook |= (*raw1 & 0x00fc0000L) >> 10;
|
||||
*cook++ |= (*raw1 & 0x00000fc0L) >> 6;
|
||||
*cook = (*raw0 & 0x0003f000L) << 12;
|
||||
*cook |= (*raw0 & 0x0000003fL) << 16;
|
||||
*cook |= (*raw1 & 0x0003f000L) >> 4;
|
||||
*cook++ |= (*raw1 & 0x0000003fL);
|
||||
}
|
||||
usekey(dough);
|
||||
return;
|
||||
}
|
||||
|
||||
void cpkey(into)
|
||||
unsigned long *into;
|
||||
{
|
||||
unsigned long *from, *endp;
|
||||
|
||||
from = KnL, endp = &KnL[32];
|
||||
while( from < endp ) *into++ = *from++;
|
||||
return;
|
||||
}
|
||||
|
||||
void usekey(from)
|
||||
unsigned long *from;
|
||||
{
|
||||
unsigned long *to, *endp;
|
||||
|
||||
to = KnL, endp = &KnL[32];
|
||||
while( to < endp ) *to++ = *from++;
|
||||
return;
|
||||
}
|
||||
|
||||
void des(inblock, outblock)
|
||||
unsigned char *inblock, *outblock;
|
||||
{
|
||||
unsigned long work[2];
|
||||
|
||||
scrunch(inblock, work);
|
||||
desfunc(work, KnL);
|
||||
unscrun(work, outblock);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
static void scrunch(outof, into)
|
||||
unsigned char *outof;
|
||||
unsigned long *into;
|
||||
{
|
||||
*into = (*outof++ & 0xffL) << 24;
|
||||
*into |= (*outof++ & 0xffL) << 16;
|
||||
*into |= (*outof++ & 0xffL) << 8;
|
||||
*into++ |= (*outof++ & 0xffL);
|
||||
*into = (*outof++ & 0xffL) << 24;
|
||||
*into |= (*outof++ & 0xffL) << 16;
|
||||
*into |= (*outof++ & 0xffL) << 8;
|
||||
*into |= (*outof & 0xffL);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
static void unscrun(outof, into)
|
||||
unsigned long *outof;
|
||||
unsigned char *into;
|
||||
{
|
||||
*into++ = (*outof >> 24) & 0xffL;
|
||||
*into++ = (*outof >> 16) & 0xffL;
|
||||
*into++ = (*outof >> 8) & 0xffL;
|
||||
*into++ = *outof++ & 0xffL;
|
||||
*into++ = (*outof >> 24) & 0xffL;
|
||||
*into++ = (*outof >> 16) & 0xffL;
|
||||
*into++ = (*outof >> 8) & 0xffL;
|
||||
*into = *outof & 0xffL;
|
||||
return;
|
||||
}
|
||||
|
||||
#include "spr.h"
|
||||
/*
|
||||
static unsigned long SP1[64] = {
|
||||
0x01010400L, 0x00000000L, 0x00010000L, 0x01010404L,
|
||||
0x01010004L, 0x00010404L, 0x00000004L, 0x00010000L,
|
||||
0x00000400L, 0x01010400L, 0x01010404L, 0x00000400L,
|
||||
0x01000404L, 0x01010004L, 0x01000000L, 0x00000004L,
|
||||
0x00000404L, 0x01000400L, 0x01000400L, 0x00010400L,
|
||||
0x00010400L, 0x01010000L, 0x01010000L, 0x01000404L,
|
||||
0x00010004L, 0x01000004L, 0x01000004L, 0x00010004L,
|
||||
0x00000000L, 0x00000404L, 0x00010404L, 0x01000000L,
|
||||
0x00010000L, 0x01010404L, 0x00000004L, 0x01010000L,
|
||||
0x01010400L, 0x01000000L, 0x01000000L, 0x00000400L,
|
||||
0x01010004L, 0x00010000L, 0x00010400L, 0x01000004L,
|
||||
0x00000400L, 0x00000004L, 0x01000404L, 0x00010404L,
|
||||
0x01010404L, 0x00010004L, 0x01010000L, 0x01000404L,
|
||||
0x01000004L, 0x00000404L, 0x00010404L, 0x01010400L,
|
||||
0x00000404L, 0x01000400L, 0x01000400L, 0x00000000L,
|
||||
0x00010004L, 0x00010400L, 0x00000000L, 0x01010004L };
|
||||
|
||||
static unsigned long SP2[64] = {
|
||||
0x80108020L, 0x80008000L, 0x00008000L, 0x00108020L,
|
||||
0x00100000L, 0x00000020L, 0x80100020L, 0x80008020L,
|
||||
0x80000020L, 0x80108020L, 0x80108000L, 0x80000000L,
|
||||
0x80008000L, 0x00100000L, 0x00000020L, 0x80100020L,
|
||||
0x00108000L, 0x00100020L, 0x80008020L, 0x00000000L,
|
||||
0x80000000L, 0x00008000L, 0x00108020L, 0x80100000L,
|
||||
0x00100020L, 0x80000020L, 0x00000000L, 0x00108000L,
|
||||
0x00008020L, 0x80108000L, 0x80100000L, 0x00008020L,
|
||||
0x00000000L, 0x00108020L, 0x80100020L, 0x00100000L,
|
||||
0x80008020L, 0x80100000L, 0x80108000L, 0x00008000L,
|
||||
0x80100000L, 0x80008000L, 0x00000020L, 0x80108020L,
|
||||
0x00108020L, 0x00000020L, 0x00008000L, 0x80000000L,
|
||||
0x00008020L, 0x80108000L, 0x00100000L, 0x80000020L,
|
||||
0x00100020L, 0x80008020L, 0x80000020L, 0x00100020L,
|
||||
0x00108000L, 0x00000000L, 0x80008000L, 0x00008020L,
|
||||
0x80000000L, 0x80100020L, 0x80108020L, 0x00108000L };
|
||||
|
||||
static unsigned long SP3[64] = {
|
||||
0x00000208L, 0x08020200L, 0x00000000L, 0x08020008L,
|
||||
0x08000200L, 0x00000000L, 0x00020208L, 0x08000200L,
|
||||
0x00020008L, 0x08000008L, 0x08000008L, 0x00020000L,
|
||||
0x08020208L, 0x00020008L, 0x08020000L, 0x00000208L,
|
||||
0x08000000L, 0x00000008L, 0x08020200L, 0x00000200L,
|
||||
0x00020200L, 0x08020000L, 0x08020008L, 0x00020208L,
|
||||
0x08000208L, 0x00020200L, 0x00020000L, 0x08000208L,
|
||||
0x00000008L, 0x08020208L, 0x00000200L, 0x08000000L,
|
||||
0x08020200L, 0x08000000L, 0x00020008L, 0x00000208L,
|
||||
0x00020000L, 0x08020200L, 0x08000200L, 0x00000000L,
|
||||
0x00000200L, 0x00020008L, 0x08020208L, 0x08000200L,
|
||||
0x08000008L, 0x00000200L, 0x00000000L, 0x08020008L,
|
||||
0x08000208L, 0x00020000L, 0x08000000L, 0x08020208L,
|
||||
0x00000008L, 0x00020208L, 0x00020200L, 0x08000008L,
|
||||
0x08020000L, 0x08000208L, 0x00000208L, 0x08020000L,
|
||||
0x00020208L, 0x00000008L, 0x08020008L, 0x00020200L };
|
||||
|
||||
static unsigned long SP4[64] = {
|
||||
0x00802001L, 0x00002081L, 0x00002081L, 0x00000080L,
|
||||
0x00802080L, 0x00800081L, 0x00800001L, 0x00002001L,
|
||||
0x00000000L, 0x00802000L, 0x00802000L, 0x00802081L,
|
||||
0x00000081L, 0x00000000L, 0x00800080L, 0x00800001L,
|
||||
0x00000001L, 0x00002000L, 0x00800000L, 0x00802001L,
|
||||
0x00000080L, 0x00800000L, 0x00002001L, 0x00002080L,
|
||||
0x00800081L, 0x00000001L, 0x00002080L, 0x00800080L,
|
||||
0x00002000L, 0x00802080L, 0x00802081L, 0x00000081L,
|
||||
0x00800080L, 0x00800001L, 0x00802000L, 0x00802081L,
|
||||
0x00000081L, 0x00000000L, 0x00000000L, 0x00802000L,
|
||||
0x00002080L, 0x00800080L, 0x00800081L, 0x00000001L,
|
||||
0x00802001L, 0x00002081L, 0x00002081L, 0x00000080L,
|
||||
0x00802081L, 0x00000081L, 0x00000001L, 0x00002000L,
|
||||
0x00800001L, 0x00002001L, 0x00802080L, 0x00800081L,
|
||||
0x00002001L, 0x00002080L, 0x00800000L, 0x00802001L,
|
||||
0x00000080L, 0x00800000L, 0x00002000L, 0x00802080L };
|
||||
|
||||
static unsigned long SP5[64] = {
|
||||
0x00000100L, 0x02080100L, 0x02080000L, 0x42000100L,
|
||||
0x00080000L, 0x00000100L, 0x40000000L, 0x02080000L,
|
||||
0x40080100L, 0x00080000L, 0x02000100L, 0x40080100L,
|
||||
0x42000100L, 0x42080000L, 0x00080100L, 0x40000000L,
|
||||
0x02000000L, 0x40080000L, 0x40080000L, 0x00000000L,
|
||||
0x40000100L, 0x42080100L, 0x42080100L, 0x02000100L,
|
||||
0x42080000L, 0x40000100L, 0x00000000L, 0x42000000L,
|
||||
0x02080100L, 0x02000000L, 0x42000000L, 0x00080100L,
|
||||
0x00080000L, 0x42000100L, 0x00000100L, 0x02000000L,
|
||||
0x40000000L, 0x02080000L, 0x42000100L, 0x40080100L,
|
||||
0x02000100L, 0x40000000L, 0x42080000L, 0x02080100L,
|
||||
0x40080100L, 0x00000100L, 0x02000000L, 0x42080000L,
|
||||
0x42080100L, 0x00080100L, 0x42000000L, 0x42080100L,
|
||||
0x02080000L, 0x00000000L, 0x40080000L, 0x42000000L,
|
||||
0x00080100L, 0x02000100L, 0x40000100L, 0x00080000L,
|
||||
0x00000000L, 0x40080000L, 0x02080100L, 0x40000100L };
|
||||
|
||||
static unsigned long SP6[64] = {
|
||||
0x20000010L, 0x20400000L, 0x00004000L, 0x20404010L,
|
||||
0x20400000L, 0x00000010L, 0x20404010L, 0x00400000L,
|
||||
0x20004000L, 0x00404010L, 0x00400000L, 0x20000010L,
|
||||
0x00400010L, 0x20004000L, 0x20000000L, 0x00004010L,
|
||||
0x00000000L, 0x00400010L, 0x20004010L, 0x00004000L,
|
||||
0x00404000L, 0x20004010L, 0x00000010L, 0x20400010L,
|
||||
0x20400010L, 0x00000000L, 0x00404010L, 0x20404000L,
|
||||
0x00004010L, 0x00404000L, 0x20404000L, 0x20000000L,
|
||||
0x20004000L, 0x00000010L, 0x20400010L, 0x00404000L,
|
||||
0x20404010L, 0x00400000L, 0x00004010L, 0x20000010L,
|
||||
0x00400000L, 0x20004000L, 0x20000000L, 0x00004010L,
|
||||
0x20000010L, 0x20404010L, 0x00404000L, 0x20400000L,
|
||||
0x00404010L, 0x20404000L, 0x00000000L, 0x20400010L,
|
||||
0x00000010L, 0x00004000L, 0x20400000L, 0x00404010L,
|
||||
0x00004000L, 0x00400010L, 0x20004010L, 0x00000000L,
|
||||
0x20404000L, 0x20000000L, 0x00400010L, 0x20004010L };
|
||||
|
||||
static unsigned long SP7[64] = {
|
||||
0x00200000L, 0x04200002L, 0x04000802L, 0x00000000L,
|
||||
0x00000800L, 0x04000802L, 0x00200802L, 0x04200800L,
|
||||
0x04200802L, 0x00200000L, 0x00000000L, 0x04000002L,
|
||||
0x00000002L, 0x04000000L, 0x04200002L, 0x00000802L,
|
||||
0x04000800L, 0x00200802L, 0x00200002L, 0x04000800L,
|
||||
0x04000002L, 0x04200000L, 0x04200800L, 0x00200002L,
|
||||
0x04200000L, 0x00000800L, 0x00000802L, 0x04200802L,
|
||||
0x00200800L, 0x00000002L, 0x04000000L, 0x00200800L,
|
||||
0x04000000L, 0x00200800L, 0x00200000L, 0x04000802L,
|
||||
0x04000802L, 0x04200002L, 0x04200002L, 0x00000002L,
|
||||
0x00200002L, 0x04000000L, 0x04000800L, 0x00200000L,
|
||||
0x04200800L, 0x00000802L, 0x00200802L, 0x04200800L,
|
||||
0x00000802L, 0x04000002L, 0x04200802L, 0x04200000L,
|
||||
0x00200800L, 0x00000000L, 0x00000002L, 0x04200802L,
|
||||
0x00000000L, 0x00200802L, 0x04200000L, 0x00000800L,
|
||||
0x04000002L, 0x04000800L, 0x00000800L, 0x00200002L };
|
||||
|
||||
static unsigned long SP8[64] = {
|
||||
0x10001040L, 0x00001000L, 0x00040000L, 0x10041040L,
|
||||
0x10000000L, 0x10001040L, 0x00000040L, 0x10000000L,
|
||||
0x00040040L, 0x10040000L, 0x10041040L, 0x00041000L,
|
||||
0x10041000L, 0x00041040L, 0x00001000L, 0x00000040L,
|
||||
0x10040000L, 0x10000040L, 0x10001000L, 0x00001040L,
|
||||
0x00041000L, 0x00040040L, 0x10040040L, 0x10041000L,
|
||||
0x00001040L, 0x00000000L, 0x00000000L, 0x10040040L,
|
||||
0x10000040L, 0x10001000L, 0x00041040L, 0x00040000L,
|
||||
0x00041040L, 0x00040000L, 0x10041000L, 0x00001000L,
|
||||
0x00000040L, 0x10040040L, 0x00001000L, 0x00041040L,
|
||||
0x10001000L, 0x00000040L, 0x10000040L, 0x10040000L,
|
||||
0x10040040L, 0x10000000L, 0x00040000L, 0x10001040L,
|
||||
0x00000000L, 0x10041040L, 0x00040040L, 0x10000040L,
|
||||
0x10040000L, 0x10001000L, 0x10001040L, 0x00000000L,
|
||||
0x10041040L, 0x00041000L, 0x00041000L, 0x00001040L,
|
||||
0x00001040L, 0x00040040L, 0x10000000L, 0x10041000L };
|
||||
*/
|
||||
|
||||
|
||||
static void desfunc(block, keys)
|
||||
unsigned long *block, *keys;
|
||||
{
|
||||
unsigned long fval, work, right, leftt;
|
||||
int round;
|
||||
|
||||
leftt = block[0];
|
||||
right = block[1];
|
||||
work = ((leftt >> 4) ^ right) & 0x0f0f0f0fL;
|
||||
right ^= work;
|
||||
leftt ^= (work << 4);
|
||||
work = ((leftt >> 16) ^ right) & 0x0000ffffL;
|
||||
right ^= work;
|
||||
leftt ^= (work << 16);
|
||||
work = ((right >> 2) ^ leftt) & 0x33333333L;
|
||||
leftt ^= work;
|
||||
right ^= (work << 2);
|
||||
work = ((right >> 8) ^ leftt) & 0x00ff00ffL;
|
||||
leftt ^= work;
|
||||
right ^= (work << 8);
|
||||
right = ((right << 1) | ((right >> 31) & 1L)) & 0xffffffffL;
|
||||
work = (leftt ^ right) & 0xaaaaaaaaL;
|
||||
leftt ^= work;
|
||||
right ^= work;
|
||||
leftt = ((leftt << 1) | ((leftt >> 31) & 1L)) & 0xffffffffL;
|
||||
|
||||
for( round = 0; round < 8; round++ ) {
|
||||
work = (right << 28) | (right >> 4);
|
||||
work ^= *keys++;
|
||||
fval = SP7[ work & 0x3fL];
|
||||
fval |= SP5[(work >> 8) & 0x3fL];
|
||||
fval |= SP3[(work >> 16) & 0x3fL];
|
||||
fval |= SP1[(work >> 24) & 0x3fL];
|
||||
work = right ^ *keys++;
|
||||
fval |= SP8[ work & 0x3fL];
|
||||
fval |= SP6[(work >> 8) & 0x3fL];
|
||||
fval |= SP4[(work >> 16) & 0x3fL];
|
||||
fval |= SP2[(work >> 24) & 0x3fL];
|
||||
leftt ^= fval;
|
||||
work = (leftt << 28) | (leftt >> 4);
|
||||
work ^= *keys++;
|
||||
fval = SP7[ work & 0x3fL];
|
||||
fval |= SP5[(work >> 8) & 0x3fL];
|
||||
fval |= SP3[(work >> 16) & 0x3fL];
|
||||
fval |= SP1[(work >> 24) & 0x3fL];
|
||||
work = leftt ^ *keys++;
|
||||
fval |= SP8[ work & 0x3fL];
|
||||
fval |= SP6[(work >> 8) & 0x3fL];
|
||||
fval |= SP4[(work >> 16) & 0x3fL];
|
||||
fval |= SP2[(work >> 24) & 0x3fL];
|
||||
right ^= fval;
|
||||
}
|
||||
|
||||
right = (right << 31) | (right >> 1);
|
||||
work = (leftt ^ right) & 0xaaaaaaaaL;
|
||||
leftt ^= work;
|
||||
right ^= work;
|
||||
leftt = (leftt << 31) | (leftt >> 1);
|
||||
work = ((leftt >> 8) ^ right) & 0x00ff00ffL;
|
||||
right ^= work;
|
||||
leftt ^= (work << 8);
|
||||
work = ((leftt >> 2) ^ right) & 0x33333333L;
|
||||
right ^= work;
|
||||
leftt ^= (work << 2);
|
||||
work = ((right >> 16) ^ leftt) & 0x0000ffffL;
|
||||
leftt ^= work;
|
||||
right ^= (work << 16);
|
||||
work = ((right >> 4) ^ leftt) & 0x0f0f0f0fL;
|
||||
leftt ^= work;
|
||||
right ^= (work << 4);
|
||||
*block++ = right;
|
||||
*block = leftt;
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef D2_DES
|
||||
|
||||
void des2key(hexkey, mode) /* stomps on Kn3 too */
|
||||
unsigned char *hexkey; /* unsigned char[16] */
|
||||
short mode;
|
||||
{
|
||||
short revmod;
|
||||
|
||||
revmod = (mode == EN0) ? DE1 : EN0;
|
||||
deskey(&hexkey[8], revmod);
|
||||
cpkey(KnR);
|
||||
deskey(hexkey, mode);
|
||||
cpkey(Kn3); /* Kn3 = KnL */
|
||||
return;
|
||||
}
|
||||
|
||||
void Ddes(from, into)
|
||||
unsigned char *from, *into; /* unsigned char[8] */
|
||||
{
|
||||
unsigned long work[2];
|
||||
|
||||
scrunch(from, work);
|
||||
desfunc(work, KnL);
|
||||
desfunc(work, KnR);
|
||||
desfunc(work, Kn3);
|
||||
unscrun(work, into);
|
||||
return;
|
||||
}
|
||||
|
||||
void D2des(from, into)
|
||||
unsigned char *from; /* unsigned char[16] */
|
||||
unsigned char *into; /* unsigned char[16] */
|
||||
{
|
||||
unsigned long *right, *l1, swap;
|
||||
unsigned long leftt[2], bufR[2];
|
||||
|
||||
right = bufR;
|
||||
l1 = &leftt[1];
|
||||
scrunch(from, leftt);
|
||||
scrunch(&from[8], right);
|
||||
desfunc(leftt, KnL);
|
||||
desfunc(right, KnL);
|
||||
swap = *l1;
|
||||
*l1 = *right;
|
||||
*right = swap;
|
||||
desfunc(leftt, KnR);
|
||||
desfunc(right, KnR);
|
||||
swap = *l1;
|
||||
*l1 = *right;
|
||||
*right = swap;
|
||||
desfunc(leftt, Kn3);
|
||||
desfunc(right, Kn3);
|
||||
unscrun(leftt, into);
|
||||
unscrun(right, &into[8]);
|
||||
return;
|
||||
}
|
||||
|
||||
void makekey(aptr, kptr)
|
||||
char *aptr; /* NULL-terminated */
|
||||
unsigned char *kptr; /* unsigned char[8] */
|
||||
{
|
||||
unsigned char *store;
|
||||
int first, i;
|
||||
unsigned long savek[96];
|
||||
|
||||
cpDkey(savek);
|
||||
des2key(Df_Key, EN0);
|
||||
for( i = 0; i < 8; i++ ) kptr[i] = Df_Key[i];
|
||||
first = 1;
|
||||
while( (*aptr != '\0') || first ) {
|
||||
store = kptr;
|
||||
for( i = 0; i < 8 && (*aptr != '\0'); i++ ) {
|
||||
*store++ ^= *aptr & 0x7f;
|
||||
*aptr++ = '\0';
|
||||
}
|
||||
Ddes(kptr, kptr);
|
||||
first = 0;
|
||||
}
|
||||
useDkey(savek);
|
||||
return;
|
||||
}
|
||||
|
||||
void make2key(aptr, kptr)
|
||||
char *aptr; /* NULL-terminated */
|
||||
unsigned char *kptr; /* unsigned char[16] */
|
||||
{
|
||||
unsigned char *store;
|
||||
int first, i;
|
||||
unsigned long savek[96];
|
||||
|
||||
cpDkey(savek);
|
||||
des2key(Df_Key, EN0);
|
||||
for( i = 0; i < 16; i++ ) kptr[i] = Df_Key[i];
|
||||
first = 1;
|
||||
while( (*aptr != '\0') || first ) {
|
||||
store = kptr;
|
||||
for( i = 0; i < 16 && (*aptr != '\0'); i++ ) {
|
||||
*store++ ^= *aptr & 0x7f;
|
||||
*aptr++ = '\0';
|
||||
}
|
||||
D2des(kptr, kptr);
|
||||
first = 0;
|
||||
}
|
||||
useDkey(savek);
|
||||
return;
|
||||
}
|
||||
|
||||
#ifndef D3_DES /* D2_DES only */
|
||||
|
||||
void cp2key(into)
|
||||
unsigned long *into; /* unsigned long[64] */
|
||||
{
|
||||
unsigned long *from, *endp;
|
||||
|
||||
cpkey(into);
|
||||
into = &into[32];
|
||||
from = KnR, endp = &KnR[32];
|
||||
while( from < endp ) *into++ = *from++;
|
||||
return;
|
||||
}
|
||||
|
||||
void use2key(from) /* stomps on Kn3 too */
|
||||
unsigned long *from; /* unsigned long[64] */
|
||||
{
|
||||
unsigned long *to, *endp;
|
||||
|
||||
usekey(from);
|
||||
from = &from[32];
|
||||
to = KnR, endp = &KnR[32];
|
||||
while( to < endp ) *to++ = *from++;
|
||||
cpkey(Kn3); /* Kn3 = KnL */
|
||||
return;
|
||||
}
|
||||
|
||||
#else /* D3_DES too */
|
||||
|
||||
void des3key(hexkey, mode)
|
||||
unsigned char *hexkey; /* unsigned char[24] */
|
||||
short mode;
|
||||
{
|
||||
unsigned char *first, *third;
|
||||
short revmod;
|
||||
|
||||
if( mode == EN0 ) {
|
||||
revmod = DE1;
|
||||
first = hexkey;
|
||||
third = &hexkey[16];
|
||||
}
|
||||
else {
|
||||
revmod = EN0;
|
||||
first = &hexkey[16];
|
||||
third = hexkey;
|
||||
}
|
||||
deskey(&hexkey[8], revmod);
|
||||
cpkey(KnR);
|
||||
deskey(third, mode);
|
||||
cpkey(Kn3);
|
||||
deskey(first, mode);
|
||||
return;
|
||||
}
|
||||
|
||||
void cp3key(into)
|
||||
unsigned long *into; /* unsigned long[96] */
|
||||
{
|
||||
unsigned long *from, *endp;
|
||||
|
||||
cpkey(into);
|
||||
into = &into[32];
|
||||
from = KnR, endp = &KnR[32];
|
||||
while( from < endp ) *into++ = *from++;
|
||||
from = Kn3, endp = &Kn3[32];
|
||||
while( from < endp ) *into++ = *from++;
|
||||
return;
|
||||
}
|
||||
|
||||
void use3key(from)
|
||||
unsigned long *from; /* unsigned long[96] */
|
||||
{
|
||||
unsigned long *to, *endp;
|
||||
|
||||
usekey(from);
|
||||
from = &from[32];
|
||||
to = KnR, endp = &KnR[32];
|
||||
while( to < endp ) *to++ = *from++;
|
||||
to = Kn3, endp = &Kn3[32];
|
||||
while( to < endp ) *to++ = *from++;
|
||||
return;
|
||||
}
|
||||
|
||||
static void D3des(unsigned char *, unsigned char *);
|
||||
|
||||
static void D3des(from, into) /* amateur theatrics */
|
||||
unsigned char *from; /* unsigned char[24] */
|
||||
unsigned char *into; /* unsigned char[24] */
|
||||
{
|
||||
unsigned long swap, leftt[2], middl[2], right[2];
|
||||
|
||||
scrunch(from, leftt);
|
||||
scrunch(&from[8], middl);
|
||||
scrunch(&from[16], right);
|
||||
desfunc(leftt, KnL);
|
||||
desfunc(middl, KnL);
|
||||
desfunc(right, KnL);
|
||||
swap = leftt[1];
|
||||
leftt[1] = middl[0];
|
||||
middl[0] = swap;
|
||||
swap = middl[1];
|
||||
middl[1] = right[0];
|
||||
right[0] = swap;
|
||||
desfunc(leftt, KnR);
|
||||
desfunc(middl, KnR);
|
||||
desfunc(right, KnR);
|
||||
swap = leftt[1];
|
||||
leftt[1] = middl[0];
|
||||
middl[0] = swap;
|
||||
swap = middl[1];
|
||||
middl[1] = right[0];
|
||||
right[0] = swap;
|
||||
desfunc(leftt, Kn3);
|
||||
desfunc(middl, Kn3);
|
||||
desfunc(right, Kn3);
|
||||
unscrun(leftt, into);
|
||||
unscrun(middl, &into[8]);
|
||||
unscrun(right, &into[16]);
|
||||
return;
|
||||
}
|
||||
|
||||
void make3key(aptr, kptr)
|
||||
char *aptr; /* NULL-terminated */
|
||||
unsigned char *kptr; /* unsigned char[24] */
|
||||
{
|
||||
unsigned char *store;
|
||||
int first, i;
|
||||
unsigned long savek[96];
|
||||
|
||||
cp3key(savek);
|
||||
des3key(Df_Key, EN0);
|
||||
for( i = 0; i < 24; i++ ) kptr[i] = Df_Key[i];
|
||||
first = 1;
|
||||
while( (*aptr != '\0') || first ) {
|
||||
store = kptr;
|
||||
for( i = 0; i < 24 && (*aptr != '\0'); i++ ) {
|
||||
*store++ ^= *aptr & 0x7f;
|
||||
*aptr++ = '\0';
|
||||
}
|
||||
D3des(kptr, kptr);
|
||||
first = 0;
|
||||
}
|
||||
use3key(savek);
|
||||
return;
|
||||
}
|
||||
|
||||
#endif /* D3_DES */
|
||||
#endif /* D2_DES */
|
||||
|
||||
/* Validation sets:
|
||||
*
|
||||
* Single-length key, single-length plaintext -
|
||||
* Key : 0123 4567 89ab cdef
|
||||
* Plain : 0123 4567 89ab cde7
|
||||
* Cipher : c957 4425 6a5e d31d
|
||||
*
|
||||
* Double-length key, single-length plaintext -
|
||||
* Key : 0123 4567 89ab cdef fedc ba98 7654 3210
|
||||
* Plain : 0123 4567 89ab cde7
|
||||
* Cipher : 7f1d 0a77 826b 8aff
|
||||
*
|
||||
* Double-length key, double-length plaintext -
|
||||
* Key : 0123 4567 89ab cdef fedc ba98 7654 3210
|
||||
* Plain : 0123 4567 89ab cdef 0123 4567 89ab cdff
|
||||
* Cipher : 27a0 8440 406a df60 278f 47cf 42d6 15d7
|
||||
*
|
||||
* Triple-length key, single-length plaintext -
|
||||
* Key : 0123 4567 89ab cdef fedc ba98 7654 3210 89ab cdef 0123 4567
|
||||
* Plain : 0123 4567 89ab cde7
|
||||
* Cipher : de0b 7c06 ae5e 0ed5
|
||||
*
|
||||
* Triple-length key, double-length plaintext -
|
||||
* Key : 0123 4567 89ab cdef fedc ba98 7654 3210 89ab cdef 0123 4567
|
||||
* Plain : 0123 4567 89ab cdef 0123 4567 89ab cdff
|
||||
* Cipher : ad0d 1b30 ac17 cf07 0ed1 1c63 81e4 4de5
|
||||
*
|
||||
* d3des V5.09 rwo 9208.04 20:31 Graven Imagery
|
||||
**********************************************************************/
|
||||
|
98
src/calibre/utils/msdes/msdesmodule.c
Normal file
98
src/calibre/utils/msdes/msdesmodule.c
Normal file
@ -0,0 +1,98 @@
|
||||
/* __license__ = 'GPL v3'
|
||||
* __copyright__ = '2008, Marshall T. Vandegrift <llasram@gmail.com>'
|
||||
*
|
||||
* Python module C glue code.
|
||||
*/
|
||||
|
||||
|
||||
#include <Python.h>
|
||||
|
||||
#include <d3des.h>
|
||||
|
||||
static char msdes_doc[] =
|
||||
"Provide LIT-specific DES en/decryption.";
|
||||
|
||||
static PyObject *MsDesError = NULL;
|
||||
|
||||
static PyObject *
|
||||
msdes_deskey(PyObject *self, PyObject *args)
|
||||
{
|
||||
unsigned char *key = NULL;
|
||||
unsigned int len = 0;
|
||||
short int edf = 0;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "s#h", &key, &len, &edf)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (len != 8) {
|
||||
PyErr_SetString(MsDesError, "Key length incorrect");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ((edf != EN0) && (edf != DE1)) {
|
||||
PyErr_SetString(MsDesError, "En/decryption direction invalid");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
deskey(key, edf);
|
||||
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
msdes_des(PyObject *self, PyObject *args)
|
||||
{
|
||||
unsigned char *inbuf = NULL;
|
||||
unsigned char *outbuf = NULL;
|
||||
unsigned int len = 0;
|
||||
unsigned int off = 0;
|
||||
PyObject *retval = NULL;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "s#", &inbuf, &len)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ((len == 0) || ((len % 8) != 0)) {
|
||||
PyErr_SetString(MsDesError,
|
||||
"Input length not a multiple of the block size");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
retval = PyString_FromStringAndSize(NULL, len);
|
||||
if (retval == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
outbuf = (unsigned char *)PyString_AS_STRING(retval);
|
||||
|
||||
for (off = 0; off < len; off += 8) {
|
||||
des((inbuf + off), (outbuf + off));
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
static PyMethodDef msdes_methods[] = {
|
||||
{ "deskey", &msdes_deskey, METH_VARARGS, "Provide a new key for DES en/decryption." },
|
||||
{ "des", &msdes_des, METH_VARARGS, "Perform DES en/decryption." },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
PyMODINIT_FUNC
|
||||
initmsdes(void)
|
||||
{
|
||||
PyObject *m;
|
||||
|
||||
m = Py_InitModule3("msdes", msdes_methods, msdes_doc);
|
||||
if (m == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
MsDesError = PyErr_NewException("msdes.MsDesError", NULL, NULL);
|
||||
Py_INCREF(MsDesError);
|
||||
PyModule_AddObject(m, "MsDesError", MsDesError);
|
||||
PyModule_AddObject(m, "EN0", PyInt_FromLong(EN0));
|
||||
PyModule_AddObject(m, "DE1", PyInt_FromLong(DE1));
|
||||
|
||||
return;
|
||||
}
|
202
src/calibre/utils/msdes/spr.h
Normal file
202
src/calibre/utils/msdes/spr.h
Normal file
@ -0,0 +1,202 @@
|
||||
/* crypto/des/spr.h */
|
||||
/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com)
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young (eay@cryptsoft.com).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young (eay@cryptsoft.com)"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.]
|
||||
*/
|
||||
|
||||
static unsigned long SP1[64] = {
|
||||
0x02080800L, 0x00080000L, 0x02000002L, 0x02080802L,
|
||||
0x02000000L, 0x00080802L, 0x00080002L, 0x02000002L,
|
||||
0x00080802L, 0x02080800L, 0x02080000L, 0x00000802L,
|
||||
0x02000802L, 0x02000000L, 0x00000000L, 0x00080002L,
|
||||
0x00080000L, 0x00000002L, 0x02000800L, 0x00080800L,
|
||||
0x02080802L, 0x02080000L, 0x00000802L, 0x02000800L,
|
||||
0x00000002L, 0x00000800L, 0x00080800L, 0x02080002L,
|
||||
0x00000800L, 0x02000802L, 0x02080002L, 0x00000000L,
|
||||
0x00000000L, 0x02080802L, 0x02000800L, 0x00080002L,
|
||||
0x02080800L, 0x00080000L, 0x00000802L, 0x02000800L,
|
||||
0x02080002L, 0x00000800L, 0x00080800L, 0x02000002L,
|
||||
0x00080802L, 0x00000002L, 0x02000002L, 0x02080000L,
|
||||
0x02080802L, 0x00080800L, 0x02080000L, 0x02000802L,
|
||||
0x02000000L, 0x00000802L, 0x00080002L, 0x00000000L,
|
||||
0x00080000L, 0x02000000L, 0x02000802L, 0x02080800L,
|
||||
0x00000002L, 0x02080002L, 0x00000800L, 0x00080802L
|
||||
};
|
||||
static unsigned long SP2[64] = {
|
||||
0x40108010L, 0x00000000L, 0x00108000L, 0x40100000L,
|
||||
0x40000010L, 0x00008010L, 0x40008000L, 0x00108000L,
|
||||
0x00008000L, 0x40100010L, 0x00000010L, 0x40008000L,
|
||||
0x00100010L, 0x40108000L, 0x40100000L, 0x00000010L,
|
||||
0x00100000L, 0x40008010L, 0x40100010L, 0x00008000L,
|
||||
0x00108010L, 0x40000000L, 0x00000000L, 0x00100010L,
|
||||
0x40008010L, 0x00108010L, 0x40108000L, 0x40000010L,
|
||||
0x40000000L, 0x00100000L, 0x00008010L, 0x40108010L,
|
||||
0x00100010L, 0x40108000L, 0x40008000L, 0x00108010L,
|
||||
0x40108010L, 0x00100010L, 0x40000010L, 0x00000000L,
|
||||
0x40000000L, 0x00008010L, 0x00100000L, 0x40100010L,
|
||||
0x00008000L, 0x40000000L, 0x00108010L, 0x40008010L,
|
||||
0x40108000L, 0x00008000L, 0x00000000L, 0x40000010L,
|
||||
0x00000010L, 0x40108010L, 0x00108000L, 0x40100000L,
|
||||
0x40100010L, 0x00100000L, 0x00008010L, 0x40008000L,
|
||||
0x40008010L, 0x00000010L, 0x40100000L, 0x00108000L
|
||||
};
|
||||
static unsigned long SP3[64] = {
|
||||
0x04000001L, 0x04040100L, 0x00000100L, 0x04000101L,
|
||||
0x00040001L, 0x04000000L, 0x04000101L, 0x00040100L,
|
||||
0x04000100L, 0x00040000L, 0x04040000L, 0x00000001L,
|
||||
0x04040101L, 0x00000101L, 0x00000001L, 0x04040001L,
|
||||
0x00000000L, 0x00040001L, 0x04040100L, 0x00000100L,
|
||||
0x00000101L, 0x04040101L, 0x00040000L, 0x04000001L,
|
||||
0x04040001L, 0x04000100L, 0x00040101L, 0x04040000L,
|
||||
0x00040100L, 0x00000000L, 0x04000000L, 0x00040101L,
|
||||
0x04040100L, 0x00000100L, 0x00000001L, 0x00040000L,
|
||||
0x00000101L, 0x00040001L, 0x04040000L, 0x04000101L,
|
||||
0x00000000L, 0x04040100L, 0x00040100L, 0x04040001L,
|
||||
0x00040001L, 0x04000000L, 0x04040101L, 0x00000001L,
|
||||
0x00040101L, 0x04000001L, 0x04000000L, 0x04040101L,
|
||||
0x00040000L, 0x04000100L, 0x04000101L, 0x00040100L,
|
||||
0x04000100L, 0x00000000L, 0x04040001L, 0x00000101L,
|
||||
0x04000001L, 0x00040101L, 0x00000100L, 0x04040000L
|
||||
};
|
||||
static unsigned long SP4[64] = {
|
||||
0x00401008L, 0x10001000L, 0x00000008L, 0x10401008L,
|
||||
0x00000000L, 0x10400000L, 0x10001008L, 0x00400008L,
|
||||
0x10401000L, 0x10000008L, 0x10000000L, 0x00001008L,
|
||||
0x10000008L, 0x00401008L, 0x00400000L, 0x10000000L,
|
||||
0x10400008L, 0x00401000L, 0x00001000L, 0x00000008L,
|
||||
0x00401000L, 0x10001008L, 0x10400000L, 0x00001000L,
|
||||
0x00001008L, 0x00000000L, 0x00400008L, 0x10401000L,
|
||||
0x10001000L, 0x10400008L, 0x10401008L, 0x00400000L,
|
||||
0x10400008L, 0x00001008L, 0x00400000L, 0x10000008L,
|
||||
0x00401000L, 0x10001000L, 0x00000008L, 0x10400000L,
|
||||
0x10001008L, 0x00000000L, 0x00001000L, 0x00400008L,
|
||||
0x00000000L, 0x10400008L, 0x10401000L, 0x00001000L,
|
||||
0x10000000L, 0x10401008L, 0x00401008L, 0x00400000L,
|
||||
0x10401008L, 0x00000008L, 0x10001000L, 0x00401008L,
|
||||
0x00400008L, 0x00401000L, 0x10400000L, 0x10001008L,
|
||||
0x00001008L, 0x10000000L, 0x10000008L, 0x10401000L
|
||||
};
|
||||
static unsigned long SP5[64] = {
|
||||
0x08000000L, 0x00010000L, 0x00000400L, 0x08010420L,
|
||||
0x08010020L, 0x08000400L, 0x00010420L, 0x08010000L,
|
||||
0x00010000L, 0x00000020L, 0x08000020L, 0x00010400L,
|
||||
0x08000420L, 0x08010020L, 0x08010400L, 0x00000000L,
|
||||
0x00010400L, 0x08000000L, 0x00010020L, 0x00000420L,
|
||||
0x08000400L, 0x00010420L, 0x00000000L, 0x08000020L,
|
||||
0x00000020L, 0x08000420L, 0x08010420L, 0x00010020L,
|
||||
0x08010000L, 0x00000400L, 0x00000420L, 0x08010400L,
|
||||
0x08010400L, 0x08000420L, 0x00010020L, 0x08010000L,
|
||||
0x00010000L, 0x00000020L, 0x08000020L, 0x08000400L,
|
||||
0x08000000L, 0x00010400L, 0x08010420L, 0x00000000L,
|
||||
0x00010420L, 0x08000000L, 0x00000400L, 0x00010020L,
|
||||
0x08000420L, 0x00000400L, 0x00000000L, 0x08010420L,
|
||||
0x08010020L, 0x08010400L, 0x00000420L, 0x00010000L,
|
||||
0x00010400L, 0x08010020L, 0x08000400L, 0x00000420L,
|
||||
0x00000020L, 0x00010420L, 0x08010000L, 0x08000020L
|
||||
};
|
||||
static unsigned long SP6[64] = {
|
||||
0x80000040L, 0x00200040L, 0x00000000L, 0x80202000L,
|
||||
0x00200040L, 0x00002000L, 0x80002040L, 0x00200000L,
|
||||
0x00002040L, 0x80202040L, 0x00202000L, 0x80000000L,
|
||||
0x80002000L, 0x80000040L, 0x80200000L, 0x00202040L,
|
||||
0x00200000L, 0x80002040L, 0x80200040L, 0x00000000L,
|
||||
0x00002000L, 0x00000040L, 0x80202000L, 0x80200040L,
|
||||
0x80202040L, 0x80200000L, 0x80000000L, 0x00002040L,
|
||||
0x00000040L, 0x00202000L, 0x00202040L, 0x80002000L,
|
||||
0x00002040L, 0x80000000L, 0x80002000L, 0x00202040L,
|
||||
0x80202000L, 0x00200040L, 0x00000000L, 0x80002000L,
|
||||
0x80000000L, 0x00002000L, 0x80200040L, 0x00200000L,
|
||||
0x00200040L, 0x80202040L, 0x00202000L, 0x00000040L,
|
||||
0x80202040L, 0x00202000L, 0x00200000L, 0x80002040L,
|
||||
0x80000040L, 0x80200000L, 0x00202040L, 0x00000000L,
|
||||
0x00002000L, 0x80000040L, 0x80002040L, 0x80202000L,
|
||||
0x80200000L, 0x00002040L, 0x00000040L, 0x80200040L,
|
||||
};
|
||||
static unsigned long SP7[64] = {
|
||||
0x00004000L, 0x00000200L, 0x01000200L, 0x01000004L,
|
||||
0x01004204L, 0x00004004L, 0x00004200L, 0x00000000L,
|
||||
0x01000000L, 0x01000204L, 0x00000204L, 0x01004000L,
|
||||
0x00000004L, 0x01004200L, 0x01004000L, 0x00000204L,
|
||||
0x01000204L, 0x00004000L, 0x00004004L, 0x01004204L,
|
||||
0x00000000L, 0x01000200L, 0x01000004L, 0x00004200L,
|
||||
0x01004004L, 0x00004204L, 0x01004200L, 0x00000004L,
|
||||
0x00004204L, 0x01004004L, 0x00000200L, 0x01000000L,
|
||||
0x00004204L, 0x01004000L, 0x01004004L, 0x00000204L,
|
||||
0x00004000L, 0x00000200L, 0x01000000L, 0x01004004L,
|
||||
0x01000204L, 0x00004204L, 0x00004200L, 0x00000000L,
|
||||
0x00000200L, 0x01000004L, 0x00000004L, 0x01000200L,
|
||||
0x00000000L, 0x01000204L, 0x01000200L, 0x00004200L,
|
||||
0x00000204L, 0x00004000L, 0x01004204L, 0x01000000L,
|
||||
0x01004200L, 0x00000004L, 0x00004004L, 0x01004204L,
|
||||
0x01000004L, 0x01004200L, 0x01004000L, 0x00004004L,
|
||||
};
|
||||
static unsigned long SP8[64] = {
|
||||
0x20800080L, 0x20820000L, 0x00020080L, 0x00000000L,
|
||||
0x20020000L, 0x00800080L, 0x20800000L, 0x20820080L,
|
||||
0x00000080L, 0x20000000L, 0x00820000L, 0x00020080L,
|
||||
0x00820080L, 0x20020080L, 0x20000080L, 0x20800000L,
|
||||
0x00020000L, 0x00820080L, 0x00800080L, 0x20020000L,
|
||||
0x20820080L, 0x20000080L, 0x00000000L, 0x00820000L,
|
||||
0x20000000L, 0x00800000L, 0x20020080L, 0x20800080L,
|
||||
0x00800000L, 0x00020000L, 0x20820000L, 0x00000080L,
|
||||
0x00800000L, 0x00020000L, 0x20000080L, 0x20820080L,
|
||||
0x00020080L, 0x20000000L, 0x00000000L, 0x00820000L,
|
||||
0x20800080L, 0x20020080L, 0x20020000L, 0x00800080L,
|
||||
0x20820000L, 0x00000080L, 0x00800080L, 0x20020000L,
|
||||
0x20820080L, 0x00800000L, 0x20800000L, 0x20000080L,
|
||||
0x00820000L, 0x00020080L, 0x20020080L, 0x20800000L,
|
||||
0x00000080L, 0x20820000L, 0x00820080L, 0x00000000L,
|
||||
0x20000000L, 0x20800080L, 0x00020000L, 0x00820080L,
|
||||
};
|
@ -163,15 +163,17 @@ class ProgressBar:
|
||||
|
||||
The progress bar is colored, if the terminal supports color
|
||||
output; and adjusts to the width of the terminal.
|
||||
|
||||
If the terminal doesn't have the required capabilities, it uses a
|
||||
simple progress bar.
|
||||
"""
|
||||
BAR = '%3d%% ${GREEN}[${BOLD}%s%s${NORMAL}${GREEN}]${NORMAL}\n'
|
||||
HEADER = '${BOLD}${CYAN}%s${NORMAL}\n\n'
|
||||
|
||||
def __init__(self, term, header):
|
||||
self.term = term
|
||||
if not (self.term.CLEAR_EOL and self.term.UP and self.term.BOL):
|
||||
raise ValueError("Terminal isn't capable enough -- you "
|
||||
"should use a simpler progress dispaly.")
|
||||
def __init__(self, term, header, no_progress_bar = False):
|
||||
self.term, self.no_progress_bar = term, no_progress_bar
|
||||
self.fancy = self.term.CLEAR_EOL and self.term.UP and self.term.BOL
|
||||
if self.fancy:
|
||||
self.width = self.term.COLS or 75
|
||||
self.bar = term.render(self.BAR)
|
||||
self.header = self.term.render(self.HEADER % header.center(self.width))
|
||||
@ -179,7 +181,12 @@ class ProgressBar:
|
||||
|
||||
def update(self, percent, message=''):
|
||||
if isinstance(message, unicode):
|
||||
message = message.encode('utf-8', 'ignore')
|
||||
message = message.encode('utf-8', 'replace')
|
||||
|
||||
if self.no_progress_bar:
|
||||
if message:
|
||||
print message
|
||||
elif self.fancy:
|
||||
if self.cleared:
|
||||
sys.stdout.write(self.header)
|
||||
self.cleared = 0
|
||||
@ -190,9 +197,16 @@ class ProgressBar:
|
||||
(self.bar % (100*percent, '='*n, '-'*(self.width-10-n))) +
|
||||
self.term.CLEAR_EOL + msg)
|
||||
sys.stdout.flush()
|
||||
else:
|
||||
if not message:
|
||||
print '%d%%'%(percent*100),
|
||||
else:
|
||||
print '%d%%'%(percent*100), message
|
||||
sys.stdout.flush()
|
||||
|
||||
|
||||
def clear(self):
|
||||
if not self.cleared:
|
||||
if self.fancy and not self.cleared:
|
||||
sys.stdout.write(self.term.BOL + self.term.CLEAR_EOL +
|
||||
self.term.UP + self.term.CLEAR_EOL +
|
||||
self.term.UP + self.term.CLEAR_EOL)
|
18
src/calibre/utils/windows/Makefile
Normal file
18
src/calibre/utils/windows/Makefile
Normal file
@ -0,0 +1,18 @@
|
||||
# Makefile to test the winutil module
|
||||
# Invoke with nmake /f Makefile.winutil
|
||||
|
||||
test : winutil.pyd
|
||||
python.exe -c "import winutil; winutil.set_debug(True); print winutil.get_usb_devices(); print winutil.get_mounted_volumes_for_usb_device(0x054c, 0x031e)"
|
||||
|
||||
winutil.pyd : winutil.obj
|
||||
link.exe /DLL /nologo /INCREMENTAL:NO /LIBPATH:c:\Python25\libs \
|
||||
/LIBPATH:c:\Python25\PCBuild shell32.lib setupapi.lib /EXPORT:initwinutil \
|
||||
winutil.obj /OUT:winutil.pyd
|
||||
|
||||
|
||||
winutil.obj : winutil.c
|
||||
cl.exe /c /nologo /Ox /MD /W3 /GX /DNDEBUG -Ic:\Python25\include \
|
||||
-Ic:\Python25\PC -Ic:\WinDDK\6001.18001\inc\api /Tcwinutil.c /Fowinutil.obj
|
||||
|
||||
clean :
|
||||
del winutil.pyd winutil.obj winutil.exp winutil.lib
|
587
src/calibre/utils/windows/winutil.c
Normal file
587
src/calibre/utils/windows/winutil.c
Normal file
@ -0,0 +1,587 @@
|
||||
/*
|
||||
:mod:`winutil` -- Interface to Windows
|
||||
============================================
|
||||
|
||||
.. module:: winutil
|
||||
:platform: Windows
|
||||
:synopsis: Various methods to interface with the operating system
|
||||
|
||||
.. moduleauthor:: Kovid Goyal <kovid@kovidgoyal.net> Copyright 2008
|
||||
|
||||
This module contains utility functions to interface with the windows operating
|
||||
system. It should be compiled with the same version of VisualStudio used to
|
||||
compile python. It hasn't been tested with MinGW. We try to use unicode
|
||||
wherever possible in this module.
|
||||
|
||||
.. exception:: winutil.DriveError
|
||||
Raised when scanning for mounted volumes fails.
|
||||
|
||||
.. function:: is_usb_device_connected(vid : integer, pid : integer) -> bool
|
||||
Return `True` iff the USB device identified by the VendorID `vid` and
|
||||
ProductID `pid` is connected to the system.
|
||||
|
||||
.. function:: get_usb_devices() -> list of lowercase strings
|
||||
Return a list of all USB devices connected to the system. Each
|
||||
device is represented by a lowercase unicode string whoose format is
|
||||
the windows *Device Identifier* format. See the MSDN documentation.
|
||||
|
||||
.. function:: get_mounted_volumes_for_usb_device(vid : integer, pid : integer) -> dictionary
|
||||
Return a dictionary of the form `volume_id`:`drive_letter` for all
|
||||
volumes mounted from the device specified by `vid` and `pid`.
|
||||
|
||||
:raises: :exception:`winutil.DriveError` if scanning fails.
|
||||
|
||||
.. function:: special_folder_path(csidl_id) -> path
|
||||
Get paths to common system folders.
|
||||
See windows documentation of SHGetFolderPath.
|
||||
The paths are returned as unicode objects. `csidl_id` should be one
|
||||
of the symbolic constants defined in this module. You can also `OR`
|
||||
a symbolic constant with :data:`CSIDL_FLAG_CREATE` to force the operating
|
||||
system to create a folder if it does not exist. For example::
|
||||
|
||||
>>> from winutil import *
|
||||
>>> special_folder_path(CSIDL_APPDATA)
|
||||
u'C:\\Documents and Settings\\Kovid Goyal\\Application Data'
|
||||
>>> special_folder_path(CSIDL_PERSONAL)
|
||||
u'C:\\Documents and Settings\\Kovid Goyal\\My Documents'
|
||||
|
||||
.. function:: argv() -> list of unicode command line arguments
|
||||
Get command line arguments as unicode objects. Note that the
|
||||
first argument will be the path to the interpreter, *not* the
|
||||
script being run. So to replace sys.argv, you should use
|
||||
sys.argv[1:] = winutil.argv()[1:].
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#define UNICODE
|
||||
#include <Windows.h>
|
||||
#include <Python.h>
|
||||
#include <shlobj.h>
|
||||
#include <stdio.h>
|
||||
#include <setupapi.h>
|
||||
#include <devguid.h>
|
||||
#include <cfgmgr32.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#define BUFSIZE 512
|
||||
#define MAX_DRIVES 26
|
||||
static PyObject *DriveError;
|
||||
static BOOL DEBUG = FALSE;
|
||||
|
||||
//#define debug(fmt, ...) if DEBUG printf(x, __VA_ARGS__);
|
||||
void
|
||||
debug(const char *fmt, ...) {
|
||||
va_list argList;
|
||||
va_start(argList, fmt);
|
||||
if (DEBUG) vprintf(fmt, argList);
|
||||
va_end(argList);
|
||||
}
|
||||
|
||||
struct tagDrives
|
||||
{
|
||||
WCHAR letter;
|
||||
WCHAR volume[BUFSIZE];
|
||||
};
|
||||
|
||||
static PyObject *
|
||||
winutil_folder_path(PyObject *self, PyObject *args) {
|
||||
int res; DWORD dwFlags;
|
||||
PyObject *ans = NULL;
|
||||
TCHAR wbuf[MAX_PATH]; CHAR buf[4*MAX_PATH];
|
||||
memset(wbuf, 0, sizeof(TCHAR)*MAX_PATH); memset(buf, 0, sizeof(CHAR)*MAX_PATH);
|
||||
|
||||
if (!PyArg_ParseTuple(args, "l", &dwFlags)) return NULL;
|
||||
|
||||
res = SHGetFolderPath(NULL, dwFlags, NULL, 0, wbuf);
|
||||
if (res != S_OK) {
|
||||
if (res == E_FAIL) PyErr_SetString(PyExc_ValueError, "Folder does not exist.");
|
||||
PyErr_SetString(PyExc_ValueError, "Folder not valid");
|
||||
return NULL;
|
||||
}
|
||||
res = WideCharToMultiByte(CP_UTF8, 0, wbuf, -1, buf, 4*MAX_PATH, NULL, NULL);
|
||||
ans = PyUnicode_DecodeUTF8(buf, res-1, "strict");
|
||||
return ans;
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
winutil_argv(PyObject *self, PyObject *args) {
|
||||
PyObject *argv, *v;
|
||||
LPWSTR *_argv;
|
||||
LPSTR buf;
|
||||
int argc, i, bytes;
|
||||
if (!PyArg_ParseTuple(args, "")) return NULL;
|
||||
_argv = CommandLineToArgvW(GetCommandLine(), &argc);
|
||||
if (_argv == NULL) { PyErr_NoMemory(); return NULL; }
|
||||
argv = PyList_New(argc);
|
||||
if (argv != NULL) {
|
||||
for (i = 0; i < argc; i++) {
|
||||
bytes = WideCharToMultiByte(CP_UTF8, 0, _argv[i], -1, NULL, 0, NULL, NULL);
|
||||
buf = (LPSTR)PyMem_Malloc(sizeof(CHAR)*bytes);
|
||||
if (buf == NULL) { Py_DECREF(argv); argv = NULL; break; }
|
||||
WideCharToMultiByte(CP_UTF8, 0, _argv[i], -1, buf, bytes, NULL, NULL);
|
||||
v = PyUnicode_DecodeUTF8(buf, bytes-1, "strict");
|
||||
PyMem_Free(buf);
|
||||
if (v == NULL) { Py_DECREF(argv); argv = NULL; break; }
|
||||
PyList_SetItem(argv, i, v);
|
||||
}
|
||||
}
|
||||
LocalFree(_argv);
|
||||
return argv;
|
||||
}
|
||||
|
||||
static LPVOID
|
||||
format_last_error() {
|
||||
/* Format the last error as a string. The returned pointer should
|
||||
be freed with :cfunction:`LocalFree(lpMsgBuf)`. It can be printed with
|
||||
:cfunction:`printf("\n%ws\n", (LPCTSTR)lpMsgBuf)`.
|
||||
*/
|
||||
|
||||
LPVOID lpMsgBuf;
|
||||
FormatMessage(
|
||||
FORMAT_MESSAGE_ALLOCATE_BUFFER |
|
||||
FORMAT_MESSAGE_FROM_SYSTEM |
|
||||
FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||
NULL,
|
||||
GetLastError(),
|
||||
0, // Default language
|
||||
(LPTSTR) &lpMsgBuf,
|
||||
0,
|
||||
NULL
|
||||
);
|
||||
return lpMsgBuf;
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
winutil_set_debug(PyObject *self, PyObject *args) {
|
||||
PyObject *yes;
|
||||
if (!PyArg_ParseTuple(args, "O", &yes)) return NULL;
|
||||
DEBUG = (BOOL)PyObject_IsTrue(yes);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
static LPTSTR
|
||||
get_registry_property(HDEVINFO hDevInfo, DWORD index, DWORD property, BOOL *iterate) {
|
||||
/* Get a the property specified by `property` from the registry for the
|
||||
* device enumerated by `index` in the collection `hDevInfo`. `iterate`
|
||||
* will be set to `FALSE` if `index` points outside `hDevInfo`.
|
||||
* :return: A string allocated on the heap containing the property or
|
||||
* `NULL` if an error occurred.
|
||||
*/
|
||||
SP_DEVINFO_DATA DeviceInfoData;
|
||||
DWORD DataT;
|
||||
LPTSTR buffer = NULL;
|
||||
DWORD buffersize = 0;
|
||||
DeviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
|
||||
|
||||
if (!SetupDiEnumDeviceInfo(hDevInfo, index, &DeviceInfoData)) {
|
||||
*iterate = FALSE;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
while(!SetupDiGetDeviceRegistryProperty(
|
||||
hDevInfo,
|
||||
&DeviceInfoData,
|
||||
property,
|
||||
&DataT,
|
||||
(PBYTE)buffer,
|
||||
buffersize,
|
||||
&buffersize)) {
|
||||
if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
|
||||
buffer = (LPTSTR)PyMem_Malloc(2*buffersize); // Twice for bug in Win2k
|
||||
} else {
|
||||
PyMem_Free(buffer);
|
||||
PyErr_SetFromWindowsErr(0);
|
||||
buffer = NULL;
|
||||
break;
|
||||
}
|
||||
} //while
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
static BOOL
|
||||
check_device_id(LPTSTR buffer, unsigned int vid, unsigned int pid) {
|
||||
WCHAR xVid[9], dVid[9], xPid[9], dPid[9];
|
||||
unsigned int j;
|
||||
swprintf(xVid, L"vid_%4.4x", vid);
|
||||
swprintf(dVid, L"vid_%4.4d", vid);
|
||||
swprintf(xPid, L"pid_%4.4x", pid);
|
||||
swprintf(dPid, L"pid_%4.4d", pid);
|
||||
|
||||
for (j = 0; j < wcslen(buffer); j++) buffer[j] = tolower(buffer[j]);
|
||||
|
||||
return ( (wcsstr(buffer, xVid) != NULL || wcsstr(buffer, dVid) != NULL ) &&
|
||||
(wcsstr(buffer, xPid) != NULL || wcsstr(buffer, dPid) != NULL )
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
static HDEVINFO
|
||||
create_device_info_set(LPGUID guid, PCTSTR enumerator, HWND parent, DWORD flags) {
|
||||
HDEVINFO hDevInfo;
|
||||
hDevInfo = SetupDiGetClassDevs(
|
||||
guid,
|
||||
enumerator,
|
||||
parent,
|
||||
flags
|
||||
);
|
||||
if (hDevInfo == INVALID_HANDLE_VALUE) {
|
||||
PyErr_SetFromWindowsErr(0);
|
||||
}
|
||||
return hDevInfo;
|
||||
}
|
||||
|
||||
int n;
|
||||
|
||||
BOOL
|
||||
get_all_removable_disks(struct tagDrives *g_drives)
|
||||
{
|
||||
WCHAR caDrive[4];
|
||||
WCHAR volume[BUFSIZE];
|
||||
int nLoopIndex;
|
||||
DWORD dwDriveMask;
|
||||
unsigned int g_count=0;
|
||||
|
||||
|
||||
caDrive[0] = 'A';
|
||||
caDrive[1] = ':';
|
||||
caDrive[2] = '\\';
|
||||
caDrive[3] = 0;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// Get all drives in the system.
|
||||
dwDriveMask = GetLogicalDrives();
|
||||
|
||||
|
||||
if(dwDriveMask == 0)
|
||||
{
|
||||
PyErr_SetString(DriveError, "GetLogicalDrives failed");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
// Loop for all drives (MAX_DRIVES = 26)
|
||||
|
||||
|
||||
for(nLoopIndex = 0; nLoopIndex< MAX_DRIVES; nLoopIndex++)
|
||||
{
|
||||
// if a drive is present,
|
||||
if(dwDriveMask & 1)
|
||||
{
|
||||
caDrive[0] = 'A' + nLoopIndex;
|
||||
|
||||
|
||||
// If a drive is removable
|
||||
if(GetDriveType(caDrive) == DRIVE_REMOVABLE)
|
||||
{
|
||||
//Get its volume info and store it in the global variable.
|
||||
if(GetVolumeNameForVolumeMountPoint(caDrive, volume, BUFSIZE))
|
||||
{
|
||||
g_drives[g_count].letter = caDrive[0];
|
||||
wcscpy(g_drives[g_count].volume, volume);
|
||||
g_count ++;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
dwDriveMask >>= 1;
|
||||
}
|
||||
|
||||
|
||||
// success if atleast one removable drive is found.
|
||||
if(g_count == 0)
|
||||
{
|
||||
PyErr_SetString(DriveError, "No removable drives found");
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
|
||||
}
|
||||
|
||||
PSP_DEVICE_INTERFACE_DETAIL_DATA
|
||||
get_device_grandparent(HDEVINFO hDevInfo, DWORD index, PWSTR buf, PWSTR volume_id,
|
||||
BOOL *iterate) {
|
||||
SP_DEVICE_INTERFACE_DATA interfaceData;
|
||||
SP_DEVINFO_DATA devInfoData;
|
||||
BOOL status;
|
||||
PSP_DEVICE_INTERFACE_DETAIL_DATA interfaceDetailData;
|
||||
DWORD interfaceDetailDataSize,
|
||||
reqSize;
|
||||
DEVINST parent;
|
||||
|
||||
interfaceData.cbSize = sizeof (SP_INTERFACE_DEVICE_DATA);
|
||||
devInfoData.cbSize = sizeof (SP_DEVINFO_DATA);
|
||||
|
||||
status = SetupDiEnumDeviceInterfaces (
|
||||
hDevInfo, // Interface Device Info handle
|
||||
NULL, // Device Info data
|
||||
(LPGUID)&GUID_DEVINTERFACE_VOLUME, // Interface registered by driver
|
||||
index, // Member
|
||||
&interfaceData // Device Interface Data
|
||||
);
|
||||
if ( status == FALSE ) {
|
||||
*iterate = FALSE;
|
||||
return NULL;
|
||||
}
|
||||
SetupDiGetDeviceInterfaceDetail (
|
||||
hDevInfo, // Interface Device info handle
|
||||
&interfaceData, // Interface data for the event class
|
||||
NULL, // Checking for buffer size
|
||||
0, // Checking for buffer size
|
||||
&reqSize, // Buffer size required to get the detail data
|
||||
NULL // Checking for buffer size
|
||||
);
|
||||
|
||||
interfaceDetailDataSize = reqSize;
|
||||
interfaceDetailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA)PyMem_Malloc(interfaceDetailDataSize+10);
|
||||
if ( interfaceDetailData == NULL ) {
|
||||
PyErr_NoMemory();
|
||||
return NULL;
|
||||
}
|
||||
interfaceDetailData->cbSize = sizeof (SP_INTERFACE_DEVICE_DETAIL_DATA);
|
||||
|
||||
status = SetupDiGetDeviceInterfaceDetail (
|
||||
hDevInfo, // Interface Device info handle
|
||||
&interfaceData, // Interface data for the event class
|
||||
interfaceDetailData, // Interface detail data
|
||||
interfaceDetailDataSize, // Interface detail data size
|
||||
&reqSize, // Buffer size required to get the detail data
|
||||
&devInfoData); // Interface device info
|
||||
|
||||
if ( status == FALSE ) {PyErr_SetFromWindowsErr(0); PyMem_Free(interfaceDetailData); return NULL;}
|
||||
|
||||
// Get the device instance of parent. This points to USBSTOR.
|
||||
CM_Get_Parent(&parent, devInfoData.DevInst, 0);
|
||||
// Get the device ID of the USBSTORAGE volume
|
||||
CM_Get_Device_ID(parent, volume_id, BUFSIZE, 0);
|
||||
// Get the device instance of grand parent. This points to USB root.
|
||||
CM_Get_Parent(&parent, parent, 0);
|
||||
// Get the device ID of the USB root.
|
||||
CM_Get_Device_ID(parent, buf, BUFSIZE, 0);
|
||||
|
||||
return interfaceDetailData;
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
winutil_get_mounted_volumes_for_usb_device(PyObject *self, PyObject *args) {
|
||||
unsigned int vid, pid, length, j;
|
||||
HDEVINFO hDevInfo;
|
||||
BOOL iterate = TRUE;
|
||||
PSP_DEVICE_INTERFACE_DETAIL_DATA interfaceDetailData;
|
||||
DWORD i;
|
||||
WCHAR buf[BUFSIZE], volume[BUFSIZE], volume_id[BUFSIZE];
|
||||
struct tagDrives g_drives[MAX_DRIVES];
|
||||
PyObject *volumes, *key, *val;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "ii", &vid, &pid)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
volumes = PyDict_New();
|
||||
if (volumes == NULL) return NULL;
|
||||
|
||||
for (j = 0; j < MAX_DRIVES; j++) g_drives[j].letter = 0;
|
||||
|
||||
// Find all removable drives
|
||||
if (!get_all_removable_disks(g_drives)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
hDevInfo = create_device_info_set((LPGUID)&GUID_DEVINTERFACE_VOLUME,
|
||||
NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
|
||||
if (hDevInfo == INVALID_HANDLE_VALUE) return NULL;
|
||||
|
||||
// Enumerate through the set
|
||||
for (i=0; iterate; i++) {
|
||||
interfaceDetailData = get_device_grandparent(hDevInfo, i, buf, volume_id, &iterate);
|
||||
if (interfaceDetailData == NULL) {
|
||||
PyErr_Print(); continue;
|
||||
}
|
||||
debug("Device num: %d Device Id: %ws\n\n", i, buf);
|
||||
if (check_device_id(buf, vid, pid)) {
|
||||
debug("Device matches\n\n");
|
||||
length = wcslen(interfaceDetailData->DevicePath);
|
||||
interfaceDetailData->DevicePath[length] = '\\';
|
||||
interfaceDetailData->DevicePath[length+1] = 0;
|
||||
if(GetVolumeNameForVolumeMountPoint(interfaceDetailData->DevicePath, volume, BUFSIZE)) {
|
||||
|
||||
for(j = 0; j < MAX_DRIVES; j++) {
|
||||
// Compare volume mount point with the one stored earlier.
|
||||
// If both match, return the corresponding drive letter.
|
||||
if(g_drives[j].letter != 0 && wcscmp(g_drives[j].volume, volume)==0)
|
||||
{
|
||||
key = PyUnicode_FromWideChar(volume_id, wcslen(volume_id));
|
||||
val = PyString_FromFormat("%c", (char)g_drives[j].letter);
|
||||
if (key == NULL || val == NULL) {
|
||||
PyErr_NoMemory();
|
||||
PyMem_Free(interfaceDetailData);
|
||||
return NULL;
|
||||
}
|
||||
PyDict_SetItem(volumes, key, val);
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
debug("Failed to get volume name for volume mount point:\n");
|
||||
if (DEBUG) debug("%ws\n\n", format_last_error());
|
||||
}
|
||||
|
||||
PyMem_Free(interfaceDetailData);
|
||||
}
|
||||
|
||||
} //for
|
||||
|
||||
SetupDiDestroyDeviceInfoList(hDevInfo);
|
||||
return volumes;
|
||||
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
winutil_get_usb_devices(PyObject *self, PyObject *args) {
|
||||
unsigned int j, buffersize;
|
||||
HDEVINFO hDevInfo;
|
||||
DWORD i; BOOL iterate = TRUE;
|
||||
PyObject *devices, *temp = (PyObject *)1;
|
||||
LPTSTR buffer;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "")) return NULL;
|
||||
|
||||
devices = PyList_New(0);
|
||||
if (devices == NULL) {PyErr_NoMemory(); return NULL;}
|
||||
|
||||
// Create a Device information set with all USB devices
|
||||
hDevInfo = create_device_info_set(NULL, L"USB", 0,
|
||||
DIGCF_PRESENT | DIGCF_ALLCLASSES);
|
||||
if (hDevInfo == INVALID_HANDLE_VALUE)
|
||||
return NULL;
|
||||
// Enumerate through the set
|
||||
for (i=0; iterate; i++) {
|
||||
buffer = get_registry_property(hDevInfo, i, SPDRP_HARDWAREID, &iterate);
|
||||
if (buffer == NULL) {
|
||||
PyErr_Print(); continue;
|
||||
}
|
||||
buffersize = wcslen(buffer);
|
||||
for (j = 0; j < buffersize; j++) buffer[j] = tolower(buffer[j]);
|
||||
temp = PyUnicode_FromWideChar(buffer, buffersize);
|
||||
PyMem_Free(buffer);
|
||||
if (temp == NULL) {
|
||||
PyErr_NoMemory();
|
||||
break;
|
||||
}
|
||||
PyList_Append(devices, temp);
|
||||
} //for
|
||||
if (temp == NULL) { Py_DECREF(devices); devices = NULL; }
|
||||
SetupDiDestroyDeviceInfoList(hDevInfo);
|
||||
return devices;
|
||||
}
|
||||
|
||||
|
||||
static PyObject *
|
||||
winutil_is_usb_device_connected(PyObject *self, PyObject *args) {
|
||||
unsigned int vid, pid;
|
||||
HDEVINFO hDevInfo;
|
||||
DWORD i; BOOL iterate = TRUE;
|
||||
LPTSTR buffer;
|
||||
int found = FALSE;
|
||||
PyObject *ans;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "ii", &vid, &pid)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Create a Device information set with all USB devices
|
||||
hDevInfo = create_device_info_set(NULL, L"USB", 0,
|
||||
DIGCF_PRESENT | DIGCF_ALLCLASSES);
|
||||
if (hDevInfo == INVALID_HANDLE_VALUE)
|
||||
return NULL;
|
||||
|
||||
// Enumerate through the set
|
||||
for (i=0; iterate && !found; i++) {
|
||||
buffer = get_registry_property(hDevInfo, i, SPDRP_HARDWAREID, &iterate);
|
||||
if (buffer == NULL) {
|
||||
PyErr_Print(); continue;
|
||||
}
|
||||
found = check_device_id(buffer, vid, pid);
|
||||
PyMem_Free(buffer);
|
||||
} // for
|
||||
|
||||
SetupDiDestroyDeviceInfoList(hDevInfo);
|
||||
ans = (found) ? Py_True : Py_False;
|
||||
Py_INCREF(ans);
|
||||
return ans;
|
||||
}
|
||||
|
||||
|
||||
static PyMethodDef WinutilMethods[] = {
|
||||
{"special_folder_path", winutil_folder_path, METH_VARARGS,
|
||||
"special_folder_path(csidl_id) -> path\n\n"
|
||||
"Get paths to common system folders. "
|
||||
"See windows documentation of SHGetFolderPath. "
|
||||
"The paths are returned as unicode objects. csidl_id should be one "
|
||||
"of the symbolic constants defined in this module. You can also OR "
|
||||
"a symbolic constant with CSIDL_FLAG_CREATE to force the operating "
|
||||
"system to create a folder if it does not exist."},
|
||||
|
||||
{"argv", winutil_argv, METH_VARARGS,
|
||||
"argv() -> list of command line arguments\n\n"
|
||||
"Get command line arguments as unicode objects. Note that the "
|
||||
"first argument will be the path to the interpreter, *not* the "
|
||||
"script being run. So to replace sys.argv, you should use "
|
||||
"sys.argv[1:] = argv()[1:]."},
|
||||
|
||||
{"is_usb_device_connected", winutil_is_usb_device_connected, METH_VARARGS,
|
||||
"is_usb_device_connected(vid, pid) -> bool\n\n"
|
||||
"Check if the USB device identified by VendorID: vid (integer) and"
|
||||
" ProductID: pid (integer) is currently connected."},
|
||||
|
||||
{"get_usb_devices", winutil_get_usb_devices, METH_VARARGS,
|
||||
"get_usb_devices() -> list of strings\n\n"
|
||||
"Return a list of the hardware IDs of all USB devices "
|
||||
"connected to the system."},
|
||||
|
||||
{"get_mounted_volumes_for_usb_device", winutil_get_mounted_volumes_for_usb_device, METH_VARARGS,
|
||||
"get_mounted_volumes_for_usb_device(vid, pid) -> dict\n\n"
|
||||
"Return a dictionary of volume_id:drive_letter for all"
|
||||
"volumes mounted on the system that belong to the"
|
||||
"usb device specified by vid (integer) and pid (integer)."},
|
||||
|
||||
{"set_debug", winutil_set_debug, METH_VARARGS,
|
||||
"set_debug(bool)\n\nSet debugging mode."
|
||||
},
|
||||
|
||||
{NULL, NULL, 0, NULL}
|
||||
};
|
||||
|
||||
PyMODINIT_FUNC
|
||||
initwinutil(void) {
|
||||
PyObject *m;
|
||||
m = Py_InitModule3("winutil", WinutilMethods,
|
||||
"Defines utility methods to interface with windows."
|
||||
);
|
||||
if (m == NULL) return;
|
||||
DriveError = PyErr_NewException("winutil.DriveError", NULL, NULL);
|
||||
|
||||
PyModule_AddIntConstant(m, "CSIDL_ADMINTOOLS", CSIDL_ADMINTOOLS);
|
||||
PyModule_AddIntConstant(m, "CSIDL_APPDATA", CSIDL_APPDATA);
|
||||
PyModule_AddIntConstant(m, "CSIDL_COMMON_ADMINTOOLS", CSIDL_COMMON_ADMINTOOLS);
|
||||
PyModule_AddIntConstant(m, "CSIDL_COMMON_APPDATA", CSIDL_COMMON_APPDATA);
|
||||
PyModule_AddIntConstant(m, "CSIDL_COMMON_DOCUMENTS", CSIDL_COMMON_DOCUMENTS);
|
||||
PyModule_AddIntConstant(m, "CSIDL_COOKIES", CSIDL_COOKIES);
|
||||
PyModule_AddIntConstant(m, "CSIDL_FLAG_CREATE", CSIDL_FLAG_CREATE);
|
||||
PyModule_AddIntConstant(m, "CSIDL_FLAG_DONT_VERIFY", CSIDL_FLAG_DONT_VERIFY);
|
||||
PyModule_AddIntConstant(m, "CSIDL_HISTORY", CSIDL_HISTORY);
|
||||
PyModule_AddIntConstant(m, "CSIDL_INTERNET_CACHE", CSIDL_INTERNET_CACHE);
|
||||
PyModule_AddIntConstant(m, "CSIDL_LOCAL_APPDATA", CSIDL_LOCAL_APPDATA);
|
||||
PyModule_AddIntConstant(m, "CSIDL_MYPICTURES", CSIDL_MYPICTURES);
|
||||
PyModule_AddIntConstant(m, "CSIDL_PERSONAL", CSIDL_PERSONAL);
|
||||
PyModule_AddIntConstant(m, "CSIDL_PROGRAM_FILES", CSIDL_PROGRAM_FILES);
|
||||
PyModule_AddIntConstant(m, "CSIDL_PROGRAM_FILES_COMMON", CSIDL_PROGRAM_FILES_COMMON);
|
||||
PyModule_AddIntConstant(m, "CSIDL_SYSTEM", CSIDL_SYSTEM);
|
||||
PyModule_AddIntConstant(m, "CSIDL_WINDOWS", CSIDL_WINDOWS);
|
||||
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -60,35 +60,15 @@ If you specify this option, any argument to %prog is ignored and a default recip
|
||||
|
||||
return p
|
||||
|
||||
def simple_progress_bar(percent, msg):
|
||||
if isinstance(msg, unicode):
|
||||
msg = msg.encode('utf-8', 'ignore')
|
||||
if not msg:
|
||||
print '%d%%'%(percent*100),
|
||||
else:
|
||||
print '%d%%'%(percent*100), msg
|
||||
sys.stdout.flush()
|
||||
|
||||
def no_progress_bar(percent, msg):
|
||||
print msg
|
||||
|
||||
class RecipeError(Exception):
|
||||
pass
|
||||
|
||||
def run_recipe(opts, recipe_arg, parser, notification=None, handler=None):
|
||||
if notification is None:
|
||||
from calibre.terminfo import TerminalController, ProgressBar
|
||||
from calibre.utils.terminfo import TerminalController, ProgressBar
|
||||
term = TerminalController(sys.stdout)
|
||||
if opts.progress_bar:
|
||||
try:
|
||||
pb = ProgressBar(term, _('Fetching feeds...'))
|
||||
pb = ProgressBar(term, _('Fetching feeds...'), no_progress_bar=opts.progress_bar)
|
||||
notification = pb.update
|
||||
except ValueError:
|
||||
notification = simple_progress_bar
|
||||
print _('Fetching feeds...')
|
||||
else:
|
||||
notification = no_progress_bar
|
||||
|
||||
|
||||
recipe, is_profile = None, False
|
||||
if opts.feeds is not None:
|
||||
|
@ -20,7 +20,7 @@ from calibre.ebooks.metadata import MetaInformation
|
||||
from calibre.web.feeds import feed_from_xml, templates, feeds_from_index
|
||||
from calibre.web.fetch.simple import option_parser as web2disk_option_parser
|
||||
from calibre.web.fetch.simple import RecursiveFetcher
|
||||
from calibre.threadpool import WorkRequest, ThreadPool, NoResultsPending
|
||||
from calibre.utils.threadpool import WorkRequest, ThreadPool, NoResultsPending
|
||||
from calibre.ebooks.lrf.web.profiles import FullContentProfile
|
||||
from calibre.ptempfile import PersistentTemporaryFile
|
||||
|
||||
|
29
upload.py
29
upload.py
@ -29,10 +29,10 @@ BUILD_SCRIPT ='''\
|
||||
#!/bin/bash
|
||||
cd ~/build && \
|
||||
rsync -avz --exclude src/calibre/plugins --exclude docs --exclude .bzr --exclude .build --exclude build --exclude dist --exclude "*.pyc" --exclude "*.pyo" rsync://%(host)s/work/%(project)s . && \
|
||||
cd %(project)s && \
|
||||
cd %(project)s && rm -rf build dist src/calibre/plugins && \
|
||||
mkdir -p build dist src/calibre/plugins && \
|
||||
%%s && \
|
||||
rm -rf build/* dist/* && \
|
||||
rm -rf build/* && \
|
||||
%%s %%s
|
||||
'''%dict(host=HOST, project=PROJECT)
|
||||
check_call = partial(_check_call, shell=True)
|
||||
@ -63,6 +63,15 @@ def start_vm(vm, ssh_host, build_script, sleep=75):
|
||||
subprocess.check_call(('scp', t.name, ssh_host+':build-'+PROJECT))
|
||||
subprocess.check_call('ssh -t %s bash build-%s'%(ssh_host, PROJECT), shell=True)
|
||||
|
||||
def run_windows_install_jammer(installer):
|
||||
ibp = os.path.abspath('installer/windows')
|
||||
sys.path.insert(0, ibp)
|
||||
import build_installer
|
||||
sys.path.remove(ibp)
|
||||
build_installer.run_install_jammer(installer_name=os.path.basename(installer))
|
||||
if not os.path.exists(installer):
|
||||
raise Exception('Failed to run installjammer')
|
||||
|
||||
def build_windows(shutdown=True):
|
||||
installer = installer_name('exe')
|
||||
vm = '/vmware/Windows XP/Windows XP Professional.vmx'
|
||||
@ -72,20 +81,14 @@ def build_windows(shutdown=True):
|
||||
raise Exception('Failed to run py2exe')
|
||||
if shutdown:
|
||||
subprocess.Popen(('ssh', 'windows', 'shutdown', '-s', '-t', '0'))
|
||||
ibp = os.path.abspath('installer/windows')
|
||||
sys.path.insert(0, ibp)
|
||||
import build_installer
|
||||
sys.path.remove(ibp)
|
||||
build_installer.run_install_jammer(installer_name=os.path.basename(installer))
|
||||
if not os.path.exists(installer):
|
||||
raise Exception('Failed to run installjammer')
|
||||
run_windows_install_jammer(installer)
|
||||
return os.path.basename(installer)
|
||||
|
||||
def build_osx(shutdown=True):
|
||||
installer = installer_name('dmg')
|
||||
vm = '/vmware/Mac OSX/Mac OSX.vmx'
|
||||
python = '/Library/Frameworks/Python.framework/Versions/Current/bin/python'
|
||||
start_vm(vm, 'osx', BUILD_SCRIPT%('sudo %s setup.py develop'%python, python, 'osx_installer.py'))
|
||||
start_vm(vm, 'osx', (BUILD_SCRIPT%('sudo %s setup.py develop'%python, python, 'installer/osx/freeze.py')).replace('rm ', 'sudo rm '))
|
||||
subprocess.check_call(('scp', 'osx:build/%s/dist/*.dmg'%PROJECT, 'dist'))
|
||||
if not os.path.exists(installer):
|
||||
raise Exception('Failed to build installer '+installer)
|
||||
@ -97,7 +100,7 @@ def build_osx(shutdown=True):
|
||||
def build_linux(shutdown=True):
|
||||
installer = installer_name('tar.bz2')
|
||||
vm = '/vmware/linux/libprs500-gentoo.vmx'
|
||||
start_vm(vm, 'linux', BUILD_SCRIPT%('sudo python setup.py develop', 'python','linux_installer.py'))
|
||||
start_vm(vm, 'linux', (BUILD_SCRIPT%('sudo python setup.py develop', 'python','installer/linux/freeze.py')).replace('rm ', 'sudo rm '))
|
||||
subprocess.check_call(('scp', 'linux:/tmp/%s'%os.path.basename(installer), 'dist'))
|
||||
if not os.path.exists(installer):
|
||||
raise Exception('Failed to build installer '+installer)
|
||||
@ -218,8 +221,8 @@ def stage_one():
|
||||
os.mkdir('build')
|
||||
shutil.rmtree('docs')
|
||||
os.mkdir('docs')
|
||||
check_call("sudo python setup.py develop", shell=True)
|
||||
check_call('sudo rm src/%s/gui2/images_rc.pyc'%__appname__, shell=True)
|
||||
check_call(['python', 'setup.py', 'build'])
|
||||
check_call('sudo rm -f src/%s/gui2/images_rc.pyc'%__appname__, shell=True)
|
||||
check_call('make', shell=True)
|
||||
tag_release()
|
||||
upload_demo()
|
||||
|
Loading…
x
Reference in New Issue
Block a user