Browse Source

Sync with 0.6.x

tags/0.6.0
ShyPike 15 years ago
parent
commit
d4a0c23e37
  1. 16
      NSIS_Installer.nsi
  2. 124
      SABHelper.py
  3. 45
      SABnzbd.py
  4. 6
      interfaces/Classic/templates/config_email.tmpl
  5. 6
      interfaces/Plush/templates/config_email.tmpl
  6. 6
      interfaces/smpl/templates/config_email.tmpl
  7. 3
      language/email-fr-fr.tmpl
  8. 23
      package.py
  9. 54
      sabnzbd/emailer.py
  10. 12
      sabnzbd/encoding.py
  11. 6
      sabnzbd/interface.py
  12. 4
      sabnzbd/misc.py
  13. 35
      sabnzbd/newsunpack.py
  14. 3
      sabnzbd/tvsort.py
  15. 0
      util/__init__.py
  16. 130
      util/mailslot.py

16
NSIS_Installer.nsi

@ -110,6 +110,7 @@ InstallDirRegKey HKEY_LOCAL_MACHINE "SOFTWARE\SABnzbd" ""
!insertmacro MUI_LANGUAGE "German"
!insertmacro MUI_LANGUAGE "Dutch"
!insertmacro MUI_LANGUAGE "Swedish"
!insertmacro MUI_LANGUAGE "Danish"
;--------------------------------
@ -234,11 +235,13 @@ Section "un.$(MsgDelProgram)" Uninstall
Delete "$INSTDIR\language\email-nl-du.tmpl"
Delete "$INSTDIR\language\email-fr-fr.tmpl"
Delete "$INSTDIR\language\email-sv-se.tmpl"
Delete "$INSTDIR\language\email-dk-da.tmpl"
Delete "$INSTDIR\language\de-de.txt"
Delete "$INSTDIR\language\us-en.txt"
Delete "$INSTDIR\language\nl-du.txt"
Delete "$INSTDIR\language\fr-fr.txt"
Delete "$INSTDIR\language\sv-se.txt"
Delete "$INSTDIR\language\dk-da.txt"
RMDir "$INSTDIR\language"
RMDir /r "$INSTDIR\interfaces\Classic"
RMDir /r "$INSTDIR\interfaces\Plush"
@ -326,78 +329,91 @@ SectionEnd
LangString MsgStartSab ${LANG_FRENCH} "Lancer SABnzbd (caché)"
LangString MsgStartSab ${LANG_GERMAN} "SABnzbd starten (unsichtbar)"
LangString MsgStartSab ${LANG_SWEDISH} "Starta SABnzbd (dold)"
LangString MsgStartSab ${LANG_DANISH} "Start SABnzbd (hidden)"
LangString MsgShowRelNote ${LANG_ENGLISH} "Show Release Notes"
LangString MsgShowRelNote ${LANG_DUTCH} "Toon Vrijgave Bericht (Engels)"
LangString MsgShowRelNote ${LANG_FRENCH} "Afficher les notes de version"
LangString MsgShowRelNote ${LANG_GERMAN} "Versionshinweise anzeigen"
LangString MsgShowRelNote ${LANG_SWEDISH} "Visa release noteringar"
LangString MsgShowRelNote ${LANG_DANISH} "Show Release Notes"
LangString MsgSupportUs ${LANG_ENGLISH} "Support the project, Donate!"
LangString MsgSupportUs ${LANG_DUTCH} "Steun het project, Doneer!"
LangString MsgSupportUs ${LANG_FRENCH} "Supportez le projet, faites un don !"
LangString MsgSupportUs ${LANG_GERMAN} "Bitte unterstützen Sie das Projekt durch eine Spende!"
LangString MsgSupportUs ${LANG_SWEDISH} "Donera och stöd detta projekt!"
LangString MsgSupportUs ${LANG_DANISH} "Support the project, Donate!"
LangString MsgCloseSab ${LANG_ENGLISH} "Please close $\"SABnzbd.exe$\" first"
LangString MsgCloseSab ${LANG_DUTCH} "Sluit $\"SABnzbd.exe$\" eerst af"
LangString MsgCloseSab ${LANG_FRENCH} "Quittez $\"SABnzbd.exe$\" avant l\'installation, SVP"
LangString MsgCloseSab ${LANG_GERMAN} "Schliessen Sie bitte zuerst $\"SABnzbd.exe$\"."
LangString MsgCloseSab ${LANG_SWEDISH} "Var vänlig stäng $\"SABnzbd.exe$\" först"
LangString MsgCloseSab ${LANG_DANISH} "Please close $\"SABnzbd.exe$\" first"
LangString MsgOldQueue ${LANG_ENGLISH} " >>>> WARNING <<<<$\r$\n$\r$\nIf not empty, download your current queue with the old program.$\r$\nThe new program will ignore your current queue!"
LangString MsgOldQueue ${LANG_DUTCH} " >>>> WAARSCHUWING <<<<$\r$\n$\r$\nIndien niet leeg, download eerst de gehele huidige wachtrij met het oude programma.$\r$\nHet nieuwe programma zal je huidige wachtrij negeren!"
LangString MsgOldQueue ${LANG_FRENCH} " >>>> ATTENTION <<<<$\r$\n$\r$\nsi votre file d'attente de téléchargement n'est pas vide, terminez la avec la version précédente du programme.$\r$\nLa nouvelle version l'ignorera!"
LangString MsgOldQueue ${LANG_GERMAN} " >>>> ACHTUNG <<<<$\r$\n$\r$\nWarten Sie, bis das alte Programm alle Downloads fertiggestellt hat.$\r$\nDas neue Programm wird die noch ausstehenden Downloads ignorieren!"
LangString MsgOldQueue ${LANG_SWEDISH} " >>>> VARNING <<<<$\r$\n$\r$\nOm kön inte är tom, hämta din nuvarande kö med det gamla programmet.$\r$\nDet nya programmet kommer att ignorera din nuvarande kö!"
LangString MsgOldQueue ${LANG_DANISH} " >>>> WARNING <<<<$\r$\n$\r$\nIf not empty, download your current queue with the old program.$\r$\nThe new program will ignore your current queue!"
LangString MsgUninstall ${LANG_ENGLISH} "This will uninstall SABnzbd from your system"
LangString MsgUninstall ${LANG_DUTCH} "Dit verwijdert SABnzbd van je systeem"
LangString MsgUninstall ${LANG_FRENCH} "Ceci désinstallera SABnzbd de votre système"
LangString MsgUninstall ${LANG_GERMAN} "Dies entfernt SABnzbd von Ihrem System"
LangString MsgUninstall ${LANG_SWEDISH} "Detta kommer att avinstallera SABnzbd från systemet"
LangString MsgUninstall ${LANG_DANISH} "This will uninstall SABnzbd from your system"
LangString MsgRunAtStart ${LANG_ENGLISH} "Run at startup"
LangString MsgRunAtStart ${LANG_DUTCH} "Opstarten bij systeem start"
LangString MsgRunAtStart ${LANG_FRENCH} "Lancer au démarrage"
LangString MsgRunAtStart ${LANG_GERMAN} "Beim Systemstart ausführen"
LangString MsgRunAtStart ${LANG_SWEDISH} "Kör vid uppstart"
LangString MsgRunAtStart ${LANG_DANISH} "Run at startup"
LangString MsgIcon ${LANG_ENGLISH} "Desktop Icon"
LangString MsgIcon ${LANG_DUTCH} "Pictogram op bureaublad"
LangString MsgIcon ${LANG_FRENCH} "Icône sur le Bureau"
LangString MsgIcon ${LANG_GERMAN} "Desktop-Symbol"
LangString MsgIcon ${LANG_SWEDISH} "Skrivbordsikon"
LangString MsgIcon ${LANG_DANISH} "Desktop Icon"
LangString MsgAssoc ${LANG_ENGLISH} "NZB File association"
LangString MsgAssoc ${LANG_DUTCH} "NZB bestanden koppelen aan SABnzbd"
LangString MsgAssoc ${LANG_FRENCH} "Association des fichiers NZB"
LangString MsgAssoc ${LANG_GERMAN} "Mit NZB-Dateien verknüpfen"
LangString MsgAssoc ${LANG_SWEDISH} "NZB Filassosication"
LangString MsgAssoc ${LANG_DANISH} "NZB File association"
LangString MsgDelProgram ${LANG_ENGLISH} "Delete Program"
LangString MsgDelProgram ${LANG_DUTCH} "Verwijder programma"
LangString MsgDelProgram ${LANG_FRENCH} "Supprimer le programme"
LangString MsgDelProgram ${LANG_GERMAN} "Programm löschen"
LangString MsgDelProgram ${LANG_SWEDISH} "Ta bort programmet"
LangString MsgDelProgram ${LANG_DANISH} "Delete Program"
LangString MsgDelSettings ${LANG_ENGLISH} "Delete Settings"
LangString MsgDelSettings ${LANG_DUTCH} "Verwijder instellingen"
LangString MsgDelSettings ${LANG_FRENCH} "Supprimer Paramètres"
LangString MsgDelSettings ${LANG_GERMAN} "Einstellungen löschen"
LangString MsgDelSettings ${LANG_SWEDISH} "Ta bort inställningar"
LangString MsgDelSettings ${LANG_DANISH} "Delete Settings"
LangString MsgDelLogs ${LANG_ENGLISH} "Delete Logs"
LangString MsgDelLogs ${LANG_DUTCH} "Verwijder logging"
LangString MsgDelLogs ${LANG_FRENCH} "Supprimer les logs"
LangString MsgDelLogs ${LANG_GERMAN} "Protokoll löschen"
LangString MsgDelLogs ${LANG_SWEDISH} "Ta bort logg"
LangString MsgDelLogs ${LANG_DANISH} "Delete Logs"
LangString MsgDelCache ${LANG_ENGLISH} "Delete Cache"
LangString MsgDelCache ${LANG_DUTCH} "Verwijder Cache"
LangString MsgDelCache ${LANG_FRENCH} "Supprimer le cache"
LangString MsgDelCache ${LANG_GERMAN} "Cache löschen"
LangString MsgDelCache ${LANG_SWEDISH} "Ta bort temporär-mapp"
LangString MsgDelCache ${LANG_DANISH} "Delete Cache"
Function un.onInit
!insertmacro MUI_UNGETLANGUAGE

