IMP: Added HTTPS support, with certificate/key generation, FIX: If a series had a ', search results would miss some key results when not hitting rss feeds, IMP: Better handling of series' that have non-alphanumeric characters when it comes to requesting search results, FIX: Removed some unnecessary spamming when file-checking/manual post-processing in relation to # signs

This commit is contained in:
evilhero 2015-01-24 21:26:22 -05:00
parent e80c39c085
commit cd5a8b2be5
10 changed files with 346 additions and 44 deletions

View File

@ -15,6 +15,8 @@
# along with Mylar. If not, see <http://www.gnu.org/licenses/>.
import os, sys, locale
import errno
import shutil
import time
import threading
import signal
@ -64,6 +66,7 @@ def main():
parser.add_argument('-q', '--quiet', action='store_true', help='Turn off console logging')
parser.add_argument('-d', '--daemon', action='store_true', help='Run as a daemon')
parser.add_argument('-p', '--port', type=int, help='Force mylar to run on a specified port')
parser.add_argument('-b', '--backup', action='store_true', help='Will automatically backup & keep the last 2 copies of the .db & ini files prior to startup')
parser.add_argument('--datadir', help='Specify a directory where to store your data files')
parser.add_argument('--config', help='Specify a config file to use')
parser.add_argument('--nolaunch', action='store_true', help='Prevent browser from launching on startup')
@ -85,7 +88,6 @@ def main():
# except Exception, e:
# sys.exit('Mylar failed to update.')
if args.daemon:
if sys.platform == 'win32':
print "Daemonize not supported under Windows, starting normally"
@ -142,6 +144,47 @@ def main():
# Put the database in the DATA_DIR
mylar.DB_FILE = os.path.join(mylar.DATA_DIR, 'mylar.db')
# backup the db and configs before they load.
if args.backup:
print '[AUTO-BACKUP] Backing up .db and config.ini files for safety.'
backupdir = os.path.join(mylar.DATA_DIR, 'backup')
try:
os.makedirs(backupdir)
print '[AUTO-BACKUP] Directory does not exist for backup - creating : ' + backupdir
except OSError as exception:
if exception.errno != errno.EEXIST:
print '[AUTO-BACKUP] Directory already exists.'
raise
i = 0
while (i < 2):
if i == 0:
ogfile = mylar.DB_FILE
back = os.path.join(backupdir, 'mylar.db')
back_1 = os.path.join(backupdir, 'mylar.db.1')
else:
ogfile = mylar.CONFIG_FILE
back = os.path.join(backupdir, 'config.ini')
back_1 = os.path.join(backupdir, 'config.ini.1')
try:
print '[AUTO-BACKUP] Now Backing up mylar.db file'
if os.path.isfile(back_1):
print '[AUTO-BACKUP] ' + back_1 + ' exists. Deleting and keeping new.'
os.remove(back_1)
if os.path.isfile(back):
print '[AUTO-BACKUP] Now renaming ' + back + ' to ' + back_1
shutil.move(back, back_1)
print '[AUTO-BACKUP] Now copying db file to ' + back
shutil.copy(ogfile, back)
except OSError as exception:
if exception.errno != errno.EXIST:
raise
i+=1
mylar.CFG = ConfigObj(mylar.CONFIG_FILE, encoding='utf-8')
# Rename the main thread
@ -160,16 +203,32 @@ def main():
else:
http_port = int(mylar.HTTP_PORT)
# Check if pyOpenSSL is installed. It is required for certificate generation
# and for CherryPy.
if mylar.ENABLE_HTTPS:
try:
import OpenSSL
except ImportError:
logger.warn("The pyOpenSSL module is missing. Install this " \
"module to enable HTTPS. HTTPS will be disabled.")
mylar.ENABLE_HTTPS = False
# Try to start the server. Will exit here is address is already in use.
web_config = {
'http_port': http_port,
'http_host': mylar.HTTP_HOST,
'http_root': mylar.HTTP_ROOT,
'enable_https': mylar.ENABLE_HTTPS,
'https_cert': mylar.HTTPS_CERT,
'https_key': mylar.HTTPS_KEY,
'http_username': mylar.HTTP_USERNAME,
'http_password': mylar.HTTP_PASSWORD,
}
# Try to start the server.
webstart.initialize({
'http_port': http_port,
'http_host': mylar.HTTP_HOST,
'http_root': mylar.HTTP_ROOT,
'http_username': mylar.HTTP_USERNAME,
'http_password': mylar.HTTP_PASSWORD,
})
webstart.initialize(web_config)
logger.info('Starting Mylar on port: %i' % http_port)
#logger.info('Starting Mylar on port: %i' % http_port)
if mylar.LAUNCH_BROWSER and not args.nolaunch:
mylar.launch_browser(mylar.HTTP_HOST, http_port, mylar.HTTP_ROOT)

