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/gui2/pictureflow/release/
|
||||||
src/calibre/translations/compiled.py
|
src/calibre/translations/compiled.py
|
||||||
installer/windows/calibre/build.log
|
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
|
PYTHON = python
|
||||||
|
|
||||||
all : plugins gui2 translations resources
|
all : gui2 translations resources
|
||||||
|
|
||||||
plugins : src/calibre/plugins pictureflow lzx
|
|
||||||
|
|
||||||
src/calibre/plugins:
|
|
||||||
mkdir -p src/calibre/plugins
|
|
||||||
|
|
||||||
clean :
|
clean :
|
||||||
cd src/calibre/gui2 && ${PYTHON} make.py clean
|
cd src/calibre/gui2 && ${PYTHON} make.py clean
|
||||||
@ -25,26 +20,6 @@ resources:
|
|||||||
manual:
|
manual:
|
||||||
make -C src/calibre/manual clean html
|
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 :
|
pot :
|
||||||
cd src/calibre/translations && ${PYTHON} __init__.py pot
|
cd src/calibre/translations && ${PYTHON} __init__.py pot
|
||||||
|
|
||||||
|
@ -6,7 +6,7 @@ __docformat__ = 'restructuredtext en'
|
|||||||
'''
|
'''
|
||||||
Create linux binary.
|
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'
|
HOME = '/home/kovid'
|
||||||
PYINSTALLER = os.path.expanduser('~/build/pyinstaller')
|
PYINSTALLER = os.path.expanduser('~/build/pyinstaller')
|
||||||
CALIBREPREFIX = '___'
|
CALIBREPREFIX = '___'
|
||||||
@ -16,6 +16,9 @@ LIBUNRAR = '/usr/lib/libunrar.so'
|
|||||||
QTDIR = '/usr/lib/qt4'
|
QTDIR = '/usr/lib/qt4'
|
||||||
QTDLLS = ('QtCore', 'QtGui', 'QtNetwork', 'QtSvg', 'QtXml')
|
QTDLLS = ('QtCore', 'QtGui', 'QtNetwork', 'QtSvg', 'QtXml')
|
||||||
EXTRAS = ('/usr/lib/python2.5/site-packages/PIL', os.path.expanduser('~/ipython/IPython'))
|
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')
|
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):
|
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(('/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('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())
|
cp = HOME+'/build/'+os.path.basename(os.getcwd())
|
||||||
spec = open(os.path.join(PYINSTALLER, 'calibre', 'calibre.spec'), 'wb')
|
spec = open(os.path.join(PYINSTALLER, 'calibre', 'calibre.spec'), 'wb')
|
||||||
raw = re.sub(r'CALIBREPREFIX\s+=\s+\'___\'', 'CALIBREPREFIX = '+repr(cp),
|
raw = re.sub(r'CALIBREPREFIX\s+=\s+\'___\'', 'CALIBREPREFIX = '+repr(cp),
|
||||||
@ -41,12 +43,14 @@ def run_pyinstaller(args=sys.argv):
|
|||||||
spec.write(raw)
|
spec.write(raw)
|
||||||
spec.close()
|
spec.close()
|
||||||
os.chdir(PYINSTALLER)
|
os.chdir(PYINSTALLER)
|
||||||
|
shutil.rmtree('calibre/dist')
|
||||||
|
os.mkdir('calibre/dist')
|
||||||
subprocess.check_call('python -OO Build.py calibre/calibre.spec', shell=True)
|
subprocess.check_call('python -OO Build.py calibre/calibre.spec', shell=True)
|
||||||
|
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__' and 'linux_installer.py' in __file__:
|
if __name__ == '__main__' and 'freeze.py' in __file__:
|
||||||
sys.exit(run_pyinstaller())
|
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, os.path.join(sys.frozen_path, "library.pyz"))
|
||||||
sys.path.insert(0, sys.frozen_path)
|
sys.path.insert(0, sys.frozen_path)
|
||||||
from PyQt4.QtCore import QCoreApplication
|
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',
|
excludes = ['gtk._gtk', 'gtk.glade', 'qt', 'matplotlib.nxutils', 'matplotlib._cntr',
|
||||||
'matplotlib.ttconv', 'matplotlib._image', 'matplotlib.ft2font',
|
'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')
|
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],
|
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()
|
pyz = TOC()
|
||||||
binaries = TOC()
|
binaries = TOC()
|
||||||
@ -104,11 +108,18 @@ for script, exe, a in zip(scripts, executables, analyses):
|
|||||||
|
|
||||||
print 'Adding plugins...'
|
print 'Adding plugins...'
|
||||||
for f in glob.glob(os.path.join(CALIBREPLUGINS, '*.so')):
|
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')]
|
binaries += [(os.path.basename(f), f, 'BINARY')]
|
||||||
|
|
||||||
print 'Adding external programs...'
|
print 'Adding external programs...'
|
||||||
binaries += [('clit', CLIT, 'BINARY'), ('pdftohtml', PDFTOHTML, 'BINARY'),
|
binaries += [('clit', CLIT, 'BINARY'), ('pdftohtml', PDFTOHTML, 'BINARY'),
|
||||||
('libunrar.so', LIBUNRAR, 'BINARY')]
|
('libunrar.so', LIBUNRAR, 'BINARY')]
|
||||||
|
|
||||||
|
print 'Adding external libraries...'
|
||||||
|
binaries += [ (os.path.basename(x), x, 'BINARY') for x in (SQLITE, DBUS, LIBMNG)]
|
||||||
|
|
||||||
|
|
||||||
qt = []
|
qt = []
|
||||||
for dll in QTDLLS:
|
for dll in QTDLLS:
|
||||||
path = os.path.join(QTDIR, 'lib'+dll+'.so.4')
|
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:
|
for f in filenames:
|
||||||
if not f.endswith('.so') or 'designer' in dirpath or 'codcs' in dirpath or 'sqldrivers' in dirpath : continue
|
if not f.endswith('.so') or 'designer' in dirpath or 'codcs' in dirpath or 'sqldrivers' in dirpath : continue
|
||||||
f = os.path.join(dirpath, f)
|
f = os.path.join(dirpath, f)
|
||||||
plugins.append(('plugins/'+f.replace(plugdir, ''), f, 'BINARY'))
|
plugins.append(('qtplugins/'+f.replace(plugdir, ''), f, 'BINARY'))
|
||||||
binaries += plugins
|
binaries += plugins
|
||||||
|
|
||||||
manifest = '/tmp/manifest'
|
manifest = '/tmp/manifest'
|
@ -4,7 +4,14 @@ __copyright__ = '2008, Kovid Goyal <kovid at kovidgoyal.net>'
|
|||||||
''' Create an OSX installer '''
|
''' Create an OSX installer '''
|
||||||
|
|
||||||
import sys, re, os, shutil, subprocess, stat, glob, zipfile
|
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 setuptools import setup
|
||||||
from py2app.build_app import py2app
|
from py2app.build_app import py2app
|
||||||
from modulegraph.find_modules import find_modules
|
from modulegraph.find_modules import find_modules
|
||||||
@ -38,8 +45,10 @@ print >>loader, 'from %(module)s import %(function)s'
|
|||||||
print >>loader, '%(function)s()'
|
print >>loader, '%(function)s()'
|
||||||
loader.close()
|
loader.close()
|
||||||
os.chmod(loader_path, 0700)
|
os.chmod(loader_path, 0700)
|
||||||
os.environ['PYTHONHOME'] = resources_dir
|
os.environ['PYTHONHOME'] = resources_dir
|
||||||
os.environ['FC_CONFIG_DIR'] = os.path.join(resources_dir, 'fonts')
|
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)
|
os.execv(loader_path, sys.argv)
|
||||||
'''
|
'''
|
||||||
CHECK_SYMLINKS_PRESCRIPT = \
|
CHECK_SYMLINKS_PRESCRIPT = \
|
||||||
@ -170,64 +179,46 @@ _check_symlinks_prescript()
|
|||||||
for f in files:
|
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])
|
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):
|
def add_plugins(self):
|
||||||
plugins = [
|
self.add_qt_plugins()
|
||||||
('lzx', os.path.join('utils', 'lzx')),
|
frameworks_dir = os.path.join(self.dist_dir, APPNAME + '.app', 'Contents', 'Frameworks')
|
||||||
]
|
plugins_dir = os.path.join(frameworks_dir, 'plugins')
|
||||||
files = []
|
if not os.path.exists(plugins_dir):
|
||||||
env = {'PATH':os.environ['PATH']}
|
os.mkdir(plugins_dir)
|
||||||
for name, path in plugins:
|
|
||||||
print 'Building plugin', name
|
maps = {}
|
||||||
path = os.path.abspath(os.path.join('src', 'calibre', path))
|
for f in glob.glob('src/calibre/plugins/*'):
|
||||||
cwd = os.getcwd()
|
tgt = plugins_dir
|
||||||
os.chdir(path)
|
if f.endswith('.dylib'):
|
||||||
try:
|
tgt = frameworks_dir
|
||||||
if os.path.exists('.build'):
|
maps[f] = os.path.join(tgt, os.path.basename(f))
|
||||||
shutil.rmtree('.build')
|
deps = []
|
||||||
subprocess.check_call((sys.executable, 'setup.py', 'build', '--build-base', '.build'),
|
for src, dst in maps.items():
|
||||||
env=env)
|
shutil.copyfile(src, dst)
|
||||||
plugin = os.path.abspath(glob.glob('.build/lib*/%s.so'%name)[0])
|
self.fix_qt_dependencies(dst, self.qt_dependencies(dst))
|
||||||
files.append([plugin, os.path.basename(plugin)])
|
deps.append(dst)
|
||||||
finally:
|
self.fix_python_dependencies(deps)
|
||||||
os.chdir(cwd)
|
self.fix_misc_dependencies(deps)
|
||||||
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)
|
|
||||||
|
|
||||||
return files
|
|
||||||
finally:
|
|
||||||
os.chdir(cwd)
|
|
||||||
|
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
plugin_files = self.build_distutils_plugins()
|
|
||||||
py2app.run(self)
|
py2app.run(self)
|
||||||
resource_dir = os.path.join(self.dist_dir,
|
resource_dir = os.path.join(self.dist_dir,
|
||||||
APPNAME + '.app', 'Contents', 'Resources')
|
APPNAME + '.app', 'Contents', 'Resources')
|
||||||
@ -249,8 +240,8 @@ _check_symlinks_prescript()
|
|||||||
f.close()
|
f.close()
|
||||||
os.chmod(path, stat.S_IXUSR|stat.S_IXGRP|stat.S_IXOTH|stat.S_IREAD\
|
os.chmod(path, stat.S_IXUSR|stat.S_IXGRP|stat.S_IXOTH|stat.S_IREAD\
|
||||||
|stat.S_IWUSR|stat.S_IROTH|stat.S_IRGRP)
|
|stat.S_IWUSR|stat.S_IROTH|stat.S_IRGRP)
|
||||||
self.add_qt_plugins()
|
self.add_plugins()
|
||||||
plugin_files += self.build_plugins()
|
|
||||||
|
|
||||||
print
|
print
|
||||||
print 'Adding clit'
|
print 'Adding clit'
|
||||||
@ -264,13 +255,8 @@ _check_symlinks_prescript()
|
|||||||
print 'Adding plugins'
|
print 'Adding plugins'
|
||||||
module_dir = os.path.join(resource_dir, 'lib', 'python2.5', 'lib-dynload')
|
module_dir = os.path.join(resource_dir, 'lib', 'python2.5', 'lib-dynload')
|
||||||
print 'Adding fontconfig'
|
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)))
|
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')
|
dst = os.path.join(resource_dir, 'fonts')
|
||||||
if os.path.exists(dst):
|
if os.path.exists(dst):
|
||||||
shutil.rmtree(dst)
|
shutil.rmtree(dst)
|
||||||
@ -281,6 +267,15 @@ _check_symlinks_prescript()
|
|||||||
dst = os.path.join(resource_dir, 'lib', 'python2.5', 'IPython')
|
dst = os.path.join(resource_dir, 'lib', 'python2.5', 'IPython')
|
||||||
if os.path.exists(dst): shutil.rmtree(dst)
|
if os.path.exists(dst): shutil.rmtree(dst)
|
||||||
shutil.copytree(os.path.expanduser('~/build/ipython/IPython'), 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
|
||||||
print 'Installing prescipt'
|
print 'Installing prescipt'
|
||||||
sf = [os.path.basename(s) for s in all_names]
|
sf = [os.path.basename(s) for s in all_names]
|
||||||
@ -341,6 +336,8 @@ def main():
|
|||||||
'NSHumanReadableCopyright':'Copyright 2008, Kovid Goyal',
|
'NSHumanReadableCopyright':'Copyright 2008, Kovid Goyal',
|
||||||
'LSEnvironment':{
|
'LSEnvironment':{
|
||||||
'FC_CONFIG_DIR':'@executable_path/../Resources/fonts',
|
'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 ::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 ::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 ::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 ::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 ::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
|
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 ::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 ::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 ::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 ::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 ::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
|
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 ::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 ::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 ::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
|
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
|
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>
|
</trustInfo>
|
||||||
</assembly>
|
</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):
|
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)
|
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
|
qtsvgdll = None
|
||||||
for other in self.other_depends:
|
for other in self.other_depends:
|
||||||
if 'qtsvg4.dll' in other.lower():
|
if 'qtsvg4.dll' in other.lower():
|
||||||
@ -116,7 +74,7 @@ class BuildEXE(py2exe.build_exe.py2exe):
|
|||||||
print 'Adding', qtxmldll
|
print 'Adding', qtxmldll
|
||||||
shutil.copyfile(qtxmldll,
|
shutil.copyfile(qtxmldll,
|
||||||
os.path.join(self.dist_dir, os.path.basename(qtxmldll)))
|
os.path.join(self.dist_dir, os.path.basename(qtxmldll)))
|
||||||
print 'Adding plugins...',
|
print 'Adding Qt plugins...',
|
||||||
qt_prefix = QT_DIR
|
qt_prefix = QT_DIR
|
||||||
if qtsvgdll:
|
if qtsvgdll:
|
||||||
qt_prefix = os.path.dirname(os.path.dirname(qtsvgdll))
|
qt_prefix = os.path.dirname(os.path.dirname(qtsvgdll))
|
||||||
@ -152,7 +110,8 @@ class BuildEXE(py2exe.build_exe.py2exe):
|
|||||||
print '\tAdding pdftohtml'
|
print '\tAdding pdftohtml'
|
||||||
shutil.copyfile(PDFTOHTML, os.path.join(PY2EXE_DIR, os.path.basename(PDFTOHTML)))
|
shutil.copyfile(PDFTOHTML, os.path.join(PY2EXE_DIR, os.path.basename(PDFTOHTML)))
|
||||||
print '\tAdding ImageMagick'
|
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'
|
print '\tCopying fontconfig'
|
||||||
for f in glob.glob(os.path.join(FONTCONFIG_DIR, '*')):
|
for f in glob.glob(os.path.join(FONTCONFIG_DIR, '*')):
|
||||||
tgt = os.path.join(PY2EXE_DIR, os.path.basename(f))
|
tgt = os.path.join(PY2EXE_DIR, os.path.basename(f))
|
||||||
|
129
setup.py
129
setup.py
@ -4,7 +4,9 @@ __copyright__ = '2008, Kovid Goyal <kovid at kovidgoyal.net>'
|
|||||||
|
|
||||||
import sys, re, os, shutil
|
import sys, re, os, shutil
|
||||||
sys.path.append('src')
|
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()
|
src = open('src/calibre/__init__.py', 'rb').read()
|
||||||
VERSION = re.search(r'__version__\s+=\s+[\'"]([^\'"]+)[\'"]', src).group(1)
|
VERSION = re.search(r'__version__\s+=\s+[\'"]([^\'"]+)[\'"]', src).group(1)
|
||||||
APPNAME = re.search(r'__appname__\s+=\s+[\'"]([^\'"]+)[\'"]', src).group(1)
|
APPNAME = re.search(r'__appname__\s+=\s+[\'"]([^\'"]+)[\'"]', src).group(1)
|
||||||
@ -44,59 +46,114 @@ main_functions = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
from setuptools import setup, find_packages
|
from setuptools import setup, find_packages, Extension
|
||||||
import subprocess, glob
|
import subprocess, glob
|
||||||
|
|
||||||
entry_points['console_scripts'].append('calibre_postinstall = calibre.linux:post_install')
|
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(
|
setup(
|
||||||
name=APPNAME,
|
name=APPNAME,
|
||||||
packages = find_packages('src'),
|
packages = find_packages('src'),
|
||||||
package_dir = { '' : 'src' },
|
package_dir = { '' : 'src' },
|
||||||
version=VERSION,
|
version=VERSION,
|
||||||
author='Kovid Goyal',
|
author='Kovid Goyal',
|
||||||
author_email='kovid@kovidgoyal.net',
|
author_email='kovid@kovidgoyal.net',
|
||||||
url = 'http://%s.kovidgoyal.net'%APPNAME,
|
url = 'http://%s.kovidgoyal.net'%APPNAME,
|
||||||
package_data = {'calibre':['plugins/*']},
|
package_data = {'calibre':['plugins/*']},
|
||||||
include_package_data=True,
|
include_package_data=True,
|
||||||
entry_points = entry_points,
|
entry_points = entry_points,
|
||||||
zip_safe = False,
|
zip_safe = False,
|
||||||
options = { 'bdist_egg' : {'exclude_source_files': True,}, },
|
options = { 'bdist_egg' : {'exclude_source_files': True,}, },
|
||||||
description =
|
ext_modules=ext_modules,
|
||||||
|
description =
|
||||||
'''
|
'''
|
||||||
E-book management application.
|
E-book management application.
|
||||||
''',
|
''',
|
||||||
long_description =
|
long_description =
|
||||||
'''
|
'''
|
||||||
%s is an e-book library manager. It can view, convert and catalog e-books in most of the major e-book formats. It can also talk to a few e-book reader devices. It can go out to the internet and fetch metadata for your books. It can download newspapers and convert them into e-books for convenient reading. It is cross platform, running on Linux, Windows and OS X.
|
%s is an e-book library manager. It can view, convert and catalog e-books in most of the major e-book formats. It can also talk to a few e-book reader devices. It can go out to the internet and fetch metadata for your books. It can download newspapers and convert them into e-books for convenient reading. It is cross platform, running on Linux, Windows and OS X.
|
||||||
|
|
||||||
For screenshots: https://%s.kovidgoyal.net/wiki/Screenshots
|
For screenshots: https://%s.kovidgoyal.net/wiki/Screenshots
|
||||||
|
|
||||||
For installation/usage instructions please see
|
For installation/usage instructions please see
|
||||||
http://%s.kovidgoyal.net
|
http://%s.kovidgoyal.net
|
||||||
|
|
||||||
For source code access:
|
For source code access:
|
||||||
bzr branch http://bzr.kovidgoyal.net/code/%s/trunk %s
|
bzr branch http://bzr.kovidgoyal.net/code/%s/trunk %s
|
||||||
|
|
||||||
To update your copy of the source code:
|
To update your copy of the source code:
|
||||||
bzr merge
|
bzr merge
|
||||||
|
|
||||||
'''%(APPNAME, APPNAME, APPNAME, APPNAME, APPNAME),
|
'''%(APPNAME, APPNAME, APPNAME, APPNAME, APPNAME),
|
||||||
license = 'GPL',
|
license = 'GPL',
|
||||||
classifiers = [
|
classifiers = [
|
||||||
'Development Status :: 4 - Beta',
|
'Development Status :: 4 - Beta',
|
||||||
'Environment :: Console',
|
'Environment :: Console',
|
||||||
'Environment :: X11 Applications :: Qt',
|
'Environment :: X11 Applications :: Qt',
|
||||||
'Intended Audience :: Developers',
|
'Intended Audience :: Developers',
|
||||||
'Intended Audience :: End Users/Desktop',
|
'Intended Audience :: End Users/Desktop',
|
||||||
'License :: OSI Approved :: GNU General Public License (GPL)',
|
'License :: OSI Approved :: GNU General Public License (GPL)',
|
||||||
'Natural Language :: English',
|
'Natural Language :: English',
|
||||||
'Operating System :: POSIX :: Linux',
|
'Operating System :: POSIX :: Linux',
|
||||||
'Programming Language :: Python',
|
'Programming Language :: Python',
|
||||||
'Topic :: Software Development :: Libraries :: Python Modules',
|
'Topic :: Software Development :: Libraries :: Python Modules',
|
||||||
'Topic :: System :: Hardware :: Hardware Drivers'
|
'Topic :: System :: Hardware :: Hardware Drivers'
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
if 'develop' in ' '.join(sys.argv) and islinux:
|
if 'develop' in ' '.join(sys.argv) and islinux:
|
||||||
subprocess.check_call('calibre_postinstall', shell=True)
|
subprocess.check_call('calibre_postinstall', shell=True)
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
''' E-book management software'''
|
''' E-book management software'''
|
||||||
__license__ = 'GPL v3'
|
__license__ = 'GPL v3'
|
||||||
__copyright__ = '2008, Kovid Goyal <kovid at kovidgoyal.net>'
|
__copyright__ = '2008, Kovid Goyal <kovid at kovidgoyal.net>'
|
||||||
__version__ = '0.4.79'
|
__version__ = '0.4.80'
|
||||||
__docformat__ = "epytext"
|
__docformat__ = "epytext"
|
||||||
__author__ = "Kovid Goyal <kovid at kovidgoyal.net>"
|
__author__ = "Kovid Goyal <kovid at kovidgoyal.net>"
|
||||||
__appname__ = 'calibre'
|
__appname__ = 'calibre'
|
||||||
@ -20,7 +20,7 @@ from PyQt4.QtGui import QDesktopServices
|
|||||||
|
|
||||||
from calibre.translations.msgfmt import make
|
from calibre.translations.msgfmt import make
|
||||||
from calibre.ebooks.chardet import detect
|
from calibre.ebooks.chardet import detect
|
||||||
from calibre.terminfo import TerminalController
|
from calibre.utils.terminfo import TerminalController
|
||||||
|
|
||||||
terminal_controller = TerminalController(sys.stdout)
|
terminal_controller = TerminalController(sys.stdout)
|
||||||
iswindows = 'win32' in sys.platform.lower() or 'win64' in sys.platform.lower()
|
iswindows = 'win32' in sys.platform.lower() or 'win64' in sys.platform.lower()
|
||||||
@ -43,6 +43,41 @@ try:
|
|||||||
except:
|
except:
|
||||||
preferred_encoding = 'utf-8'
|
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
|
_abspath = os.path.abspath
|
||||||
def my_abspath(path, encoding=sys.getfilesystemencoding()):
|
def my_abspath(path, encoding=sys.getfilesystemencoding()):
|
||||||
'''
|
'''
|
||||||
@ -268,10 +303,10 @@ def filename_to_utf8(name):
|
|||||||
def extract(path, dir):
|
def extract(path, dir):
|
||||||
ext = os.path.splitext(path)[1][1:].lower()
|
ext = os.path.splitext(path)[1][1:].lower()
|
||||||
extractor = None
|
extractor = None
|
||||||
if ext == 'zip':
|
if ext in ['zip', 'cbz', 'epub']:
|
||||||
from calibre.libunzip import extract as zipextract
|
from calibre.libunzip import extract as zipextract
|
||||||
extractor = zipextract
|
extractor = zipextract
|
||||||
elif ext == 'rar':
|
elif ext in ['cbr', 'rar']:
|
||||||
from calibre.libunrar import extract as rarextract
|
from calibre.libunrar import extract as rarextract
|
||||||
extractor = rarextract
|
extractor = rarextract
|
||||||
if extractor is None:
|
if extractor is None:
|
||||||
@ -605,23 +640,3 @@ if isosx:
|
|||||||
for font in fonts:
|
for font in fonts:
|
||||||
exec 'from calibre.ebooks.lrf.fonts.liberation.'+font+' import font_data'
|
exec 'from calibre.ebooks.lrf.fonts.liberation.'+font+' import font_data'
|
||||||
open(os.path.join(fdir, font+'.ttf'), 'wb').write(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
|
return parser
|
||||||
|
|
||||||
def update_zipfile(zipfile, mod, path):
|
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]*')
|
pat = re.compile(mod.replace('.', '/')+r'\.py[co]*')
|
||||||
name = mod.replace('.', '/') + os.path.splitext(path)[-1]
|
name = mod.replace('.', '/') + os.path.splitext(path)[-1]
|
||||||
update(zipfile, [pat], [path], [name])
|
update(zipfile, [pat], [path], [name])
|
||||||
|
@ -133,31 +133,7 @@ class KINDLE(Device):
|
|||||||
|
|
||||||
|
|
||||||
def open_windows(self):
|
def open_windows(self):
|
||||||
drives = []
|
raise NotImplementedError
|
||||||
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]
|
|
||||||
|
|
||||||
|
|
||||||
def open_linux(self):
|
def open_linux(self):
|
||||||
|
@ -20,7 +20,8 @@ MIME_MAP = {
|
|||||||
'lrx' : 'application/x-sony-bbeb',
|
'lrx' : 'application/x-sony-bbeb',
|
||||||
"rtf" : "application/rtf",
|
"rtf" : "application/rtf",
|
||||||
"pdf" : "application/pdf",
|
"pdf" : "application/pdf",
|
||||||
"txt" : "text/plain"
|
"txt" : "text/plain" ,
|
||||||
|
'epub': 'application/epub+zip',
|
||||||
}
|
}
|
||||||
|
|
||||||
def uuid():
|
def uuid():
|
||||||
|
@ -31,6 +31,7 @@ class PRS505(Device):
|
|||||||
PRODUCT_ID = 0x031e #: Product Id for the PRS-505
|
PRODUCT_ID = 0x031e #: Product Id for the PRS-505
|
||||||
PRODUCT_NAME = 'PRS-505'
|
PRODUCT_NAME = 'PRS-505'
|
||||||
VENDOR_NAME = 'SONY'
|
VENDOR_NAME = 'SONY'
|
||||||
|
FORMATS = ["lrf", 'epub', "rtf", "pdf", "txt"]
|
||||||
|
|
||||||
MEDIA_XML = 'database/cache/media.xml'
|
MEDIA_XML = 'database/cache/media.xml'
|
||||||
CACHE_XML = 'Sony Reader/database/cache.xml'
|
CACHE_XML = 'Sony Reader/database/cache.xml'
|
||||||
@ -437,4 +438,4 @@ def main(args=sys.argv):
|
|||||||
return 0
|
return 0
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
sys.exit(main())
|
sys.exit(main())
|
||||||
|
@ -7,59 +7,42 @@ manner.
|
|||||||
|
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
from calibre import iswindows, isosx
|
from calibre import iswindows, isosx, plugins
|
||||||
from calibre.devices import libusb
|
from calibre.devices import libusb
|
||||||
|
|
||||||
osx_scanner = None
|
osx_scanner = win_scanner = linux_scanner = None
|
||||||
try:
|
|
||||||
import usbobserver
|
|
||||||
osx_scanner = usbobserver.get_devices
|
|
||||||
except ImportError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
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):
|
class DeviceScanner(object):
|
||||||
|
|
||||||
def __init__(self, wmi=None):
|
def __init__(self, *args):
|
||||||
self.wmi = wmi
|
|
||||||
if iswindows and wmi is None:
|
|
||||||
raise RuntimeError('You must pass a wmi instance to DeviceScanner on windows.')
|
|
||||||
if isosx and osx_scanner is None:
|
if isosx and osx_scanner is None:
|
||||||
raise RuntimeError('The Python extension usbobserver must be available on OS X.')
|
raise RuntimeError('The Python extension usbobserver must be available on OS X.')
|
||||||
if not (isosx or iswindows) and not libusb.has_library():
|
if not (isosx or iswindows) and not libusb.has_library():
|
||||||
raise RuntimeError('DeviceScanner requires libusb to work.')
|
raise RuntimeError('DeviceScanner requires libusb to work.')
|
||||||
|
self.scanner = win_scanner if iswindows else osx_scanner if isosx else linux_scanner
|
||||||
self.devices = []
|
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):
|
def scan(self):
|
||||||
try: # Windows WMI occasionally and temporarily barfs
|
'''Fetch list of connected USB devices from operating system'''
|
||||||
self.devices = self.get_devices()
|
self.devices = self.scanner()
|
||||||
except Exception, e:
|
|
||||||
if not iswindows and e:
|
|
||||||
raise e
|
|
||||||
|
|
||||||
|
|
||||||
def is_device_connected(self, device):
|
def is_device_connected(self, device):
|
||||||
if iswindows:
|
if iswindows:
|
||||||
for device_id in self.devices:
|
for device_id in self.devices:
|
||||||
if 'VEN_'+device.VENDOR_NAME in device_id and \
|
vid, pid = 'vid_%4.4x'%device.VENDOR_ID, 'pid_%4.4x'%device.PRODUCT_ID
|
||||||
'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()
|
|
||||||
if vid in device_id and pid in device_id:
|
if vid in device_id and pid in device_id:
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
@ -74,4 +57,4 @@ def main(args=sys.argv):
|
|||||||
return 0
|
return 0
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
sys.exit(main())
|
sys.exit(main())
|
||||||
|
@ -29,7 +29,7 @@
|
|||||||
|
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
usbobserver_get_devices(PyObject *self, PyObject *args) {
|
usbobserver_get_usb_devices(PyObject *self, PyObject *args) {
|
||||||
|
|
||||||
mach_port_t masterPort;
|
mach_port_t masterPort;
|
||||||
CFMutableDictionaryRef matchingDict;
|
CFMutableDictionaryRef matchingDict;
|
||||||
@ -62,7 +62,7 @@ usbobserver_get_devices(PyObject *self, PyObject *args) {
|
|||||||
PyObject *devices, *device;
|
PyObject *devices, *device;
|
||||||
devices = PyList_New(0);
|
devices = PyList_New(0);
|
||||||
if (devices == NULL) {
|
if (devices == NULL) {
|
||||||
PyErr_SetString(PyExc_RuntimeError, "Out of memory allocating list");
|
PyErr_NoMemory();
|
||||||
mach_port_deallocate(mach_task_self(), masterPort);
|
mach_port_deallocate(mach_task_self(), masterPort);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@ -112,7 +112,7 @@ usbobserver_get_devices(PyObject *self, PyObject *args) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static PyMethodDef usbobserver_methods[] = {
|
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)."
|
"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}
|
{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 sys, struct, cStringIO, os
|
||||||
import functools
|
import functools
|
||||||
|
import re
|
||||||
from calibre.ebooks.lit import LitError
|
from calibre.ebooks.lit import LitError
|
||||||
from calibre.ebooks.lit.maps import OPF_MAP, HTML_MAP
|
from calibre.ebooks.lit.maps import OPF_MAP, HTML_MAP
|
||||||
import calibre.ebooks.lit.mssha1 as mssha1
|
import calibre.ebooks.lit.mssha1 as mssha1
|
||||||
import calibre.ebooks.lit.msdes as msdes
|
|
||||||
from calibre import plugins
|
from calibre import plugins
|
||||||
lzx, lxzerror = plugins['lzx']
|
lzx, lxzerror = plugins['lzx']
|
||||||
|
msdes, msdeserror = plugins['msdes']
|
||||||
|
|
||||||
OPF_DECL = """<?xml version="1.0" encoding="UTF-8" ?>
|
OPF_DECL = """<?xml version="1.0" encoding="UTF-8" ?>
|
||||||
<!DOCTYPE package
|
<!DOCTYPE package
|
||||||
@ -84,42 +85,40 @@ def read_utf8_char(bytes, pos):
|
|||||||
if elsize + pos > len(bytes):
|
if elsize + pos > len(bytes):
|
||||||
raise LitError('Invalid UTF8 character: %s' % repr(bytes[pos]))
|
raise LitError('Invalid UTF8 character: %s' % repr(bytes[pos]))
|
||||||
c &= (mask - 1)
|
c &= (mask - 1)
|
||||||
for i in range(1, elsize):
|
for i in xrange(1, elsize):
|
||||||
b = ord(bytes[pos+i])
|
b = ord(bytes[pos+i])
|
||||||
if (b & 0xC0) != 0x80:
|
if (b & 0xC0) != 0x80:
|
||||||
raise LitError(
|
raise LitError(
|
||||||
'Invalid UTF8 character: %s' % repr(bytes[pos:pos+i]))
|
'Invalid UTF8 character: %s' % repr(bytes[pos:pos+i]))
|
||||||
c = (c << 6) | (b & 0x3F)
|
c = (c << 6) | (b & 0x3F)
|
||||||
return unichr(c), pos+elsize
|
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):
|
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):
|
def __init__(self, bin, manifest, map=OPF_MAP):
|
||||||
self.manifest = manifest
|
self.manifest = manifest
|
||||||
self.tag_map, self.attr_map, self.tag_to_attr_map = map
|
self.tag_map, self.attr_map, self.tag_to_attr_map = map
|
||||||
self.opf = map is OPF_MAP
|
self.opf = map is OPF_MAP
|
||||||
self.bin = bin
|
self.bin = bin
|
||||||
self.buf = cStringIO.StringIO()
|
self.buf = cStringIO.StringIO()
|
||||||
self.ampersands = []
|
|
||||||
self.binary_to_text()
|
self.binary_to_text()
|
||||||
self.raw = self.buf.getvalue().lstrip().decode('utf-8')
|
self.raw = self.buf.getvalue().lstrip().decode('utf-8')
|
||||||
self.escape_ampersands()
|
self.escape_ampersands()
|
||||||
|
|
||||||
def escape_ampersands(self):
|
def escape_ampersands(self):
|
||||||
offset = 0
|
self.raw = self.AMPERSAND_RE.sub('&', self.raw)
|
||||||
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
|
|
||||||
|
|
||||||
def item_path(self, internal_id):
|
def item_path(self, internal_id):
|
||||||
try:
|
try:
|
||||||
@ -148,8 +147,6 @@ class UnBinary(object):
|
|||||||
continue
|
continue
|
||||||
elif c == '\v':
|
elif c == '\v':
|
||||||
c = '\n'
|
c = '\n'
|
||||||
elif c == '&':
|
|
||||||
self.ampersands.append(self.buf.tell()-1)
|
|
||||||
self.buf.write(c.encode('utf-8'))
|
self.buf.write(c.encode('utf-8'))
|
||||||
|
|
||||||
elif state == 'get flags':
|
elif state == 'get flags':
|
||||||
@ -328,8 +325,11 @@ class ManifestItem(object):
|
|||||||
self.offset = offset
|
self.offset = offset
|
||||||
self.root = root
|
self.root = root
|
||||||
self.state = state
|
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 '..' (!?)
|
# 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:]
|
while path.startswith('../'): path = path[3:]
|
||||||
self.path = path
|
self.path = path
|
||||||
|
|
||||||
@ -475,7 +475,7 @@ class LitReader(object):
|
|||||||
|
|
||||||
def _read_header_pieces(self):
|
def _read_header_pieces(self):
|
||||||
src = self.header[self.hdr_len:]
|
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]
|
piece = src[i * self.PIECE_SIZE:(i + 1) * self.PIECE_SIZE]
|
||||||
if u32(piece[4:]) != 0 or u32(piece[12:]) != 0:
|
if u32(piece[4:]) != 0 or u32(piece[12:]) != 0:
|
||||||
raise LitError('Piece %s has 64bit value' % repr(piece))
|
raise LitError('Piece %s has 64bit value' % repr(piece))
|
||||||
@ -525,7 +525,7 @@ class LitReader(object):
|
|||||||
raise LitError('Directory entry had 64bit name length.')
|
raise LitError('Directory entry had 64bit name length.')
|
||||||
if namelen > remaining - 3:
|
if namelen > remaining - 3:
|
||||||
raise LitError('Read past end of directory chunk')
|
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)
|
section, chunk, remaining = encint(chunk, remaining)
|
||||||
offset, chunk, remaining = encint(chunk, remaining)
|
offset, chunk, remaining = encint(chunk, remaining)
|
||||||
size, 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.num_sections = u16(raw[2:pos])
|
||||||
self.section_names = [""]*self.num_sections
|
self.section_names = [""]*self.num_sections
|
||||||
self.section_data = [None]*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])
|
size = u16(raw[pos:pos+2])
|
||||||
pos += 2
|
pos += 2
|
||||||
size = size*2 + 2
|
size = size*2 + 2
|
||||||
@ -570,27 +570,31 @@ class LitReader(object):
|
|||||||
if len(raw) < 5:
|
if len(raw) < 5:
|
||||||
raise LitError('Truncated manifest')
|
raise LitError('Truncated manifest')
|
||||||
offset, raw = u32(raw), raw[4:]
|
offset, raw = u32(raw), raw[4:]
|
||||||
slen, raw = ord(raw[0]), raw[1:]
|
internal, raw = consume_sized_utf8_string(raw)
|
||||||
internal, raw = raw[:slen].decode('utf8'), raw[slen:]
|
original, raw = consume_sized_utf8_string(raw)
|
||||||
slen, raw = ord(raw[0]), raw[1:]
|
# Is this last one UTF-8 or ASCIIZ?
|
||||||
original, raw = raw[:slen].decode('utf8'), raw[slen:]
|
mime_type, raw = consume_sized_utf8_string(raw, zpad=True)
|
||||||
slen, raw = ord(raw[0]), raw[1:]
|
|
||||||
mime_type, raw = raw[:slen].decode('utf8'), raw[slen+1:]
|
|
||||||
self.manifest[internal] = ManifestItem(
|
self.manifest[internal] = ManifestItem(
|
||||||
original, internal, mime_type, offset, root, state)
|
original, internal, mime_type, offset, root, state)
|
||||||
mlist = self.manifest.values()
|
mlist = self.manifest.values()
|
||||||
shared = mlist[0].path
|
# Remove any common path elements
|
||||||
for item in mlist[1:]:
|
if len(mlist) > 1:
|
||||||
path = item.path
|
shared = mlist[0].path
|
||||||
while shared and not path.startswith(shared):
|
for item in mlist[1:]:
|
||||||
try: shared = shared[:shared.rindex("/", 0, -2) + 1]
|
path = item.path
|
||||||
except ValueError: shared = None
|
while shared and not path.startswith(shared):
|
||||||
if not shared:
|
try: shared = shared[:shared.rindex("/", 0, -2) + 1]
|
||||||
break
|
except ValueError: shared = None
|
||||||
if shared:
|
if not shared:
|
||||||
slen = len(shared)
|
break
|
||||||
for item in mlist:
|
if shared:
|
||||||
item.path = item.path[slen:]
|
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):
|
def _read_meta(self):
|
||||||
raw = self.get_file('/meta')
|
raw = self.get_file('/meta')
|
||||||
@ -614,8 +618,8 @@ class LitReader(object):
|
|||||||
self.drmlevel = 1
|
self.drmlevel = 1
|
||||||
else:
|
else:
|
||||||
return
|
return
|
||||||
des = msdes.new(self._calculate_deskey())
|
msdes.deskey(self._calculate_deskey(), msdes.DE1)
|
||||||
bookkey = des.decrypt(self.get_file('/DRMStorage/DRMSealed'))
|
bookkey = msdes.des(self.get_file('/DRMStorage/DRMSealed'))
|
||||||
if bookkey[0] != '\000':
|
if bookkey[0] != '\000':
|
||||||
raise LitError('Unable to decrypt title key!')
|
raise LitError('Unable to decrypt title key!')
|
||||||
self.bookkey = bookkey[1:9]
|
self.bookkey = bookkey[1:9]
|
||||||
@ -690,7 +694,8 @@ class LitReader(object):
|
|||||||
def _decrypt(self, content):
|
def _decrypt(self, content):
|
||||||
if self.drmlevel == 5:
|
if self.drmlevel == 5:
|
||||||
raise LitError('Cannot extract content from a DRM protected ebook')
|
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):
|
def _decompress(self, content, control, reset_table):
|
||||||
if len(control) < 32 or control[CONTROL_TAG:CONTROL_TAG+4] != "LZXC":
|
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
|
print _('OEB ebook created in'), opts.output_dir
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
|
try:
|
||||||
|
import psyco
|
||||||
|
psyco.bind(read_utf8_char)
|
||||||
|
psyco.bind(UnBinary.binary_to_text)
|
||||||
|
except ImportError:
|
||||||
|
pass
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
sys.exit(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']), \
|
bls, ls = int(self.book.defaultTextStyle.attrs['baselineskip']), \
|
||||||
int(self.book.defaultTextStyle.attrs['linespace'])
|
int(self.book.defaultTextStyle.attrs['linespace'])
|
||||||
try: # See if line-height is a unitless number
|
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
|
fp['linespace'] = val
|
||||||
except ValueError:
|
except ValueError:
|
||||||
val = self.unit_convert(tag_css['line-height'], pts=True, base_length='1pt')
|
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)
|
css, pcss = self.parse_css(text)
|
||||||
ncss.update(css)
|
ncss.update(css)
|
||||||
npcss.update(pcss)
|
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'):
|
and tag.has_key('href'):
|
||||||
path = munge_paths(self.target_prefix, tag['href'])[0]
|
path = munge_paths(self.target_prefix, tag['href'])[0]
|
||||||
try:
|
try:
|
||||||
|
@ -5,10 +5,11 @@ import os, sys, shutil, glob, logging
|
|||||||
from tempfile import mkdtemp
|
from tempfile import mkdtemp
|
||||||
from subprocess import Popen, PIPE
|
from subprocess import Popen, PIPE
|
||||||
from calibre.ebooks.lrf import option_parser as lrf_option_parser
|
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 import ConversionError
|
||||||
from calibre.ebooks.lrf.html.convert_from import process_file as html_process_file
|
from calibre.ebooks.lrf.html.convert_from import process_file as html_process_file
|
||||||
from calibre.ebooks.metadata.opf import OPFReader
|
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'
|
CLIT = 'clit'
|
||||||
if isosx and hasattr(sys, 'frameworks_dir'):
|
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')
|
CLIT = os.path.join(getattr(sys, 'frozen_path'), 'clit')
|
||||||
|
|
||||||
def option_parser():
|
def option_parser():
|
||||||
return lrf_option_parser(
|
parser = lrf_option_parser(
|
||||||
_('''Usage: %prog [options] mybook.lit
|
_('''Usage: %prog [options] mybook.lit
|
||||||
|
|
||||||
|
|
||||||
%prog converts mybook.lit to mybook.lrf''')
|
%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):
|
def generate_html(pathtolit, logger):
|
||||||
if not os.access(pathtolit, os.R_OK):
|
if not os.access(pathtolit, os.R_OK):
|
||||||
raise ConversionError, 'Cannot read from ' + pathtolit
|
raise ConversionError, 'Cannot read from ' + pathtolit
|
||||||
tdir = mkdtemp(prefix=__appname__+'_')
|
tdir = mkdtemp(prefix=__appname__+'_')
|
||||||
os.rmdir(tdir)
|
os.rmdir(tdir)
|
||||||
sep = r'\\' if iswindows else os.path.sep
|
cmd = [CLIT, pathtolit, '%s'%(tdir+os.sep)]
|
||||||
cmd = ' '.join([CLIT, '"'+pathtolit+'"', '"%s"'%(tdir+sep,)])
|
logger.debug(repr(cmd))
|
||||||
logger.debug(cmd)
|
p = Popen(cmd, stderr=PIPE, stdout=PIPE)
|
||||||
p = Popen(cmd, shell=True, stderr=PIPE, stdout=PIPE)
|
|
||||||
stdout = p.stdout.read()
|
stdout = p.stdout.read()
|
||||||
err = p.stderr.read()
|
err = p.stderr.read()
|
||||||
logger.info(p.stdout.read())
|
logger.info(p.stdout.read())
|
||||||
@ -51,7 +63,8 @@ def process_file(path, options, logger=None):
|
|||||||
logger = logging.getLogger('lit2lrf')
|
logger = logging.getLogger('lit2lrf')
|
||||||
setup_cli_handlers(logger, level)
|
setup_cli_handlers(logger, level)
|
||||||
lit = os.path.abspath(os.path.expanduser(path))
|
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:
|
try:
|
||||||
opf = glob.glob(os.path.join(tdir, '*.opf'))
|
opf = glob.glob(os.path.join(tdir, '*.opf'))
|
||||||
if opf:
|
if opf:
|
||||||
|
@ -744,10 +744,9 @@ class Text(LRFStream):
|
|||||||
self.content.append(self.__class__.TextTag(name))
|
self.content.append(self.__class__.TextTag(name))
|
||||||
|
|
||||||
def empline(self, tag, stream):
|
def empline(self, tag, stream):
|
||||||
|
|
||||||
def invalid(op):
|
def invalid(op):
|
||||||
stream.seek(op)
|
stream.seek(op)
|
||||||
self.simple_container(None, 'EmpLine')
|
#self.simple_container(None, 'EmpLine')
|
||||||
|
|
||||||
oldpos = stream.tell()
|
oldpos = stream.tell()
|
||||||
try:
|
try:
|
||||||
@ -770,7 +769,8 @@ class Text(LRFStream):
|
|||||||
except LRFParseError:
|
except LRFParseError:
|
||||||
stream.seek(oldpos)
|
stream.seek(oldpos)
|
||||||
|
|
||||||
self.content.append(self.__class__.TextTag(
|
if attrs:
|
||||||
|
self.content.append(self.__class__.TextTag(
|
||||||
'EmpLine', attrs=attrs))
|
'EmpLine', attrs=attrs))
|
||||||
|
|
||||||
def space(self, tag, stream):
|
def space(self, tag, stream):
|
||||||
|
@ -65,7 +65,7 @@ class Resource(object):
|
|||||||
else:
|
else:
|
||||||
pc = url[2]
|
pc = url[2]
|
||||||
if isinstance(pc, unicode):
|
if isinstance(pc, unicode):
|
||||||
pc.encode('utf-8')
|
pc = pc.encode('utf-8')
|
||||||
pc = unquote(pc).decode('utf-8')
|
pc = unquote(pc).decode('utf-8')
|
||||||
self.path = os.path.abspath(os.path.join(basedir, pc.replace('/', os.sep)))
|
self.path = os.path.abspath(os.path.join(basedir, pc.replace('/', os.sep)))
|
||||||
self.fragment = unquote(url[-1])
|
self.fragment = unquote(url[-1])
|
||||||
|
@ -7,13 +7,13 @@ __copyright__ = '2008, Kovid Goyal <kovid at kovidgoyal.net>'
|
|||||||
|
|
||||||
import sys, os
|
import sys, os
|
||||||
|
|
||||||
from zipfile import ZipFile, BadZipfile
|
from calibre.utils.zipfile import ZipFile, BadZipfile
|
||||||
from cStringIO import StringIO
|
from cStringIO import StringIO
|
||||||
from contextlib import closing
|
from contextlib import closing
|
||||||
|
|
||||||
from calibre.ebooks.BeautifulSoup import BeautifulStoneSoup
|
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):
|
class EPubException(Exception):
|
||||||
pass
|
pass
|
||||||
@ -71,9 +71,9 @@ class OCFReader(OCF):
|
|||||||
raise EPubException("missing OPF package file")
|
raise EPubException("missing OPF package file")
|
||||||
|
|
||||||
class OCFZipReader(OCFReader):
|
class OCFZipReader(OCFReader):
|
||||||
def __init__(self, stream):
|
def __init__(self, stream, mode='r'):
|
||||||
try:
|
try:
|
||||||
self.archive = ZipFile(stream, 'r')
|
self.archive = ZipFile(stream, mode)
|
||||||
except BadZipfile:
|
except BadZipfile:
|
||||||
raise EPubException("not a ZIP .epub OCF container")
|
raise EPubException("not a ZIP .epub OCF container")
|
||||||
self.root = getattr(stream, 'name', os.getcwd())
|
self.root = getattr(stream, 'name', os.getcwd())
|
||||||
@ -81,6 +81,19 @@ class OCFZipReader(OCFReader):
|
|||||||
|
|
||||||
def open(self, name, mode='r'):
|
def open(self, name, mode='r'):
|
||||||
return StringIO(self.archive.read(name))
|
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):
|
class OCFDirReader(OCFReader):
|
||||||
def __init__(self, path):
|
def __init__(self, path):
|
||||||
@ -95,13 +108,35 @@ def get_metadata(stream):
|
|||||||
""" Return metadata as a L{MetaInfo} object """
|
""" Return metadata as a L{MetaInfo} object """
|
||||||
return OCFZipReader(stream).opf
|
return OCFZipReader(stream).opf
|
||||||
|
|
||||||
|
def set_metadata(stream, mi):
|
||||||
|
OCFZipWriter(stream).set_metadata(mi)
|
||||||
|
|
||||||
|
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):
|
def main(args=sys.argv):
|
||||||
if len(args) != 2 or '--help' in args or '-h' in args:
|
parser = option_parser()
|
||||||
print >>sys.stderr, _('Usage:'), args[0], _('mybook.epub')
|
opts, args = parser.parse_args(args)
|
||||||
|
if len(args) != 2:
|
||||||
|
parser.print_help()
|
||||||
return 1
|
return 1
|
||||||
|
stream = open(args[1], 'r+b')
|
||||||
path = os.path.abspath(os.path.expanduser(args[1]))
|
mi = MetaInformation(OCFZipReader(stream).opf)
|
||||||
print unicode(get_metadata(open(path, 'rb')))
|
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
|
return 0
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
@ -140,7 +140,7 @@ def main(args=sys.argv):
|
|||||||
return 1
|
return 1
|
||||||
|
|
||||||
for book in create_books(opts, args):
|
for book in create_books(opts, args):
|
||||||
print unicode(book)
|
print unicode(book).encode('utf-8')
|
||||||
|
|
||||||
return 0
|
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.opf import OPFReader
|
||||||
from calibre.ebooks.metadata.rtf import set_metadata as set_rtf_metadata
|
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.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
|
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: stream_type = stream_type.lower()
|
||||||
if stream_type == 'lrf':
|
if stream_type == 'lrf':
|
||||||
set_lrf_metadata(stream, mi)
|
set_lrf_metadata(stream, mi)
|
||||||
|
elif stream_type == 'epub':
|
||||||
|
set_epub_metadata(stream, mi)
|
||||||
elif stream_type == 'rtf':
|
elif stream_type == 'rtf':
|
||||||
set_rtf_metadata(stream, mi)
|
set_rtf_metadata(stream, mi)
|
||||||
|
|
||||||
|
@ -20,7 +20,7 @@ class NCXSoup(BeautifulStoneSoup):
|
|||||||
|
|
||||||
class TOC(list):
|
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()):
|
base_path=os.getcwd()):
|
||||||
self.href = href
|
self.href = href
|
||||||
self.fragment = fragment
|
self.fragment = fragment
|
||||||
@ -30,7 +30,9 @@ class TOC(list):
|
|||||||
self.play_order = play_order
|
self.play_order = play_order
|
||||||
|
|
||||||
def add_item(self, href, fragment, text):
|
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]
|
return self[-1]
|
||||||
|
|
||||||
def top_level_items(self):
|
def top_level_items(self):
|
||||||
@ -151,4 +153,4 @@ class TOC(list):
|
|||||||
template = MarkupTemplate(ncx_template)
|
template = MarkupTemplate(ncx_template)
|
||||||
raw = template.generate(uid=uid, toc=self, __appname__=__appname__)
|
raw = template.generate(uid=uid, toc=self, __appname__=__appname__)
|
||||||
raw = raw.render(doctype=doctype)
|
raw = raw.render(doctype=doctype)
|
||||||
stream.write(raw)
|
stream.write(raw)
|
||||||
|
@ -66,7 +66,8 @@ class ConfigDialog(QDialog, Ui_Dialog):
|
|||||||
single_format = settings.get('save to disk single format', 'lrf')
|
single_format = settings.get('save to disk single format', 'lrf')
|
||||||
self.single_format.setCurrentIndex(BOOK_EXTENSIONS.index(single_format))
|
self.single_format.setCurrentIndex(BOOK_EXTENSIONS.index(single_format))
|
||||||
self.cover_browse.setValue(settings.get('cover flow queue length', 6))
|
self.cover_browse.setValue(settings.get('cover flow queue length', 6))
|
||||||
|
self.confirm_delete.setChecked(settings.get('confirm delete', False))
|
||||||
|
|
||||||
def compact(self, toggled):
|
def compact(self, toggled):
|
||||||
d = Vacuum(self, self.db)
|
d = Vacuum(self, self.db)
|
||||||
d.exec_()
|
d.exec_()
|
||||||
@ -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())]
|
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('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('show text in toolbar', bool(self.show_toolbar_text.isChecked()))
|
||||||
|
settings.set('confirm delete', bool(self.confirm_delete.isChecked()))
|
||||||
pattern = self.filename_pattern.commit()
|
pattern = self.filename_pattern.commit()
|
||||||
settings.set('filename pattern', pattern)
|
settings.set('filename pattern', pattern)
|
||||||
settings.set('save to disk single format', BOOK_EXTENSIONS[self.single_format.currentIndex()])
|
settings.set('save to disk single format', BOOK_EXTENSIONS[self.single_format.currentIndex()])
|
||||||
|
@ -83,7 +83,7 @@
|
|||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>595</width>
|
<width>595</width>
|
||||||
<height>638</height>
|
<height>640</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QVBoxLayout" name="verticalLayout" >
|
<layout class="QVBoxLayout" name="verticalLayout" >
|
||||||
@ -159,6 +159,13 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QCheckBox" name="confirm_delete" >
|
||||||
|
<property name="text" >
|
||||||
|
<string>Ask for &confirmation before deleting files</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<layout class="QGridLayout" name="gridLayout_2" >
|
<layout class="QGridLayout" name="gridLayout_2" >
|
||||||
<item row="0" column="0" >
|
<item row="0" column="0" >
|
||||||
|
@ -126,7 +126,7 @@ class ConversionJob(Job):
|
|||||||
def formatted_error(self):
|
def formatted_error(self):
|
||||||
if self.exception is None:
|
if self.exception is None:
|
||||||
return ''
|
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
|
ans += '<h2>Traceback:</h2><pre>%s</pre>'%self.last_traceback
|
||||||
return ans
|
return ans
|
||||||
|
|
||||||
|
@ -548,6 +548,12 @@ class Main(MainWindow, Ui_MainWindow):
|
|||||||
rows = view.selectionModel().selectedRows()
|
rows = view.selectionModel().selectedRows()
|
||||||
if not rows or len(rows) == 0:
|
if not rows or len(rows) == 0:
|
||||||
return
|
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:
|
if self.stack.currentIndex() == 0:
|
||||||
view.model().delete_books(rows)
|
view.model().delete_books(rows)
|
||||||
else:
|
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 os, sys, glob
|
||||||
import sipconfig
|
|
||||||
if os.environ.get('PYQT4PATH', None):
|
if os.environ.get('PYQT4PATH', None):
|
||||||
print os.environ['PYQT4PATH']
|
print os.environ['PYQT4PATH']
|
||||||
sys.path.insert(0, os.environ['PYQT4PATH'])
|
sys.path.insert(0, os.environ['PYQT4PATH'])
|
||||||
@ -32,34 +31,22 @@ makefile = pyqtconfig.QtGuiModuleMakefile (
|
|||||||
qt=1,
|
qt=1,
|
||||||
)
|
)
|
||||||
|
|
||||||
# Add the library we are wrapping. The name doesn't include any platform
|
# Setup the platform dependent Makefile parameters
|
||||||
# specific prefixes or extensions (e.g. the "lib" prefix on UNIX, or the
|
d = os.path.dirname
|
||||||
# ".dll" extension on Windows).
|
if 'darwin' in sys.platform:
|
||||||
if 'linux' in sys.platform:
|
makefile.extra_cflags += ['-arch i386', '-arch ppc']
|
||||||
for f in glob.glob('../../.build/libpictureflow.a'):
|
makefile.extra_lflags += ['-arch i386', '-arch ppc']
|
||||||
shutil.copyfile(f, os.path.basename(f))
|
qtdir = os.path.join(d(d(os.getcwd())), '.build')
|
||||||
makefile.extra_lib_dirs = ['.']
|
if 'win32' in sys.platform:
|
||||||
else:
|
qtdir = os.path.join(qtdir, 'release')
|
||||||
makefile.extra_lib_dirs = ['..\\..\\.build\\release', '../../.build', '.']
|
makefile.extra_lib_dirs += ['C:/Python25/libs']
|
||||||
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 []
|
# Add the compiled Qt objects
|
||||||
makefile.extra_lflags = ['-arch i386', '-arch ppc'] if 'darwin' in sys.platform else []
|
qtobjs = map(lambda x:'"'+x+'"', glob.glob(os.path.join(qtdir, '*.o')))
|
||||||
|
makefile.extra_lflags += qtobjs
|
||||||
makefile.extra_cxxflags = makefile.extra_cflags
|
makefile.extra_cxxflags = makefile.extra_cflags
|
||||||
|
|
||||||
# Generate the Makefile itself.
|
# Generate the Makefile itself.
|
||||||
makefile.generate()
|
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)
|
|
||||||
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
|||||||
TARGET = pictureflow
|
TARGET = pictureflow
|
||||||
TEMPLATE = lib
|
TEMPLATE = lib
|
||||||
HEADERS = pictureflow.h
|
HEADERS = pictureflow.h
|
||||||
SOURCES = pictureflow.cpp
|
SOURCES = pictureflow.cpp
|
||||||
VERSION = 0.2.0
|
VERSION = 1.0.0
|
||||||
CONFIG += x86 ppc
|
CONFIG += x86 ppc
|
||||||
|
@ -778,9 +778,9 @@ ALTER TABLE books ADD COLUMN isbn TEXT DEFAULT "" COLLATE NOCASE;
|
|||||||
isbn
|
isbn
|
||||||
FROM books;
|
FROM books;
|
||||||
''')
|
''')
|
||||||
conn.execute('pragma user_version=5')
|
conn.execute('pragma user_version=12')
|
||||||
conn.commit()
|
conn.commit()
|
||||||
|
|
||||||
def __init__(self, dbpath, row_factory=False):
|
def __init__(self, dbpath, row_factory=False):
|
||||||
self.dbpath = dbpath
|
self.dbpath = dbpath
|
||||||
self.conn = _connect(dbpath)
|
self.conn = _connect(dbpath)
|
||||||
|
@ -3,8 +3,6 @@ __license__ = 'GPL v3'
|
|||||||
__copyright__ = '2008, Kovid Goyal kovid@kovidgoyal.net'
|
__copyright__ = '2008, Kovid Goyal kovid@kovidgoyal.net'
|
||||||
__docformat__ = 'restructuredtext en'
|
__docformat__ = 'restructuredtext en'
|
||||||
|
|
||||||
import os
|
|
||||||
from cStringIO import StringIO
|
|
||||||
from calibre.utils import zipfile
|
from calibre.utils import zipfile
|
||||||
|
|
||||||
def update(pathtozip, patterns, filepaths, names, compression=zipfile.ZIP_DEFLATED, verbose=True):
|
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}
|
Extract archive C{filename} into directory C{dir}
|
||||||
"""
|
"""
|
||||||
zf = zipfile.ZipFile( filename )
|
zf = zipfile.ZipFile( filename )
|
||||||
namelist = zf.namelist()
|
zf.extractall(dir)
|
||||||
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 )
|
|
@ -47,6 +47,7 @@ entry_points = {
|
|||||||
'mobi2oeb = calibre.ebooks.mobi.reader:main',
|
'mobi2oeb = calibre.ebooks.mobi.reader:main',
|
||||||
'lrf2html = calibre.ebooks.lrf.html.convert_to:main',
|
'lrf2html = calibre.ebooks.lrf.html.convert_to:main',
|
||||||
'lit2oeb = calibre.ebooks.lit.reader:main',
|
'lit2oeb = calibre.ebooks.lit.reader:main',
|
||||||
|
'comic2lrf = calibre.ebooks.lrf.comic.convert_from:main',
|
||||||
'calibre-debug = calibre.debug:main',
|
'calibre-debug = calibre.debug:main',
|
||||||
'calibredb = calibre.library.cli:main',
|
'calibredb = calibre.library.cli:main',
|
||||||
'calibre-fontconfig = calibre.utils.fontconfig: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.main import option_parser as feeds2disk
|
||||||
from calibre.web.feeds.recipes import titles as feed_titles
|
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.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 = open_file('/etc/bash_completion.d/libprs500')
|
||||||
f.close()
|
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('pdf-meta', metaop, ['pdf']))
|
||||||
f.write(opts_and_exts('lit-meta', metaop, ['lit']))
|
f.write(opts_and_exts('lit-meta', metaop, ['lit']))
|
||||||
f.write(opts_and_exts('opf-meta', metaop, ['opf']))
|
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('lrfviewer', lrfviewerop, ['lrf']))
|
||||||
f.write(opts_and_exts('pdfrelow', pdfhtmlop, ['pdf']))
|
f.write(opts_and_exts('pdfrelow', pdfhtmlop, ['pdf']))
|
||||||
f.write(opts_and_exts('mobi2oeb', mobioeb, ['mobi', 'prc']))
|
f.write(opts_and_exts('mobi2oeb', mobioeb, ['mobi', 'prc']))
|
||||||
f.write(opts_and_exts('lit2oeb', lit2oeb, ['lit']))
|
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('feeds2disk', feeds2disk, feed_titles))
|
||||||
f.write(opts_and_words('feeds2lrf', feeds2lrf, feed_titles))
|
f.write(opts_and_words('feeds2lrf', feeds2lrf, feed_titles))
|
||||||
f.write('''
|
f.write('''
|
||||||
|
@ -251,8 +251,14 @@ def download_tarball():
|
|||||||
except ValueError:
|
except ValueError:
|
||||||
print 'Downloading calibre...'
|
print 'Downloading calibre...'
|
||||||
pb = None
|
pb = None
|
||||||
src = urllib2.urlopen(MOBILEREAD+'calibre-%version-i686.tar.bz2')
|
local = 'calibre-test.tar.bz2'
|
||||||
size = int(src.info()['content-length'])
|
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()
|
f = tempfile.NamedTemporaryFile()
|
||||||
while f.tell() < size:
|
while f.tell() < size:
|
||||||
f.write(src.read(4*1024))
|
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?
|
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()"
|
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?
|
I want some feature added to |app|. What can I do?
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
@ -14,7 +14,8 @@
|
|||||||
|
|
||||||
<div id="content" class="download">
|
<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>
|
<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">
|
<div py:if="not distro.is_generic">
|
||||||
First verify that you have a sufficiently new installation of python
|
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 />
|
<pre class="wiki">python --version</pre> should return at least 2.5.1<br />
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
|
|
||||||
<div id="content" class="binary">
|
<div id="content" class="binary">
|
||||||
<h1>Download $app for Linux</h1>
|
<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>
|
<p>
|
||||||
<img width="50" height="50" style="border:1px red solid" src="${href.chrome('/dl/images/binary_logo.png')}" />
|
<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>)
|
(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())
|
open(out, 'wb').write(tf.extractfile(next).read())
|
||||||
next = tf.next()
|
next = tf.next()
|
||||||
|
|
||||||
|
check_for_critical_bugs()
|
||||||
return 0
|
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):
|
def main(args=sys.argv):
|
||||||
if len(args) > 1:
|
if len(args) > 1:
|
||||||
if args[1] == 'pot':
|
if args[1] == 'pot':
|
||||||
|
@ -426,6 +426,7 @@ msgstr ""
|
|||||||
"Expressión regular utilizada para detectar los títulos de los capítulos. "
|
"Expressión regular utilizada para detectar los títulos de los capítulos. "
|
||||||
"Busca las marcas de encabezado (h1-h6). Por defecto: %default"
|
"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
|
#: /home/kovid/work/calibre/src/calibre/ebooks/lrf/__init__.py:165
|
||||||
msgid ""
|
msgid ""
|
||||||
"Detect a chapter beginning at an element having the specified attribute. The "
|
"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 "
|
"especificado. El formato para ésta espresión es tagname regexp, nombre del "
|
||||||
"atributo, valor del atributo regexp. Por ejemplo, para encontrar todas las "
|
"atributo, valor del atributo regexp. Por ejemplo, para encontrar todas las "
|
||||||
"etiquetas de cabecera que tienen como attribute class=\"capítulo\" podría "
|
"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
|
#: /home/kovid/work/calibre/src/calibre/ebooks/lrf/__init__.py:167
|
||||||
msgid ""
|
msgid ""
|
||||||
@ -2111,6 +2112,7 @@ msgstr "&Compartir receta"
|
|||||||
msgid "&Load recipe from file"
|
msgid "&Load recipe from file"
|
||||||
msgstr "&Cargar receta desde un archivo"
|
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
|
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/user_profiles_ui.py:215
|
||||||
msgid ""
|
msgid ""
|
||||||
"<html><head><meta name=\"qrichtext\" content=\"1\" /><style "
|
"<html><head><meta name=\"qrichtext\" content=\"1\" /><style "
|
||||||
@ -2124,16 +2126,15 @@ msgid ""
|
|||||||
"use the \"Advanced mode\" to further customize the fetch "
|
"use the \"Advanced mode\" to further customize the fetch "
|
||||||
"process.</p></body></html>"
|
"process.</p></body></html>"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"<html><head><meta name=\"qrichtext\" content=\"1\" /><style "
|
"<html><head><meta name=\"qrichtext\" content=\"1\" /><style type=\"text/css\">\n"
|
||||||
"type=\"text/css\">\n"
|
|
||||||
"p, li { white-space: pre-wrap; }\n"
|
"p, li { white-space: pre-wrap; }\n"
|
||||||
"</style></head><body style=\" font-family:'DejaVu Sans'; font-size:10pt; "
|
"</style></head><body style=\" font-family:'DejaVu Sans'; font-size:10pt; "
|
||||||
"font-weight:400; font-style:normal;\">\n"
|
"font-weight:400; font-style:normal;\">\n"
|
||||||
"<p style=\" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-"
|
"<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 "
|
"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, "
|
"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 "
|
"necesitará utilizar el \"modo avanzado\" para una configuración mas detallada "
|
||||||
"detallada del proceso de adquisición de los datos</p></body></html>"
|
"del proceso de adquisición de los datos</p></body></html>"
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/user_profiles_ui.py:219
|
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/user_profiles_ui.py:219
|
||||||
msgid "Recipe &title:"
|
msgid "Recipe &title:"
|
||||||
@ -2253,9 +2254,10 @@ msgstr "Ninguna coincidencia"
|
|||||||
msgid "Authors:"
|
msgid "Authors:"
|
||||||
msgstr "Autores:"
|
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
|
#: /home/kovid/work/calibre/src/calibre/gui2/filename_pattern_ui.py:106
|
||||||
msgid "Regular expression group name (?P<authors>)"
|
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
|
#: /home/kovid/work/calibre/src/calibre/gui2/filename_pattern_ui.py:108
|
||||||
msgid "Series:"
|
msgid "Series:"
|
||||||
@ -2348,9 +2350,10 @@ msgstr "Formatos"
|
|||||||
msgid "Book <font face=\"serif\">%s</font> of %s."
|
msgid "Book <font face=\"serif\">%s</font> of %s."
|
||||||
msgstr "Libro <font face=\"serif\">%s</font> de %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
|
#: /home/kovid/work/calibre/src/calibre/gui2/library.py:396
|
||||||
msgid "Double click to <b>edit</b> me<br><br>"
|
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:406
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/library.py:757
|
#: /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"
|
msgid "Add a custom news source"
|
||||||
msgstr "Añadir nueva fuente de noticias"
|
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
|
#: /home/kovid/work/calibre/src/calibre/gui2/news.py:53
|
||||||
msgid ""
|
msgid ""
|
||||||
"<p>Please enter your username and password for %s<br>If you do not have one, "
|
"<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."
|
"please subscribe to get access to the articles.<br/> Click OK to proceed."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"<p>Por favor, introduzca el nombre de usuario y contraseña para %s<br/> Si "
|
"<p>Por favor, introduzca el nombre de usuario y contraseña para %s<br> Si no "
|
||||||
"no tiene uno, por favor dese de alta para obtener acceso a los "
|
"tiene uno, por favor dese de alta para obtener acceso a los artículos.<br/> "
|
||||||
"artículos.<br/> Haga click en OK para continuar."
|
"Haga click en OK para continuar."
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/news.py:79
|
#: /home/kovid/work/calibre/src/calibre/gui2/news.py:79
|
||||||
msgid "Custom news sources"
|
msgid "Custom news sources"
|
||||||
|
@ -1481,6 +1481,7 @@ msgstr "Cambia l'editore di questo libro"
|
|||||||
msgid "Ta&gs: "
|
msgid "Ta&gs: "
|
||||||
msgstr "T&ag: "
|
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/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_bulk_ui.py:127
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:271
|
#: /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."
|
"<br><br>They can be any words or phrases, separated by commas."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"I tag categorizzano un libro. Questo è particolarmente utile durante le "
|
"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"
|
"virgola"
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/lrf_single_ui.py:525
|
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/lrf_single_ui.py:525
|
||||||
@ -2143,6 +2144,7 @@ msgstr ""
|
|||||||
msgid "Recipe source code (python)"
|
msgid "Recipe source code (python)"
|
||||||
msgstr "Codice sorgente formula (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
|
#: /home/kovid/work/calibre/src/calibre/gui2/filename_pattern_ui.py:97
|
||||||
msgid ""
|
msgid ""
|
||||||
"<p>Set a regular expression pattern to use when trying to guess ebook "
|
"<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 "
|
"<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 "
|
"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 "
|
"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 "
|
"sottostante per testare le proprie espressioni regolari su una serie di nomi "
|
||||||
"di file di esempio."
|
"di file di esempio."
|
||||||
|
|
||||||
@ -2294,9 +2296,10 @@ msgstr "Formati"
|
|||||||
msgid "Book <font face=\"serif\">%s</font> of %s."
|
msgid "Book <font face=\"serif\">%s</font> of %s."
|
||||||
msgstr "Libro <font face=\"serif\">%s</font> di %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
|
#: /home/kovid/work/calibre/src/calibre/gui2/library.py:396
|
||||||
msgid "Double click to <b>edit</b> me<br><br>"
|
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:406
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/library.py:757
|
#: /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 "
|
"De reguliere expressie die wordt gebruikt om hoofdstukken te herkennen. Deze "
|
||||||
"wordt gezocht in 'heading tags' (h1-h6). Standaard: %default"
|
"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
|
#: /home/kovid/work/calibre/src/calibre/ebooks/lrf/__init__.py:165
|
||||||
msgid ""
|
msgid ""
|
||||||
"Detect a chapter beginning at an element having the specified attribute. The "
|
"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 "
|
"vind het begin van een hoofdstuk bij een element met het gespecificeerde "
|
||||||
"attribuut. Het formaat voor deze optie is tagnaam regexp, attribuut naam, "
|
"attribuut. Het formaat voor deze optie is tagnaam regexp, attribuut naam, "
|
||||||
"attribuut waarde regexp. Bijvoorbeeld, om alle kop tags te vinden met de "
|
"attribuut waarde regexp. Bijvoorbeeld, om alle kop tags te vinden met de "
|
||||||
"attribuut klasse \"hoofstuk\", gebruik \"h\\d\\klasse,hoofdstuk\". Standaard "
|
"attribuut klasse \"hoofstuk\", gebruik \"h\\d,klasse,hoofdstuk\". Standaard is "
|
||||||
"is %default"
|
"%default"
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/lrf/__init__.py:167
|
#: /home/kovid/work/calibre/src/calibre/ebooks/lrf/__init__.py:167
|
||||||
msgid ""
|
msgid ""
|
||||||
@ -1307,10 +1308,11 @@ msgstr "Je hebt geen permissie om het bestand te lezen: "
|
|||||||
msgid "Error reading file"
|
msgid "Error reading file"
|
||||||
msgstr "Fout bij het lezen van bestand"
|
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/lrf_single.py:183
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single.py:53
|
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single.py:53
|
||||||
msgid "<p>There was an error reading from file: <br /><b>"
|
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
|
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/lrf_single.py:189
|
||||||
msgid " is not a valid picture"
|
msgid " is not a valid picture"
|
||||||
@ -1733,6 +1735,7 @@ msgid "Comma separated list of tags to remove from the books. "
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
"Lijst van tags die moeten worden verwijderd, gescheiden met komma's. "
|
"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
|
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single.py:235
|
||||||
msgid ""
|
msgid ""
|
||||||
"<p>Enter your username and password for <b>LibraryThing.com</b>. <br/>If you "
|
"<p>Enter your username and password for <b>LibraryThing.com</b>. <br/>If you "
|
||||||
@ -1740,8 +1743,8 @@ msgid ""
|
|||||||
"for free!.</p>"
|
"for free!.</p>"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"<p>Geef uw gebruikersnaam en wachtwoord voor <b>LibraryThing.com</b>. "
|
"<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 "
|
"<br/>Als u deze niet heeft, dan kunt u er gratis een krijgen door te <a "
|
||||||
"href='http://www.librarything.com'>registreren</a>"
|
"href='http://www.librarything.com'>registreren</a>.</p>"
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single.py:265
|
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single.py:265
|
||||||
msgid "<b>Could not fetch cover.</b><br/>"
|
msgid "<b>Could not fetch cover.</b><br/>"
|
||||||
@ -2181,26 +2184,29 @@ msgstr "Geen overeenkomst"
|
|||||||
msgid "Authors:"
|
msgid "Authors:"
|
||||||
msgstr "Auteurs:"
|
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
|
#: /home/kovid/work/calibre/src/calibre/gui2/filename_pattern_ui.py:106
|
||||||
msgid "Regular expression group name (?P<authors>)"
|
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
|
#: /home/kovid/work/calibre/src/calibre/gui2/filename_pattern_ui.py:108
|
||||||
msgid "Series:"
|
msgid "Series:"
|
||||||
msgstr "Serie:"
|
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
|
#: /home/kovid/work/calibre/src/calibre/gui2/filename_pattern_ui.py:109
|
||||||
msgid "Regular expression group name (?P<series>)"
|
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
|
#: /home/kovid/work/calibre/src/calibre/gui2/filename_pattern_ui.py:111
|
||||||
msgid "Series index:"
|
msgid "Series index:"
|
||||||
msgstr "Serie 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:112
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/filename_pattern_ui.py:115
|
#: /home/kovid/work/calibre/src/calibre/gui2/filename_pattern_ui.py:115
|
||||||
msgid "Regular expression group name (?P<series_index>)"
|
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
|
#: /home/kovid/work/calibre/src/calibre/gui2/filename_pattern_ui.py:114
|
||||||
msgid "ISBN:"
|
msgid "ISBN:"
|
||||||
@ -2825,13 +2831,14 @@ msgstr "FOUT: Niet-verwerkte uitzondering"
|
|||||||
msgid "Add a custom news source"
|
msgid "Add a custom news source"
|
||||||
msgstr "Voeg een persoonlijke nieuwsbron toe"
|
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
|
#: /home/kovid/work/calibre/src/calibre/gui2/news.py:53
|
||||||
msgid ""
|
msgid ""
|
||||||
"<p>Please enter your username and password for %s<br>If you do not have one, "
|
"<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."
|
"please subscribe to get access to the articles.<br/> Click OK to proceed."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"<p>Voer uw gebruikersnaam en wachtwoord voor %s in.<br>Als u er geen geeft, "
|
"<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."
|
"verder te gaan."
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/news.py:79
|
#: /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. "
|
"Maximum aantal level om recursief te zoeken -- de diepte om links te volgen. "
|
||||||
"Standaard %default"
|
"Standaard %default"
|
||||||
|
|
||||||
|
# (pofilter) xmltags: checks that XML/HTML tags have not been translated
|
||||||
#: /home/kovid/work/calibre/src/calibre/web/fetch/simple.py:394
|
#: /home/kovid/work/calibre/src/calibre/web/fetch/simple.py:394
|
||||||
msgid ""
|
msgid ""
|
||||||
"The maximum number of files to download. This only applies to files from <a "
|
"The maximum number of files to download. This only applies to files from <a "
|
||||||
"href> tags. Default is %default"
|
"href> tags. Default is %default"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Het maximum aantal bestanden te downloaden. Dit is alleen van toepassing op "
|
"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
|
#: /home/kovid/work/calibre/src/calibre/web/fetch/simple.py:396
|
||||||
msgid ""
|
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
@ -33,14 +33,26 @@ except:
|
|||||||
preferred_encoding = 'utf-8'
|
preferred_encoding = 'utf-8'
|
||||||
|
|
||||||
iswindows = 'win32' in sys.platform or 'win64' in sys.platform
|
iswindows = 'win32' in sys.platform or 'win64' in sys.platform
|
||||||
isosx = 'darwin' 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():
|
def load_library():
|
||||||
if isosx:
|
if isosx:
|
||||||
if os.path.exists('/usr/X11/lib/libfontconfig.1.dylib'): # The fontconfig shipped with calibre doesn't work on Leopard
|
lib = os.path.join(getattr(sys, 'frameworks_dir'), 'libfontconfig.1.dylib') \
|
||||||
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')
|
if hasattr(sys, 'frameworks_dir') else util.find_library('fontconfig')
|
||||||
return cdll.LoadLibrary(lib)
|
return cdll.LoadLibrary(lib)
|
||||||
elif iswindows:
|
elif iswindows:
|
||||||
@ -159,9 +171,9 @@ class FontScanner(Thread):
|
|||||||
global _initialized
|
global _initialized
|
||||||
_initialized = True
|
_initialized = True
|
||||||
|
|
||||||
|
if not DISABLED:
|
||||||
_scanner = FontScanner()
|
_scanner = FontScanner()
|
||||||
_scanner.start()
|
_scanner.start()
|
||||||
|
|
||||||
def join():
|
def join():
|
||||||
_scanner.join(120)
|
_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
|
`allowed_extensions`: A list of allowed extensions for font file types. Defaults to
|
||||||
`['ttf', 'otf']`. If it is empty, it is ignored.
|
`['ttf', 'otf']`. If it is empty, it is ignored.
|
||||||
'''
|
'''
|
||||||
|
if DISABLED:
|
||||||
|
return []
|
||||||
join()
|
join()
|
||||||
allowed_extensions = [i.lower() for i in allowed_extensions]
|
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
|
they are a tuple (slant, weight) otherwise they are strings from the set
|
||||||
`('normal', 'bold', 'italic', 'bi', 'light', 'li')`
|
`('normal', 'bold', 'italic', 'bi', 'light', 'li')`
|
||||||
'''
|
'''
|
||||||
|
if DISABLED:
|
||||||
|
return {}
|
||||||
join()
|
join()
|
||||||
if isinstance(family, unicode):
|
if isinstance(family, unicode):
|
||||||
family = family.encode(preferred_encoding)
|
family = family.encode(preferred_encoding)
|
||||||
@ -295,6 +311,8 @@ def match(name, sort=False, verbose=False):
|
|||||||
decreasing closeness of matching.
|
decreasing closeness of matching.
|
||||||
`verbose`: If `True` print debugging information to stdout
|
`verbose`: If `True` print debugging information to stdout
|
||||||
'''
|
'''
|
||||||
|
if DISABLED:
|
||||||
|
return []
|
||||||
join()
|
join()
|
||||||
if isinstance(name, unicode):
|
if isinstance(name, unicode):
|
||||||
name = name.encode(preferred_encoding)
|
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,36 +163,50 @@ class ProgressBar:
|
|||||||
|
|
||||||
The progress bar is colored, if the terminal supports color
|
The progress bar is colored, if the terminal supports color
|
||||||
output; and adjusts to the width of the terminal.
|
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'
|
BAR = '%3d%% ${GREEN}[${BOLD}%s%s${NORMAL}${GREEN}]${NORMAL}\n'
|
||||||
HEADER = '${BOLD}${CYAN}%s${NORMAL}\n\n'
|
HEADER = '${BOLD}${CYAN}%s${NORMAL}\n\n'
|
||||||
|
|
||||||
def __init__(self, term, header):
|
def __init__(self, term, header, no_progress_bar = False):
|
||||||
self.term = term
|
self.term, self.no_progress_bar = term, no_progress_bar
|
||||||
if not (self.term.CLEAR_EOL and self.term.UP and self.term.BOL):
|
self.fancy = self.term.CLEAR_EOL and self.term.UP and self.term.BOL
|
||||||
raise ValueError("Terminal isn't capable enough -- you "
|
if self.fancy:
|
||||||
"should use a simpler progress dispaly.")
|
self.width = self.term.COLS or 75
|
||||||
self.width = self.term.COLS or 75
|
self.bar = term.render(self.BAR)
|
||||||
self.bar = term.render(self.BAR)
|
self.header = self.term.render(self.HEADER % header.center(self.width))
|
||||||
self.header = self.term.render(self.HEADER % header.center(self.width))
|
self.cleared = 1 #: true if we haven't drawn the bar yet.
|
||||||
self.cleared = 1 #: true if we haven't drawn the bar yet.
|
|
||||||
|
|
||||||
def update(self, percent, message=''):
|
def update(self, percent, message=''):
|
||||||
if isinstance(message, unicode):
|
if isinstance(message, unicode):
|
||||||
message = message.encode('utf-8', 'ignore')
|
message = message.encode('utf-8', 'replace')
|
||||||
if self.cleared:
|
|
||||||
sys.stdout.write(self.header)
|
if self.no_progress_bar:
|
||||||
self.cleared = 0
|
if message:
|
||||||
n = int((self.width-10)*percent)
|
print message
|
||||||
msg = message.center(self.width)
|
elif self.fancy:
|
||||||
sys.stdout.write(
|
if self.cleared:
|
||||||
self.term.BOL + self.term.UP + self.term.CLEAR_EOL +
|
sys.stdout.write(self.header)
|
||||||
(self.bar % (100*percent, '='*n, '-'*(self.width-10-n))) +
|
self.cleared = 0
|
||||||
self.term.CLEAR_EOL + msg)
|
n = int((self.width-10)*percent)
|
||||||
sys.stdout.flush()
|
msg = message.center(self.width)
|
||||||
|
sys.stdout.write(
|
||||||
|
self.term.BOL + self.term.UP + self.term.CLEAR_EOL +
|
||||||
|
(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):
|
def clear(self):
|
||||||
if not self.cleared:
|
if self.fancy and not self.cleared:
|
||||||
sys.stdout.write(self.term.BOL + self.term.CLEAR_EOL +
|
sys.stdout.write(self.term.BOL + self.term.CLEAR_EOL +
|
||||||
self.term.UP + self.term.CLEAR_EOL +
|
self.term.UP + 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
|
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):
|
class RecipeError(Exception):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def run_recipe(opts, recipe_arg, parser, notification=None, handler=None):
|
def run_recipe(opts, recipe_arg, parser, notification=None, handler=None):
|
||||||
if notification is None:
|
if notification is None:
|
||||||
from calibre.terminfo import TerminalController, ProgressBar
|
from calibre.utils.terminfo import TerminalController, ProgressBar
|
||||||
term = TerminalController(sys.stdout)
|
term = TerminalController(sys.stdout)
|
||||||
if opts.progress_bar:
|
pb = ProgressBar(term, _('Fetching feeds...'), no_progress_bar=opts.progress_bar)
|
||||||
try:
|
notification = pb.update
|
||||||
pb = ProgressBar(term, _('Fetching feeds...'))
|
|
||||||
notification = pb.update
|
|
||||||
except ValueError:
|
|
||||||
notification = simple_progress_bar
|
|
||||||
print _('Fetching feeds...')
|
|
||||||
else:
|
|
||||||
notification = no_progress_bar
|
|
||||||
|
|
||||||
|
|
||||||
recipe, is_profile = None, False
|
recipe, is_profile = None, False
|
||||||
if opts.feeds is not None:
|
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.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 option_parser as web2disk_option_parser
|
||||||
from calibre.web.fetch.simple import RecursiveFetcher
|
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.ebooks.lrf.web.profiles import FullContentProfile
|
||||||
from calibre.ptempfile import PersistentTemporaryFile
|
from calibre.ptempfile import PersistentTemporaryFile
|
||||||
|
|
||||||
|
31
upload.py
31
upload.py
@ -29,10 +29,10 @@ BUILD_SCRIPT ='''\
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
cd ~/build && \
|
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 . && \
|
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 && \
|
mkdir -p build dist src/calibre/plugins && \
|
||||||
%%s && \
|
%%s && \
|
||||||
rm -rf build/* dist/* && \
|
rm -rf build/* && \
|
||||||
%%s %%s
|
%%s %%s
|
||||||
'''%dict(host=HOST, project=PROJECT)
|
'''%dict(host=HOST, project=PROJECT)
|
||||||
check_call = partial(_check_call, shell=True)
|
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(('scp', t.name, ssh_host+':build-'+PROJECT))
|
||||||
subprocess.check_call('ssh -t %s bash build-%s'%(ssh_host, PROJECT), shell=True)
|
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):
|
def build_windows(shutdown=True):
|
||||||
installer = installer_name('exe')
|
installer = installer_name('exe')
|
||||||
vm = '/vmware/Windows XP/Windows XP Professional.vmx'
|
vm = '/vmware/Windows XP/Windows XP Professional.vmx'
|
||||||
@ -72,20 +81,14 @@ def build_windows(shutdown=True):
|
|||||||
raise Exception('Failed to run py2exe')
|
raise Exception('Failed to run py2exe')
|
||||||
if shutdown:
|
if shutdown:
|
||||||
subprocess.Popen(('ssh', 'windows', 'shutdown', '-s', '-t', '0'))
|
subprocess.Popen(('ssh', 'windows', 'shutdown', '-s', '-t', '0'))
|
||||||
ibp = os.path.abspath('installer/windows')
|
run_windows_install_jammer(installer)
|
||||||
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')
|
|
||||||
return os.path.basename(installer)
|
return os.path.basename(installer)
|
||||||
|
|
||||||
def build_osx(shutdown=True):
|
def build_osx(shutdown=True):
|
||||||
installer = installer_name('dmg')
|
installer = installer_name('dmg')
|
||||||
vm = '/vmware/Mac OSX/Mac OSX.vmx'
|
vm = '/vmware/Mac OSX/Mac OSX.vmx'
|
||||||
python = '/Library/Frameworks/Python.framework/Versions/Current/bin/python'
|
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'))
|
subprocess.check_call(('scp', 'osx:build/%s/dist/*.dmg'%PROJECT, 'dist'))
|
||||||
if not os.path.exists(installer):
|
if not os.path.exists(installer):
|
||||||
raise Exception('Failed to build installer '+installer)
|
raise Exception('Failed to build installer '+installer)
|
||||||
@ -97,7 +100,7 @@ def build_osx(shutdown=True):
|
|||||||
def build_linux(shutdown=True):
|
def build_linux(shutdown=True):
|
||||||
installer = installer_name('tar.bz2')
|
installer = installer_name('tar.bz2')
|
||||||
vm = '/vmware/linux/libprs500-gentoo.vmx'
|
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'))
|
subprocess.check_call(('scp', 'linux:/tmp/%s'%os.path.basename(installer), 'dist'))
|
||||||
if not os.path.exists(installer):
|
if not os.path.exists(installer):
|
||||||
raise Exception('Failed to build installer '+installer)
|
raise Exception('Failed to build installer '+installer)
|
||||||
@ -218,8 +221,8 @@ def stage_one():
|
|||||||
os.mkdir('build')
|
os.mkdir('build')
|
||||||
shutil.rmtree('docs')
|
shutil.rmtree('docs')
|
||||||
os.mkdir('docs')
|
os.mkdir('docs')
|
||||||
check_call("sudo python setup.py develop", shell=True)
|
check_call(['python', 'setup.py', 'build'])
|
||||||
check_call('sudo rm src/%s/gui2/images_rc.pyc'%__appname__, shell=True)
|
check_call('sudo rm -f src/%s/gui2/images_rc.pyc'%__appname__, shell=True)
|
||||||
check_call('make', shell=True)
|
check_call('make', shell=True)
|
||||||
tag_release()
|
tag_release()
|
||||||
upload_demo()
|
upload_demo()
|
||||||
@ -227,7 +230,7 @@ def stage_one():
|
|||||||
def stage_two():
|
def stage_two():
|
||||||
subprocess.check_call('rm -rf dist/*', shell=True)
|
subprocess.check_call('rm -rf dist/*', shell=True)
|
||||||
build_installers()
|
build_installers()
|
||||||
build_src_tarball()
|
build_src_tarball()
|
||||||
|
|
||||||
def stage_three():
|
def stage_three():
|
||||||
print 'Uploading installers...'
|
print 'Uploading installers...'
|
||||||
|
Loading…
x
Reference in New Issue
Block a user