124
SABHelper.py

@ -0,0 +1,124 @@
#!/usr/bin/python -OO
# Copyright 2008-2010 The SABnzbd-Team <team@sabnzbd.org>
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program 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. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
import sys
if sys.version_info < (2,4):
print "Sorry, requires Python 2.4 or higher."
sys.exit(1)
import os
import time
import subprocess
#------------------------------------------------------------------------------
try:
import win32api, win32file
import win32serviceutil, win32evtlogutil, win32event, win32service, pywintypes
except ImportError:
print "Sorry, requires Python module PyWin32."
sys.exit(1)
from util.mailslot import MailSlot
#------------------------------------------------------------------------------
WIN_SERVICE = None
#------------------------------------------------------------------------------
def HandleCommandLine(allow_service=True):
""" Handle command line for a Windows Service
Prescribed name that will be called by Py2Exe.
You MUST set 'cmdline_style':'custom' in the package.py!
Returns True when any service commands were detected.
"""
win32serviceutil.HandleCommandLine(SABHelper)
#------------------------------------------------------------------------------
def main():
mail = MailSlot()
if not mail.create(200):
return '- Cannot create Mailslot'
while True:
msg = mail.receive()
if msg == 'restart':
time.sleep(1.0)
res = subprocess.Popen('net start SABnzbd', stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True).stdout.read()
rc = win32event.WaitForMultipleObjects((WIN_SERVICE.hWaitStop,
WIN_SERVICE.overlapped.hEvent), 0, 500)
if rc == win32event.WAIT_OBJECT_0:
mail.disconnect()
return ''
#####################################################################
#
# Windows Service Support
#
import servicemanager
class SABHelper(win32serviceutil.ServiceFramework):
""" Win32 Service Handler """
_svc_name_ = 'SABHelper'
_svc_display_name_ = 'SABnzbd Helper'
_svc_deps_ = ["EventLog", "Tcpip"]
_svc_description_ = 'Automated downloading from Usenet. ' \
'This service helps SABnzbdcd.. to restart itself.'
def __init__(self, args):
global WIN_SERVICE
win32serviceutil.ServiceFramework.__init__(self, args)
self.hWaitStop = win32event.CreateEvent(None, 0, 0, None)
self.overlapped = pywintypes.OVERLAPPED()
self.overlapped.hEvent = win32event.CreateEvent(None, 0, 0, None)
WIN_SERVICE = self
def SvcDoRun(self):
msg = 'SABHelper-service'
self.Logger(servicemanager.PYS_SERVICE_STARTED, msg + ' has started')
res = main()
self.Logger(servicemanager.PYS_SERVICE_STOPPED, msg + ' has stopped' + res)
def SvcStop(self):
self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING)
win32event.SetEvent(self.hWaitStop)
def Logger(self, state, msg):
win32evtlogutil.ReportEvent(self._svc_display_name_,
state, 0,
servicemanager.EVENTLOG_INFORMATION_TYPE,
(self._svc_name_, unicode(msg)))
def ErrLogger(self, msg, text):
win32evtlogutil.ReportEvent(self._svc_display_name_,
servicemanager.PYS_SERVICE_STOPPED, 0,
servicemanager.EVENTLOG_ERROR_TYPE,
(self._svc_name_, unicode(msg)),
unicode(text))
#####################################################################
#
# Platform specific startup code
#
if __name__ == '__main__':
win32serviceutil.HandleCommandLine(SABHelper, argv=sys.argv)