View File

@ -54,7 +54,7 @@
<div align="center">
<label><strong>Mylar is free to use,</br>
but you can contribute and support the development</br>
by giving a donation</strong></label></br></br>
by buying me a coffee (or several)</strong></label></br></br>
</div>
<div style="width: 55%; margin: 0px auto;">
<a href="https://flattr.com/submit/auto?user_id=evilhero&url=https://github.com/evilhero/mylar&title=Mylar%20Donation%description=Supporting&20the%development%20of%20Mylar&language=en_CA&hidden=1&category=software" target="_blank">
@ -120,9 +120,27 @@
<input type="text" name="http_host" value="${config['http_host']}" size="30">
<small>e.g. localhost or 0.0.0.0</small>
</div>
<div class="row">
<label>HTTP Port</label>
<input type="text" name="http_port" value="${config['http_port']}" size="10">
<div>
<div class="row">
<label>HTTP Port</label>
<input type="text" name="http_port" value="${config['http_port']}" size="10">
<div class="row checkbox">
<input type="checkbox" name="enable_https" id="enable_https" value="1" ${config['enable_https']} />
<label title="Enable HTTPS for web server for encrypted communication">
Enable HTTPS
</label>
</div>
<div id="https_options">
<div class="row">
<label>HTTPS Cert</label>
<input type="text" title="the FULL path to the certificate" name="https_cert" value="${config['https_cert']}" size="30">
</div>
<div class="row">
<label>HTTPS Key</label>
<input type="text" title="the FULL path to the key" name="https_key" value="${config['https_key']}" size="30">
</div>
</div>
</div>
<div class="row">
<label>HTTP Username</label>
@ -136,6 +154,7 @@
<div class="row checkbox">
<input type="checkbox" name="launch_browser" value="1" ${config['launch_browser']} /> <label>Launch Browser on Startup</label>
</div>
<!--
<div class="row checkbox">
<input type="checkbox" name="logverbose" value="2" ${config['logverbose']} /> <label>Verbose Logging</label>
@ -150,6 +169,12 @@
<input type="checkbox" name="cvapifix" value="1" ${config['cvapifix']} /> <label>Comicvine URL Fix</label>
<br/><small>*Use this if CV's URL has changed*</small>
</div>
<!--
<div class="row checkbox">
<input type="checkbox" name="auto_update" value="1" ${config['auto_update']} /> <label>Automatic Updates</label>
<br/><small>Install new updates with no intervention</small>
</div>
-->
</fieldset>
<fieldset>
<legend>Annual Handling</legend>
@ -1149,7 +1174,24 @@
$('#api_key').val(data);
});
});
if ($("#enable_https").is(":checked"))
{
$("#https_options").show();
}
else
{
$("#https_options").hide();
}
$("#enable_https").click(function(){
if ($("#enable_https").is(":checked"))
{
$("#https_options").slideDown();
}
else
{
$("#https_options").slideUp();
}
});
$('#sab_apikey').click(function(){ $('#sab_apikey').select() });
$("#find_sabapi").click(function(){
$.get('findsabAPI',
@ -1185,6 +1227,7 @@
});
initActions();
initConfigCheckbox("#launch_browser");
initConfigCheckbox("#enable_https");
initConfigCheckbox("#enable_api");
initConfigCheckbox("#usenewznab");
initConfigCheckbox("#usenzbsu");

82
lib/certgen.py Normal file
View File

@ -0,0 +1,82 @@
# -*- coding: latin-1 -*-
#
# Copyright (C) Martin Sjögren and AB Strakt 2001, All rights reserved
# Copyright (C) Jean-Paul Calderone 2008, All rights reserved
# This file is licenced under the GNU LESSER GENERAL PUBLIC LICENSE Version 2.1 or later (aka LGPL v2.1)
# Please see LGPL2.1.txt for more information
"""
Certificate generation module.
"""
from OpenSSL import crypto
import time
TYPE_RSA = crypto.TYPE_RSA
TYPE_DSA = crypto.TYPE_DSA
serial = int(time.time())
def createKeyPair(type, bits):
"""
Create a public/private key pair.
Arguments: type - Key type, must be one of TYPE_RSA and TYPE_DSA
bits - Number of bits to use in the key
Returns: The public/private key pair in a PKey object
"""
pkey = crypto.PKey()
pkey.generate_key(type, bits)
return pkey
def createCertRequest(pkey, digest="md5", **name):
"""
Create a certificate request.
Arguments: pkey - The key to associate with the request
digest - Digestion method to use for signing, default is md5
**name - The name of the subject of the request, possible
arguments are:
C - Country name
ST - State or province name
L - Locality name
O - Organization name
OU - Organizational unit name
CN - Common name
emailAddress - E-mail address
Returns: The certificate request in an X509Req object
"""
req = crypto.X509Req()
subj = req.get_subject()
for (key,value) in name.items():
setattr(subj, key, value)
req.set_pubkey(pkey)
req.sign(pkey, digest)
return req
def createCertificate(req, (issuerCert, issuerKey), serial, (notBefore, notAfter), digest="md5"):
"""
Generate a certificate given a certificate request.
Arguments: req - Certificate reqeust to use
issuerCert - The certificate of the issuer
issuerKey - The private key of the issuer
serial - Serial number for the certificate
notBefore - Timestamp (relative to now) when the certificate
starts being valid
notAfter - Timestamp (relative to now) when the certificate
stops being valid
digest - Digest method to use for signing, default is md5
Returns: The signed certificate in an X509 object
"""
cert = crypto.X509()
cert.set_serial_number(serial)
cert.gmtime_adj_notBefore(notBefore)
cert.gmtime_adj_notAfter(notAfter)
cert.set_issuer(issuerCert.get_subject())
cert.set_subject(req.get_subject())
cert.set_pubkey(req.get_pubkey())
cert.sign(issuerKey, digest)
return cert

View File

@ -51,6 +51,7 @@ DAEMON = False
PIDFILE= None
CREATEPID = False
SAFESTART = False
AUTO_UPDATE = False
SCHED = Scheduler()
@ -104,6 +105,9 @@ HTTP_HOST = None
HTTP_USERNAME = None
HTTP_PASSWORD = None
HTTP_ROOT = None
ENABLE_HTTPS = False
HTTPS_CERT = None
HTTPS_KEY = None
HTTPS_FORCE_ON = False
API_ENABLED = False
API_KEY = None
@ -373,7 +377,7 @@ def initialize():
with INIT_LOCK:
global __INITIALIZED__, DBCHOICE, DBUSER, DBPASS, DBNAME, COMICVINE_API, DEFAULT_CVAPI, CVAPI_COUNT, CVAPI_TIME, CVAPI_MAX, FULL_PATH, PROG_DIR, VERBOSE, DAEMON, COMICSORT, DATA_DIR, CONFIG_FILE, CFG, CONFIG_VERSION, LOG_DIR, CACHE_DIR, MAX_LOGSIZE, LOGVERBOSE, OLDCONFIG_VERSION, OS_DETECT, OS_LANG, OS_ENCODING, \
queue, HTTP_PORT, HTTP_HOST, HTTP_USERNAME, HTTP_PASSWORD, HTTP_ROOT, HTTPS_FORCE_ON, API_ENABLED, API_KEY, LAUNCH_BROWSER, GIT_PATH, SAFESTART, \
queue, HTTP_PORT, HTTP_HOST, HTTP_USERNAME, HTTP_PASSWORD, HTTP_ROOT, ENABLE_HTTPS, HTTPS_CERT, HTTPS_KEY, HTTPS_FORCE_ON, API_ENABLED, API_KEY, LAUNCH_BROWSER, GIT_PATH, SAFESTART, AUTO_UPDATE, \
CURRENT_VERSION, LATEST_VERSION, CHECK_GITHUB, CHECK_GITHUB_ON_STARTUP, CHECK_GITHUB_INTERVAL, USER_AGENT, DESTINATION_DIR, MULTIPLE_DEST_DIRS, CREATE_FOLDERS, \
DOWNLOAD_DIR, USENET_RETENTION, SEARCH_INTERVAL, NZB_STARTUP_SEARCH, INTERFACE, DUPECONSTRAINT, AUTOWANT_ALL, AUTOWANT_UPCOMING, ZERO_LEVEL, ZERO_LEVEL_N, COMIC_COVER_LOCAL, HIGHCOUNT, \
LIBRARYSCAN, LIBRARYSCAN_INTERVAL, DOWNLOAD_SCAN_INTERVAL, NZB_DOWNLOADER, USE_SABNZBD, SAB_HOST, SAB_USERNAME, SAB_PASSWORD, SAB_APIKEY, SAB_CATEGORY, SAB_PRIORITY, SAB_DIRECTORY, USE_BLACKHOLE, BLACKHOLE_DIR, ADD_COMICS, COMIC_DIR, IMP_MOVE, IMP_RENAME, IMP_METADATA, \
@ -410,6 +414,11 @@ def initialize():
if HTTP_PORT < 21 or HTTP_PORT > 65535:
HTTP_PORT = 8090
if HTTPS_CERT == '':
HTTPS_CERT = os.path.join(DATA_DIR, 'server.crt')
if HTTPS_KEY == '':
HTTPS_KEY = os.path.join(DATA_DIR, 'server.key')
CONFIG_VERSION = check_setting_str(CFG, 'General', 'config_version', '')
DBCHOICE = check_setting_str(CFG, 'General', 'dbchoice', 'sqlite3')
@ -427,10 +436,14 @@ def initialize():
HTTP_USERNAME = check_setting_str(CFG, 'General', 'http_username', '')
HTTP_PASSWORD = check_setting_str(CFG, 'General', 'http_password', '')
HTTP_ROOT = check_setting_str(CFG, 'General', 'http_root', '/')
ENABLE_HTTPS = bool(check_setting_int(CFG, 'General', 'enable_https', 0))
HTTPS_CERT = check_setting_str(CFG, 'General', 'https_cert', '')
HTTPS_KEY = check_setting_str(CFG, 'General', 'https_key', '')
HTTPS_FORCE_ON = bool(check_setting_int(CFG, 'General', 'https_force_on', 0))
API_ENABLED = bool(check_setting_int(CFG, 'General', 'api_enabled', 0))
API_KEY = check_setting_str(CFG, 'General', 'api_key', '')
LAUNCH_BROWSER = bool(check_setting_int(CFG, 'General', 'launch_browser', 1))
AUTO_UPDATE = bool(check_setting_int(CFG, 'General', 'auto_update', 0))
LOGVERBOSE = bool(check_setting_int(CFG, 'General', 'logverbose', 0))
if LOGVERBOSE:
VERBOSE = 2
@ -924,6 +937,11 @@ def initialize():
else:
LATEST_VERSION = CURRENT_VERSION
# if AUTO_UPDATE:
# if CURRENT_VERSION != LATEST_VERSION and INSTALL_TYPE != 'win' and COMMITS_BEHIND > 0:
# logger.info('Auto-updating has been enabled. Attempting to auto-update.')
# SIGNAL = 'update'
#check for syno_fix here
if SYNO_FIX:
parsepath = os.path.join(DATA_DIR, 'bs4', 'builder', '_lxml.py')
@ -1100,10 +1118,14 @@ def config_write():
new_config['General']['http_username'] = HTTP_USERNAME
new_config['General']['http_password'] = HTTP_PASSWORD
new_config['General']['http_root'] = HTTP_ROOT
new_config['General']['enable_https'] = int(ENABLE_HTTPS)
new_config['General']['https_cert'] = HTTPS_CERT
new_config['General']['https_key'] = HTTPS_KEY
new_config['General']['https_force_on'] = int(HTTPS_FORCE_ON)
new_config['General']['api_enabled'] = int(API_ENABLED)
new_config['General']['api_key'] = API_KEY
new_config['General']['launch_browser'] = int(LAUNCH_BROWSER)
new_config['General']['auto_update'] = int(AUTO_UPDATE)
new_config['General']['log_dir'] = LOG_DIR
new_config['General']['max_logsize'] = MAX_LOGSIZE
new_config['General']['logverbose'] = int(LOGVERBOSE)

View File

@ -447,10 +447,8 @@ def listFiles(dir,watchcomic,Publisher,AlternateSearch=None,manual=None,sarc=Non
fndit = 0
blspc = 0
if nono == '#':
logger.info('# detected.')
fndit = subname.find(nono)
if subname[fndit+1].isdigit():
logger.info('# detected before digits - assuming issue number.')
subname = re.sub('#','',subname)
continue
while x < subcnt:

View File

@ -1649,6 +1649,42 @@ def duplicate_filecheck(filename, ComicID=None, IssueID=None, StoryArcID=None):
rtnval = "write"
return rtnval
def create_https_certificates(ssl_cert, ssl_key):
"""
Create a pair of self-signed HTTPS certificares and store in them in
'ssl_cert' and 'ssl_key'. Method assumes pyOpenSSL is installed.
This code is stolen from SickBeard (http://github.com/midgetspy/Sick-Beard).
"""
from mylar import logger
from OpenSSL import crypto
from lib.certgen import createKeyPair, createCertRequest, createCertificate, \
TYPE_RSA, serial
# Create the CA Certificate
cakey = createKeyPair(TYPE_RSA, 2048)
careq = createCertRequest(cakey, CN="Certificate Authority")
cacert = createCertificate(careq, (careq, cakey), serial, (0, 60 * 60 * 24 * 365 * 10)) # ten years
pkey = createKeyPair(TYPE_RSA, 2048)
req = createCertRequest(pkey, CN="Mylar")
cert = createCertificate(req, (cacert, cakey), serial, (0, 60 * 60 * 24 * 365 * 10)) # ten years
# Save the key and certificate to disk
try:
with open(ssl_key, "w") as fp:
fp.write(crypto.dump_privatekey(crypto.FILETYPE_PEM, pkey))
with open(ssl_cert, "w") as fp:
fp.write(crypto.dump_certificate(crypto.FILETYPE_PEM, cert))
except IOError as e:
logger.error("Error creating SSL key and certificate: %s", e)
return False
return True
from threading import Thread
class ThreadWithReturnValue(Thread):

View File

@ -789,8 +789,9 @@ def nzbdbsearch(seriesname,issue,comicid=None,nzbprov=None,searchYear=None,Comic
return nzbinfo
def torsend2client(seriesname, issue, seriesyear, linkit, site):
logger.info('matched on ' + str(seriesname))
filename = re.sub('[\'\!\@\#\$\%\:\;\/\\=\?\.]', '',seriesname)
logger.info('matched on ' + seriesname)
filename = helpers.filesafe(seriesname)
#filename = re.sub('[\'\!\@\#\$\%\:\;\/\\=\?\.]', '',seriesname)
filename = re.sub(' ', '_', filename)
filename += "_" + str(issue) + "_" + str(seriesyear)
if site == 'CBT':

View File

@ -37,9 +37,14 @@ def search_init(ComicName, IssueNumber, ComicYear, SeriesYear, Publisher, IssueD
unaltered_ComicName = None
if filesafe:
if filesafe != ComicName and mode != 'want_ann':
logger.info('[SEARCH] altering ComicName to search-safe Name : ' + filesafe)
logger.info('[SEARCH] Special Characters exist within Series Title. Enabling search-safe Name : ' + filesafe)
if AlternateSearch is None or AlternateSearch == 'None':
AlternateSearch = filesafe
else:
AlternateSearch += '##' + filesafe
unaltered_ComicName = ComicName
ComicName = filesafe
#ComicName = filesafe
logger.info('AlternateSearch is : ' + AlternateSearch)
if ComicYear == None: ComicYear = '2014'
else: ComicYear = str(ComicYear)[:4]
if Publisher == 'IDW Publishing': Publisher = 'IDW'
@ -464,7 +469,7 @@ def NZB_SEARCH(ComicName, IssueNumber, ComicYear, SeriesYear, Publisher, IssueDa
elif nzbprov == 'KAT':
cmname = re.sub("%20", " ", str(comsrc))
logger.fdebug("Sending request to [KAT] for " + str(cmname) + " : " + str(mod_isssearch))
bb = rsscheck.torrents(pickfeed='KAT',seriesname=cmname,issue=mod_isssearch)
bb = rsscheck.torrents(pickfeed='KAT',seriesname=cmname,issue=mod_isssearch)#cmname,issue=mod_isssearch)
rss = "no"
#if bb is not None: logger.fdebug("results: " + str(bb))
elif nzbprov != 'experimental':
@ -1018,6 +1023,7 @@ def NZB_SEARCH(ComicName, IssueNumber, ComicYear, SeriesYear, Publisher, IssueDa
watchcomic_split = helpers.cleanName(str(findcomic))
if '&' in watchcomic_split: watchcomic_split = re.sub('[/&]','and', watchcomic_split)
watchcomic_nonsplit = re.sub('[\-\:\,\.\?]', ' ', watchcomic_split)
watchcomic_nonsplit = re.sub('\'', '', watchcomic_nonsplit)
watchcomic_split = watchcomic_nonsplit.split(None)
logger.fdebug(str(splitit) + " nzb series word count: " + str(splitst))
@ -1288,7 +1294,7 @@ def NZB_SEARCH(ComicName, IssueNumber, ComicYear, SeriesYear, Publisher, IssueDa
if '[RSS]' in tmpprov : tmpprov = re.sub('\[RSS\]','', tmpprov).strip()
updater.nzblog(IssueID, nzbname, ComicName, SARC, IssueArcID, nzbid, tmpprov)
#send out the notifications for the snatch.
notify_snatch(nzbname, sent_to, modcomicname, comyear, IssueNumber, nzbprov)
notify_snatch(nzbname, sent_to, helpers.filesafe(modcomicname), comyear, IssueNumber, nzbprov)
prov_count == 0
#break
return foundc
@ -1787,7 +1793,7 @@ def searcher(nzbprov, nzbname, comicinfo, link, IssueID, ComicID, tmpprov, direc
if '[RSS]' in tmpprov : tmpprov = re.sub('\[RSS\]','', tmpprov).strip()
updater.nzblog(IssueID, nzbname, ComicName, SARC=None, IssueArcID=None, id=nzbid, prov=tmpprov)
#send out notifications for on snatch after the updater incase notification fails (it would bugger up the updater/pp scripts)
notify_snatch(nzbname, sent_to, modcomicname, comyear, IssueNumber, nzbprov)
notify_snatch(nzbname, sent_to, helpers.filesafe(modcomicname), comyear, IssueNumber, nzbprov)
return
def notify_snatch(nzbname, sent_to, modcomicname, comyear, IssueNumber, nzbprov):

View File

@ -1232,8 +1232,14 @@ class WebInterface(object):
raise cherrypy.HTTPRedirect("pullist")
#return
elif mode == 'want' or mode == 'want_ann' or manualsearch:
cdname = myDB.selectone("SELECT ComicName, ComicName_Filesafe from comics where ComicID=?", [ComicID]).fetchone()
ComicName = cdname['ComicName_Filesafe']
cdname = myDB.selectone("SELECT * from comics where ComicID=?", [ComicID]).fetchone()
ComicName_Filesafe = cdname['ComicName_Filesafe']
SeriesYear = cdname['ComicYear']
AlternateSearch = cdname['AlternateSearch']
Publisher = cdname['ComicPublisher']
UseAFuzzy = cdname['UseFuzzy']
ComicVersion = cdname['ComicVersion']
ComicName = cdname['ComicName']
controlValueDict = {"IssueID": IssueID}
newStatus = {"Status": "Wanted"}
if mode == 'want':
@ -1273,13 +1279,13 @@ class WebInterface(object):
storedate = issues['IssueDate']
else:
storedate = issues['ReleaseDate']
miy = myDB.selectone("SELECT * FROM comics WHERE ComicID=?", [ComicID]).fetchone()
SeriesYear = miy['ComicYear']
AlternateSearch = miy['AlternateSearch']
Publisher = miy['ComicPublisher']
UseAFuzzy = miy['UseFuzzy']
ComicVersion = miy['ComicVersion']
foundcom, prov = search.search_init(ComicName, ComicIssue, ComicYear, SeriesYear, Publisher, issues['IssueDate'], storedate, IssueID, AlternateSearch, UseAFuzzy, ComicVersion, mode=mode, ComicID=ComicID, manualsearch=manualsearch, filesafe=miy['ComicName_Filesafe'])
#miy = myDB.selectone("SELECT * FROM comics WHERE ComicID=?", [ComicID]).fetchone()
#SeriesYear = miy['ComicYear']
#AlternateSearch = miy['AlternateSearch']
#Publisher = miy['ComicPublisher']
#UseAFuzzy = miy['UseFuzzy']
#ComicVersion = miy['ComicVersion']
foundcom, prov = search.search_init(ComicName, ComicIssue, ComicYear, SeriesYear, Publisher, issues['IssueDate'], storedate, IssueID, AlternateSearch, UseAFuzzy, ComicVersion, mode=mode, ComicID=ComicID, manualsearch=manualsearch, filesafe=ComicName_Filesafe)
if foundcom == "yes":
# file check to see if issue exists and update 'have' count
if IssueID is not None:
@ -3120,9 +3126,13 @@ class WebInterface(object):
"http_user" : mylar.HTTP_USERNAME,
"http_port" : mylar.HTTP_PORT,
"http_pass" : mylar.HTTP_PASSWORD,
"enable_https" : helpers.checked(mylar.ENABLE_HTTPS),
"https_cert" : mylar.HTTPS_CERT,
"https_key" : mylar.HTTPS_KEY,
"api_enabled" : helpers.checked(mylar.API_ENABLED),
"api_key" : mylar.API_KEY,
"launch_browser" : helpers.checked(mylar.LAUNCH_BROWSER),
"auto_update" : helpers.checked(mylar.AUTO_UPDATE),
"logverbose" : helpers.checked(mylar.LOGVERBOSE),
"max_logsize" : mylar.MAX_LOGSIZE,
"annuals_on" : helpers.checked(mylar.ANNUALS_ON),
@ -3438,7 +3448,7 @@ class WebInterface(object):
readOptions.exposed = True
def configUpdate(self, comicvine_api=None, http_host='0.0.0.0', http_username=None, http_port=8090, http_password=None, api_enabled=0, api_key=None, launch_browser=0, logverbose=0, annuals_on=0, max_logsize=None, download_scan_interval=None, nzb_search_interval=None, nzb_startup_search=0, libraryscan_interval=None,
def configUpdate(self, comicvine_api=None, http_host='0.0.0.0', http_username=None, http_port=8090, http_password=None, enable_https=0, https_cert=None, https_key=None, api_enabled=0, api_key=None, launch_browser=0, auto_update=0, logverbose=0, annuals_on=0, max_logsize=None, download_scan_interval=None, nzb_search_interval=None, nzb_startup_search=0, libraryscan_interval=None,
nzb_downloader=0, sab_host=None, sab_username=None, sab_apikey=None, sab_password=None, sab_category=None, sab_priority=None, sab_directory=None, log_dir=None, log_level=0, blackhole_dir=None,
nzbget_host=None, nzbget_port=None, nzbget_username=None, nzbget_password=None, nzbget_category=None, nzbget_priority=None, nzbget_directory=None,
usenet_retention=None, nzbsu=0, nzbsu_uid=None, nzbsu_apikey=None, dognzb=0, dognzb_uid=None, dognzb_apikey=None, newznab=0, newznab_host=None, newznab_name=None, newznab_apikey=None, newznab_uid=None, newznab_enabled=0,
@ -3454,9 +3464,13 @@ class WebInterface(object):
mylar.HTTP_PORT = http_port
mylar.HTTP_USERNAME = http_username
mylar.HTTP_PASSWORD = http_password
mylar.ENABLE_HTTPS = enable_https
mylar.HTTPS_CERT = https_cert
mylar.HTTPS_KEY = https_key
mylar.API_ENABLED = api_enabled
mylar.API_KEY = api_key
mylar.LAUNCH_BROWSER = launch_browser
mylar.AUTO_UPDATE = auto_update
mylar.LOGVERBOSE = logverbose
mylar.ANNUALS_ON = int(annuals_on)
mylar.MAX_LOGSIZE = max_logsize

View File

@ -19,19 +19,60 @@ import sys
import cherrypy
import mylar
from mylar import logger
from mylar.webserve import WebInterface
from mylar.helpers import create_https_certificates
def initialize(options={}):
def initialize(options):
# HTTPS stuff stolen from sickbeard
enable_https = options['enable_https']
https_cert = options['https_cert']
https_key = options['https_key']
cherrypy.config.update({
'log.screen': False,
'server.thread_pool': 10,
'server.socket_port': options['http_port'],
'server.socket_host': options['http_host'],
'engine.autoreload_on': False,
})
if enable_https:
# If either the HTTPS certificate or key do not exist, try to make
# self-signed ones.
if not (https_cert and os.path.exists(https_cert)) or not (https_key and os.path.exists(https_key)):
if not create_https_certificates(https_cert, https_key):
logger.warn("Unable to create certificate and key. Disabling " \
"HTTPS")
enable_https = False
if not (os.path.exists(https_cert) and os.path.exists(https_key)):
logger.warn("Disabled HTTPS because of missing certificate and " \
"key.")
enable_https = False
options_dict = {
'server.socket_port': options['http_port'],
'server.socket_host': options['http_host'],
'server.thread_pool': 10,
'tools.encode.on': True,
'tools.encode.encoding': 'utf-8',
'tools.decode.on': True,
'log.screen': False,
'engine.autoreload.on': False,
}
if enable_https:
options_dict['server.ssl_certificate'] = https_cert
options_dict['server.ssl_private_key'] = https_key
protocol = "https"
else:
protocol = "http"
logger.info("Starting Mylar on %s://%s:%d/", protocol,
options['http_host'], options['http_port'])
cherrypy.config.update(options_dict)
# cherrypy.config.update({
# 'log.screen': False,
# 'server.thread_pool': 10,
# 'server.socket_port': options['http_port'],
# 'server.socket_host': options['http_host'],
# 'engine.autoreload_on': False,
# })
conf = {
'/': {
@ -55,7 +96,7 @@ def initialize(options={}):
},
'/favicon.ico':{
'tools.staticfile.on': True,
'tools.staticfile.filename': "images/favicon.ico"
'tools.staticfile.filename': os.path.join(os.path.abspath(os.curdir), 'images' + os.sep + 'favicon.ico')
},
'/cache':{
'tools.staticdir.on': True,
@ -70,7 +111,7 @@ def initialize(options={}):
'tools.auth_basic.checkpassword': cherrypy.lib.auth_basic.checkpassword_dict(
{options['http_username']:options['http_password']})
})
conf['/api'] = {'tools.auth_basic.on': False}
# Prevent time-outs
cherrypy.engine.timeout_monitor.unsubscribe()