45
SABnzbd.py

@ -97,7 +97,10 @@ try:
import win32api
import win32serviceutil, win32evtlogutil, win32event, win32service, pywintypes
win32api.SetConsoleCtrlHandler(sabnzbd.sig_handler, True)
from util.mailslot import MailSlot
except ImportError:
class MailSlot:
pass
if sabnzbd.WIN32:
print "Sorry, requires Python module PyWin32."
sys.exit(1)
@ -539,7 +542,9 @@ def get_webhost(cherryhost, cherryport, https_port):
if cherryport == https_port:
sabnzbd.cfg.enable_https.set(False)
logging.error(Ta('error-sameHTTP-HTTPS'))
# Should have a translated message, but that's not available yet
#logging.error(Ta('error-sameHTTP-HTTPS'))
logging.error('HTTP and HTTPS ports cannot be the same')
return cherryhost, cherryport, browserhost, https_port
@ -556,15 +561,16 @@ def is_sabnzbd_running(url):
except:
return False
def find_free_port(host, currentport, i=0):
while i >=10 and currentport <= 49151:
def find_free_port(host, currentport):
n = 0
while n < 10 and currentport <= 49151:
try:
cherrypy.process.servers.check_port(host, currentport)
return currentport
except:
currentport+=5
i+=1
return -1
currentport += 5
n += 1
return 0
def check_for_sabnzbd(url, upload_nzbs):
# Check for a running instance of sabnzbd(same version) on this port
@ -923,7 +929,7 @@ def main():
port = find_free_port(browserhost, https_port)
if port > 0:
sabnzbd.cfg.https_port.set(port)
cherryport = port
https_port = port
## NonSSL
try:
cherrypy.process.servers.check_port(browserhost, cherryport)
@ -1194,7 +1200,8 @@ def main():
exit_sab(2)
else:
logging.debug("Failed to start web-interface: ", exc_info = True)
Bail_Out(browserhost, cherryport)
# When error 13 occurs, we have no access rights
Bail_Out(browserhost, cherryport, '13' in str(error))
except socket.error, error:
logging.debug("Failed to start web-interface: ", exc_info = True)
Bail_Out(browserhost, cherryport, access=True)
@ -1283,8 +1290,14 @@ def main():
if pid == 0:
os.execv(sys.executable, args)
elif sabnzbd.WIN_SERVICE:
# Hope for the service manager to restart us
sys.exit(1)
logging.info('Asking the SABnzbdHelper service for a restart')
mail = MailSlot()
if mail.connect():
mail.send('restart')
mail.disconnect()
else:
logging.error('Cannot reach the SABnzbdHelper service')
return
else:
cherrypy.engine._do_execv()
@ -1313,7 +1326,7 @@ if sabnzbd.WIN32:
_svc_name_ = 'SABnzbd'
_svc_display_name_ = 'SABnzbd Binary Newsreader'
_svc_deps_ = ["EventLog", "Tcpip"]
_svc_deps_ = ["EventLog", "Tcpip", "SABHelper"]
_svc_description_ = 'Automated downloading from Usenet. ' \
'Set to "automatic" to start the service at system startup. ' \
'You may need to login with a real user account when you need ' \
@ -1370,6 +1383,13 @@ def prep_service_parms(args):
return serv
SERVICE_MSG = """
You may need to set additional Service parameters.
Run services.msc from a command prompt.
Don't forget to install the Service SABnzbd-helper.exe too!
"""
def HandleCommandLine(allow_service=True):
""" Handle command line for a Windows Service
Prescribed name that will be called by Py2Exe.
@ -1397,8 +1417,7 @@ def HandleCommandLine(allow_service=True):
# Add our own parameter to the Registry
sab_opts = prep_service_parms(sab_opts)
if set_serv_parms(SABnzbd._svc_name_, sab_opts):
print '\nYou may need to set additional Service parameters.\n' \
'Run services.msc from a command prompt.\n'
print SERVICE_MSG
else:
print 'Cannot set required Registry info.'
else:

6
interfaces/Classic/templates/config_email.tmpl

@ -11,9 +11,9 @@
<fieldset class="EntryFieldSet">
<legend>$T('emailOptions')</legend>
<strong>$T('opt-email_endjob')</strong><br/>
<input type="radio" name="email_endjob" value="0" <!--#if $email_endjob == 0 then "checked=1" else ""#--> /> $T('email-never')
<input type="radio" name="email_endjob" value="1" <!--#if $email_endjob == 1 then "checked=1" else ""#--> /> $T('email-always')
<input type="radio" name="email_endjob" value="2" <!--#if $email_endjob == 2 then "checked=1" else ""#--> /> $T('email-errorOnly')
<input type="radio" name="email_endjob" value="0" <!--#if $email_endjob == "0" then "checked=1" else ""#--> /> $T('email-never')
<input type="radio" name="email_endjob" value="1" <!--#if $email_endjob == "1" then "checked=1" else ""#--> /> $T('email-always')
<input type="radio" name="email_endjob" value="2" <!--#if $email_endjob == "2" then "checked=1" else ""#--> /> $T('email-errorOnly')
<br/><br/>
<label><input type="checkbox" name="email_full" value="1" <!--#if $email_full > 0 then "checked=1" else ""#--> /> <strong>$T('opt-email_full'):</strong></label><br>
$T('explain-email_full')<br/>

6
interfaces/Plush/templates/config_email.tmpl

@ -11,9 +11,9 @@
<legend><span class="config_sprite_container sprite_config_email_options">&nbsp;</span> $T('emailOptions')</legend>
<strong>$T('opt-email_endjob'):</strong><br/>
<input type="radio" name="email_endjob" value="0" <!--#if $email_endjob == 0 then "checked=1" else ""#--> /> $T('email-never')
<input type="radio" name="email_endjob" value="1" <!--#if $email_endjob == 1 then "checked=1" else ""#--> /> $T('email-always')
<input type="radio" name="email_endjob" value="2" <!--#if $email_endjob == 2 then "checked=1" else ""#--> /> $T('email-errorOnly')
<input type="radio" name="email_endjob" value="0" <!--#if $email_endjob == "0" then "checked=1" else ""#--> /> $T('email-never')
<input type="radio" name="email_endjob" value="1" <!--#if $email_endjob == "1" then "checked=1" else ""#--> /> $T('email-always')
<input type="radio" name="email_endjob" value="2" <!--#if $email_endjob == "2" then "checked=1" else ""#--> /> $T('email-errorOnly')
<br/><br/>
<input type="checkbox" name="email_full" value="1" <!--#if $email_full > 0 then "checked=1" else ""#--> />

6
interfaces/smpl/templates/config_email.tmpl

@ -8,9 +8,9 @@
<span class="label">$T('opt-email_endjob'):</span>
<input class="radio" type="radio" name="email_endjob" value="0" <!--#if $email_endjob == 0 then "checked=1" else ""#--> /> $T('email-never')
<input class="radio" type="radio" name="email_endjob" value="1" <!--#if $email_endjob == 1 then "checked=1" else ""#--> /> $T('email-always')
<input class="radio" type="radio" name="email_endjob" value="2" <!--#if $email_endjob == 2 then "checked=1" else ""#--> /> $T('email-errorOnly')
<input class="radio" type="radio" name="email_endjob" value="0" <!--#if $email_endjob == "0" then "checked=1" else ""#--> /> $T('email-never')
<input class="radio" type="radio" name="email_endjob" value="1" <!--#if $email_endjob == "1" then "checked=1" else ""#--> /> $T('email-always')
<input class="radio" type="radio" name="email_endjob" value="2" <!--#if $email_endjob == "2" then "checked=1" else ""#--> /> $T('email-errorOnly')
<span class="tips">$T('opt-email_endjob')</span>
<br class="clear" />

3
language/email-fr-fr.tmpl

@ -1,3 +1,4 @@
#encoding UTF-8
##
## Template Email pour SABnzbd
## Ceci est un template Cheetah
@ -9,7 +10,7 @@
to: $to
from: $from
date: $date
subject: SABnzbd <!--#if $status then "Succès" else "Echec" #--> du téléchargement $name
subject: SABnzbd <!--#if $status#-->Succès<!--#else#-->Echec<!--#end if#--> du téléchargement $name
X-priority: 5
X-MS-priority: 5
## Le contenu du message, la ligne vide est obligatoire !

23
package.py

@ -243,7 +243,7 @@ else:
target = sys.argv[1]
if target not in ('source', 'binary', 'installer', 'app'):
print 'Usage: package.py binary|source|app'
print 'Usage: package.py binary|installer|source|app'
exit(1)
# Derive release name from path
@ -251,8 +251,10 @@ base, release = os.path.split(os.getcwd())
prod = 'SABnzbd-' + release
Win32ServiceName = 'SABnzbd-service.exe'
Win32ServiceHelpName = 'SABnzbd-helper.exe'
Win32ConsoleName = 'SABnzbd-console.exe'
Win32WindowName = 'SABnzbd.exe'
Win32HelperName = 'SABHelper.exe'
Win32TempName = 'SABnzbd-windows.exe'
fileIns = prod + '-win32-setup.exe'
@ -298,7 +300,7 @@ options = dict(
author = 'The SABnzbd-Team',
author_email = 'team@sabnzbd.org',
#description = 'SABnzbd ' + str(sabnzbd.__version__),
scripts = ['SABnzbd.py'], # One day, add 'setup.py'
scripts = ['SABnzbd.py', 'SABHelper.py'], # One day, add 'setup.py'
packages = ['sabnzbd', 'sabnzbd.utils'],
platforms = ['posix'],
license = 'GNU General Public License 2 (GPL2) or later',
@ -425,7 +427,7 @@ elif target in ('binary', 'installer'):
options['options'] = {"py2exe":
{
"bundle_files": 3,
"packages": "email,xml,Cheetah",
"packages": "email,xml,Cheetah,win32file",
"excludes": ["pywin", "pywin.debugger", "pywin.debugger.dbgcon", "pywin.dialogs",
"pywin.dialogs.list", "Tkconstants", "Tkinter", "tcl"],
"optimize": 2,
@ -434,6 +436,7 @@ elif target in ('binary', 'installer'):
}
options['zipfile'] = 'lib/sabnzbd.zip'
options['scripts'] = ['SABnzbd.py']
############################
# Generate the console-app
@ -471,6 +474,20 @@ elif target in ('binary', 'installer'):
############################
# Generate the Helper service-app
options['scripts'] = ['SABHelper.py']
options['zipfile'] = 'lib/sabhelper.zip'
options['service'] = [{'modules':["SABHelper"], 'cmdline_style':'custom'}]
options['packages'] = ['util']
options['data_files'] = []
options['options']['py2exe']['packages'] = "win32file"
setup(**options)
rename_file('dist', Win32HelperName, Win32ServiceHelpName)
############################
if target == 'installer':
os.system('makensis.exe /v3 /DSAB_PRODUCT=%s /DSAB_FILE=%s NSIS_Installer.nsi' % \

54
sabnzbd/emailer.py

@ -47,6 +47,8 @@ def send(message):
if cfg.email_server() and cfg.email_to() and cfg.email_from():
message = _prepare_message(message)
failure = T('error-mailSend')
server, port = split_host(cfg.email_server())
if not port:
@ -99,10 +101,7 @@ def send(message):
return failure
try:
if isinstance(message, unicode):
message = message.encode('utf8')
for recipient in cfg.email_to():
mailconn.sendmail(cfg.EMAIL_FROM.get(), recipient, message)
mailconn.sendmail(cfg.email_from(), cfg.email_to(), message)
except:
logging.error(Ta('error-mailSend'))
return failure
@ -222,3 +221,50 @@ def _decode_file(path):
fp.close()
return source.decode(encoding)
################################################################################
from email.message import Message
from email.header import Header
from email.encoders import encode_quopri
RE_HEADER = re.compile(r'^([^:]+):(.*)')
def _prepare_message(txt):
""" Do the proper message encodings
"""
def plain(val):
""" Return True when val is plain ASCII """
try:
val.decode('ascii')
return True
except:
return False
# Use Latin-1 because not all email clients know UTF-8.
code = 'ISO-8859-1'
msg = Message()
msg.set_charset(code)
payload = []
body = False
for line in txt.encode(code, 'replace').split('\n'):
if not line:
body = True
if body:
payload.append(line)
else:
m = RE_HEADER.search(line)
if m:
keyword = m.group(1).strip()
value = m.group(2).strip()
if plain(value):
# Don't encode if not needed, because some email clients
# choke when headers like "date" are encoded.
msg.add_header(keyword, value)
else:
header = Header(value, code)
msg[keyword] = header
msg.set_payload('\n'.join(payload), code)
encode_quopri(msg)
return msg.as_string()

12
sabnzbd/encoding.py

@ -180,12 +180,12 @@ class LatinFilter(Filter):
if isinstance(val, unicode):
return val
elif isinstance(val, basestring):
if gUTF:
try:
return val.decode('utf-8', 'replace')
except:
return val.decode('latin-1', 'replace')
else:
try:
if sabnzbd.WIN32:
return val.decode('latin-1')
else:
return val.decode('utf-8')
except:
return val.decode('latin-1', 'replace')
elif val is None:
return u''

6
sabnzbd/interface.py

@ -2558,9 +2558,9 @@ class ConnectionInfo:
pack['download'] = ['action 1', 'action 2']
pack['unpack'] = ['action 1', 'action 2']
self.__lastmail= emailer.endjob('Test Job', 123, 'unknown', True,
os.path.normpath(os.path.join(cfg.complete_dir.get_path(), '/unknown/Test Job')),
str(123*MEBI), pack, 'my_script', 'Line 1\nLine 2\nLine 3\n', 0)
self.__lastmail= emailer.endjob('I had a d\xe8ja vu', 123, 'unknown', True,
os.path.normpath(os.path.join(cfg.COMPLETE_DIR.get_path(), '/unknown/I had a d\xe8ja vu')),
str(123*MEBI), pack, 'my_script', 'Line 1\nLine 2\nLine 3\nd\xe8ja vu\n', 0)
raise dcRaiser(self.__root, kwargs)
@cherrypy.expose

4
sabnzbd/misc.py

@ -476,8 +476,8 @@ MSG_BAD_PORT = r'''
MSG_ILL_PORT = r'''
SABnzbd needs a free tcp/ip port for its internal web server.<br>
Port %s on %s was tried , but the account SABnzbd has no permission to use it.<br>
On Linux systems, normal users must use ports above 1023.<br>
Port %s on %s was tried , but the account used for SABnzbd has no permission to use it.<br>
On OSX and Linux systems, normal users must use ports above 1023.<br>
<br>
Please restart SABnzbd with a different port number.<br>
<br>

35
sabnzbd/newsunpack.py

@ -121,6 +121,7 @@ def external_processing(extern_proc, complete_dir, filename, msgid, nicename, ca
str(nicename), str(msgid), str(cat), str(group), str(status)]
stup, need_shell, command, creationflags = build_command(command)
env = fix_env()
logging.info('Running external script %s(%s, %s, %s, %s, %s, %s, %s)', \
extern_proc, complete_dir, filename, nicename, msgid, cat, group, status)
@ -128,7 +129,7 @@ def external_processing(extern_proc, complete_dir, filename, msgid, nicename, ca
try:
p = subprocess.Popen(command, shell=need_shell, stdin=subprocess.PIPE,
stdout=subprocess.PIPE, stderr=subprocess.STDOUT,
startupinfo=stup, creationflags=creationflags)
startupinfo=stup, env=env, creationflags=creationflags)
except:
logging.debug("Failed script %s, Traceback: ", extern_proc, exc_info = True)
return "Cannot run script %s\r\n" % extern_proc, -1
@ -1016,30 +1017,20 @@ def PAR_Verify(parfile, parfile_nzf, nzo, setname, joinables, classic=False):
#-------------------------------------------------------------------------------
_RE_PYTHON = re.compile(r'^#!(.*/python)\s+(.*)$')
def fix_python_script(command):
""" Implement a work-around for Python userscripts on OSX """
try:
fp = open(command[0], 'r')
line = fp.readline(100)
fp.close()
m = _RE_PYTHON.search(line)
if m:
# Work-around for the incorrect Python paths passed
# by the OSX.app to Python scripts.
# Run the Python interpreter directly and insert the -E parameter
command.insert(0, m.group(2))
command.insert(0, '-E')
command.insert(0, m.group(1))
except IOError:
pass
def fix_env():
""" OSX: Return copy of environment without PYTHONPATH and PYTHONHOME
other: return None
"""
if sabnzbd.DARWIN:
env = os.environ.copy()
if 'PYTHONPATH' in env: del env['PYTHONPATH']
if 'PYTHONHOME' in env: del env['PYTHONHOME']
return env
else:
return None
def build_command(command):
if sabnzbd.DARWIN:
fix_python_script(command)
if not sabnzbd.WIN32:
if IONICE_COMMAND and cfg.ionice().strip():
lst = cfg.ionice().split()

3
sabnzbd/tvsort.py

@ -328,6 +328,9 @@ class SeriesSorter:
# Lowercase all characters encased in {}
path = toLowercase(path)
# Strip any extra ' ' '.' or '_' around foldernames
path = stripFolders(path)
# Split the last part of the path up for the renamer
if extension:
head, tail = os.path.split(path)

0
util/__init__.py

130
util/mailslot.py

@ -0,0 +1,130 @@
#!/usr/bin/python -OO
# Copyright 2008-2010 The SABnzbd-Team <team@sabnzbd.org>
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program 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. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
"""
sabnzbd.mailslot - Mailslot communication
"""
import os
from win32file import GENERIC_WRITE, FILE_SHARE_READ, \
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL
from ctypes import c_uint, c_buffer, byref, sizeof, windll
# Win32API Shortcuts
CreateFile = windll.kernel32.CreateFileA
ReadFile = windll.kernel32.ReadFile
WriteFile = windll.kernel32.WriteFile
CloseHandle = windll.kernel32.CloseHandle
CreateMailslot = windll.kernel32.CreateMailslotA
class MailSlot(object):
""" Simple Windows Mailslot communication
"""
slotname = r'mailslot\SABnzbd\ServiceSlot'
def __init__(self):
self.handle = -1
def create(self, timeout):
""" Create the Mailslot, after this only receiving is possible
timeout is the read timeout used for receive calls.
"""
slot = r'\\.\%s' % MailSlot.slotname
self.handle = CreateMailslot(slot, 50, timeout, None)
return self.handle != -1
def connect(self):
""" Connect to existing Mailslot so that writing is possible
"""
slot = r'\\%s\%s' % (os.environ['COMPUTERNAME'], MailSlot.slotname)
self.handle = CreateFile(slot, GENERIC_WRITE, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0)
return self.handle != -1
def disconnect(self):
""" Disconnect from Mailslot
"""
if self.handle != -1:
CloseHandle(self.handle)
self.handle = -1
return True
def send(self, command):
""" Send one message to Mailslot
"""
if self.handle == -1:
return False
w = c_uint()
return bool(WriteFile(self.handle, command, len(command), byref(w), 0))
def receive(self):
""" Receive one message from Mailslot
"""
r = c_uint()
buf = c_buffer(1024)
if ReadFile(self.handle, buf, sizeof(buf), byref(r), 0):
return buf.value
else:
return None
#------------------------------------------------------------------------------
# Simple test
#
# First start "mailslot.py server" in one process,
# Then start "mailslot.py client" in another.
# Five "restart" and one "stop" will be send from client to server.
# The server will stop after receiving "stop"
if __name__ == '__main__':
import sys
from time import sleep
if not __debug__:
print 'Run this test in non-optimized mode'
exit(1)
if len(sys.argv) > 1 and 'server' in sys.argv[1]:
recv = MailSlot()
ret = recv.create(2)
assert ret, 'Failed to create'
while True:
data = recv.receive()
if data is not None:
print data
if data.startswith('stop'):
break
sleep(2.0)
recv.disconnect()
elif len(sys.argv) > 1 and 'client' in sys.argv[1]:
send = MailSlot()
ret = send.connect()
assert ret, 'Failed to connect'
for n in xrange(5):
ret = send.send('restart')
assert ret, 'Failed to send'
sleep(2.0)
send.send('stop')
assert ret, 'Failed to send'
send.disconnect()
else:
print 'Usage: mailslot.py server|client'
Loading…
Cancel
Save