Compare commits
108 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
37acad6ec7 | ||
|
|
74d90b8361 | ||
|
|
952682d557 | ||
|
|
c1f3e44fb8 | ||
|
|
fa2a6c673c | ||
|
|
b46ae4782d | ||
|
|
6ebbc81792 | ||
|
|
1d7170f193 | ||
|
|
3dea948ecc | ||
|
|
1e960ae2e9 | ||
|
|
e6b21f1ca5 | ||
|
|
ebd3cbd932 | ||
|
|
b8fb5cbfbf | ||
|
|
01494bd010 | ||
|
|
6dd4c0551e | ||
|
|
8225dae182 | ||
|
|
9999065f0a | ||
|
|
90d11ada6b | ||
|
|
67a1ee3cde | ||
|
|
0f8df0f072 | ||
|
|
9c9936e7ae | ||
|
|
92926a4825 | ||
|
|
2cc53e8dc3 | ||
|
|
18cb5710f9 | ||
|
|
11b8f23528 | ||
|
|
cf72abedfd | ||
|
|
31f92ebdd5 | ||
|
|
39a6635229 | ||
|
|
a87a70d9c6 | ||
|
|
2d79e2ac92 | ||
|
|
7982ef2f11 | ||
|
|
9280daad41 | ||
|
|
e22709b5ff | ||
|
|
ed37330fee | ||
|
|
f1fb3f904b | ||
|
|
a3b6bb9ad9 | ||
|
|
54e6431d11 | ||
|
|
3e6f46483c | ||
|
|
f7aadb1b61 | ||
|
|
c7d5ea6ecd | ||
|
|
1060f15463 | ||
|
|
559d3064a9 | ||
|
|
084e638d30 | ||
|
|
428ab1ad96 | ||
|
|
b15673d0cd | ||
|
|
abf15149e9 | ||
|
|
1f9e328c2d | ||
|
|
2c2c1c93a1 | ||
|
|
196c06a17e | ||
|
|
be78580ece | ||
|
|
748d525ccc | ||
|
|
2269407b1c | ||
|
|
af7beab5e9 | ||
|
|
fb9abcc583 | ||
|
|
29e829de73 | ||
|
|
5225925a78 | ||
|
|
15bd0f8a78 | ||
|
|
1557f3f8e8 | ||
|
|
b0a833f3a9 | ||
|
|
8b66deef0e | ||
|
|
61608545c5 | ||
|
|
4f163ad979 | ||
|
|
a01cd34b58 | ||
|
|
e6a5b0de57 | ||
|
|
b3b1209293 | ||
|
|
4cc21efe90 | ||
|
|
6acd599d53 | ||
|
|
b73f74470b | ||
|
|
6b3efe9398 | ||
|
|
e5c9058201 | ||
|
|
897d982e2f | ||
|
|
333b83f3c5 | ||
|
|
94938847fb | ||
|
|
64f17675e2 | ||
|
|
a97974d66c | ||
|
|
349395f67a | ||
|
|
344c1ff42d | ||
|
|
08435bc138 | ||
|
|
ce00490b40 | ||
|
|
cc702dde6d | ||
|
|
913121bcc4 | ||
|
|
6448f4ff5e | ||
|
|
1fbb56fc6f | ||
|
|
6442391589 | ||
|
|
80ca43fe7d | ||
|
|
3514973f2a | ||
|
|
def241c5c4 | ||
|
|
04e1605b27 | ||
|
|
a931e80f2e | ||
|
|
f891a0ceac | ||
|
|
41697d022f | ||
|
|
f0b1b9d284 | ||
|
|
b1455398c8 | ||
|
|
396e779517 | ||
|
|
e9bc192bc7 | ||
|
|
287490d549 | ||
|
|
dcd55b552a | ||
|
|
4ac2b0d27c | ||
|
|
ea4d1e9474 | ||
|
|
61c29e232d | ||
|
|
7b6ef157e9 | ||
|
|
14d6a033ae | ||
|
|
1db567b5ae | ||
|
|
ad6c9a56d8 | ||
|
|
15f6732a5b | ||
|
|
e517218240 | ||
|
|
89fc5fc124 | ||
|
|
4025087f89 |
15
.bzreol
@@ -1,15 +0,0 @@
|
||||
[LF]
|
||||
.bzreol
|
||||
.bzrignore
|
||||
*.py
|
||||
*.tmpl
|
||||
*.js
|
||||
*.css
|
||||
*.txt
|
||||
*.po
|
||||
*.pot
|
||||
*.sh
|
||||
[CRLF]
|
||||
*.bat
|
||||
*.cmd
|
||||
*.nsi
|
||||
10
.bzrignore
@@ -1,10 +0,0 @@
|
||||
*.pyc
|
||||
*.pyo
|
||||
build
|
||||
dist
|
||||
locale
|
||||
srcdist
|
||||
cherrypy
|
||||
*.wpr
|
||||
*.keep
|
||||
*.bak
|
||||
13
.bzrtab
@@ -1,13 +0,0 @@
|
||||
[NOTAB]
|
||||
*.py
|
||||
*.txt
|
||||
*.po
|
||||
*.pot
|
||||
*.sh
|
||||
*.bat
|
||||
*.cmd
|
||||
*.nsi
|
||||
*.tmpl
|
||||
*.js
|
||||
*.css
|
||||
[TAB]
|
||||
28
.gitignore
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
#Compiled python
|
||||
*.py[co]
|
||||
|
||||
# Working folders for Win build
|
||||
build/
|
||||
dist/
|
||||
locale/
|
||||
srcdist/
|
||||
|
||||
# Generated email templates
|
||||
email/
|
||||
|
||||
# Romanian ro.po is generated from ro.px, due to mapping to latin-1
|
||||
po/*/ro.po
|
||||
|
||||
# Build results
|
||||
SABnzbd*.zip
|
||||
SABnzbd*.exe
|
||||
SABnzbd*.gz
|
||||
SABnzbd*.dmg
|
||||
|
||||
# WingIDE project file
|
||||
*.wpr
|
||||
|
||||
# General junk
|
||||
*.keep
|
||||
*.bak
|
||||
*.log
|
||||
63
ABOUT.txt
Normal file
@@ -0,0 +1,63 @@
|
||||
*******************************************
|
||||
*** This is SABnzbd 0.6.9 ***
|
||||
*******************************************
|
||||
SABnzbd is an open-source cross-platform binary newsreader.
|
||||
It simplifies the process of downloading from Usenet dramatically,
|
||||
thanks to its friendly web-based user interface and advanced
|
||||
built-in post-processing options that automatically verify, repair,
|
||||
extract and clean up posts downloaded from Usenet.
|
||||
SABnzbd also has a fully customizable user interface,
|
||||
and offers a complete API for third-party applications to hook into.
|
||||
|
||||
There is an extensive Wiki on the use of SABnzbd.
|
||||
http://wiki.sabnzbd.org/
|
||||
|
||||
IMPORTANT INFORMATION about release 0.6.0:
|
||||
http://wiki.sabnzbd.org/introducing-0-6-0
|
||||
|
||||
|
||||
Please also read the file "ISSUES.txt"
|
||||
|
||||
*******************************************
|
||||
*** Upgrading from 0.6.x ***
|
||||
*******************************************
|
||||
Stop SABnzbd.
|
||||
Install new version
|
||||
Start SABnzbd.
|
||||
|
||||
|
||||
*******************************************
|
||||
*** Upgrading from 0.5.x ***
|
||||
*******************************************
|
||||
Stop SABnzbd.
|
||||
Uninstall current version, keeping the data.
|
||||
Install new version
|
||||
Start SABnzbd.
|
||||
|
||||
The organization of the download queue is different from 0.5.x.
|
||||
0.6.x will finish downloading an existing queue, but you
|
||||
cannot go back to an older version without losing your queue.
|
||||
Also, your sabnzbd.ini file will be upgraded, making it
|
||||
incompatible with release 0.5.x
|
||||
|
||||
|
||||
*******************************************
|
||||
*** Upgrading from 0.4.x ***
|
||||
*******************************************
|
||||
|
||||
>>>>> PLEASE DOWNLOAD YOUR CURRENT QUEUE BEFORE UPGRADING <<<<<<
|
||||
|
||||
When upgrading from a 0.4.x release such as 0.4.12 your old settings will be kept.
|
||||
You will however be given a fresh queue and history. If you have items in your queue
|
||||
from the older version of SABnzbd, you can either re-import the nzb files if you kept
|
||||
an nzb backup folder, or temporarily go back to 0.4.x until your queue is complete.
|
||||
|
||||
The history is now stored in a better format meaning future upgrades should be backwards
|
||||
compatible.
|
||||
|
||||
|
||||
*******************************************
|
||||
*** Changes since 0.5.6 ***
|
||||
*******************************************
|
||||
|
||||
See: http://wiki.sabnzbd.org/introducing-0-6-0
|
||||
@@ -1,3 +1,71 @@
|
||||
-------------------------------------------------------------------------------
|
||||
0.6.9RC2 by The SABnzbd-Team
|
||||
-------------------------------------------------------------------------------
|
||||
- Generic Sorter failed to uppercase first letter of title when starting with "the/a/to" etc.
|
||||
- Add "hidden" option allow_64bit_tools (lost when going from 0.5.6 to 0.6.0)
|
||||
- Improve handling of non-creatable final and category folders
|
||||
- Fix and I18N the "Downloaded in X days Y hours Z seconds" text in the history report.
|
||||
- Change the OSX DMG window size so that the optional "path bar" doesn't obsure part of the background image.
|
||||
-------------------------------------------------------------------------------
|
||||
0.6.9RC1 by The SABnzbd-Team
|
||||
-------------------------------------------------------------------------------
|
||||
- Update Plush to solve minor browser incompatibilities
|
||||
- On Windows the 64bit versions of par2 and unrar were never used
|
||||
- Updated unrar to 4.01
|
||||
- Using the "Download" button in newzbin.com RSS feeds produced malformed names.
|
||||
- For OSX make a Lion and a Leopard/SnowLeopard version and show this in DMG background image
|
||||
- When removing job folders in the "temporary download folder", remove everything.
|
||||
This is needed because some operating systems add spurious files and folders.
|
||||
- Servers with square brackets in the name could not be removed.
|
||||
- Check email parameters also when only email_rss is set.
|
||||
- Try out work-around for potential memory leak in pickle.
|
||||
-------------------------------------------------------------------------------
|
||||
0.6.8Final by The SABnzbd-Team
|
||||
-------------------------------------------------------------------------------
|
||||
- Fix several RSS issues, due to corruption of stored RSS data
|
||||
-------------------------------------------------------------------------------
|
||||
0.6.7Final by The SABnzbd-Team
|
||||
-------------------------------------------------------------------------------
|
||||
- Prevent immediate exit after startup when queue is empty and
|
||||
an end-of-queue action like "shutdown" was set
|
||||
- Fix failure to launch browser when clicking shortcut the second time
|
||||
- Allow jobs still waiting for post-processing to be deleted
|
||||
- Delay starting of dowload task until after webserver is started.
|
||||
- Plush: button "Purge failed NZBs & delete files" will now actually delete files
|
||||
- Classic/smpl: add link "Purge failed NZBs & delete files"
|
||||
- Plush: fix flashing top menu in Safari 5.1
|
||||
-------------------------------------------------------------------------------
|
||||
0.6.6Final by The SABnzbd-Team
|
||||
-------------------------------------------------------------------------------
|
||||
- Prevent crashes when running into disk-full situations.
|
||||
-------------------------------------------------------------------------------
|
||||
0.6.6RC1 by The SABnzbd-Team
|
||||
-------------------------------------------------------------------------------
|
||||
- When "Download only" is used, do not send downloaded NZB files to the queue
|
||||
- Fix bad links coming from nzbclub.com
|
||||
- A job sometimes fails verification when the option "don't download samples" is used.
|
||||
Now this option will be ignored when you click "Retry" in the history.
|
||||
- File an error message when the RSS-email template is missing.
|
||||
-------------------------------------------------------------------------------
|
||||
0.6.6Beta2 by The SABnzbd-Team
|
||||
-------------------------------------------------------------------------------
|
||||
- Fix sending of duplicate emails when using a list of recipients
|
||||
- Fix handle leakage on Windows
|
||||
- On OSX, SABnzbd didn't handle "Open With" of nzb.gz files properly
|
||||
- Limit the amount of retries when getting a partial NZB from an index site
|
||||
-------------------------------------------------------------------------------
|
||||
0.6.6Beta1 by The SABnzbd-Team
|
||||
-------------------------------------------------------------------------------
|
||||
- Compatible with OSX Lion
|
||||
- End-of-queue action now ignores paused items in the queue
|
||||
- Fetching extra par2 files now obeys pause too
|
||||
- Extension-based cleanup now also cleans sub-folders
|
||||
-------------------------------------------------------------------------------
|
||||
0.6.5Final by The SABnzbd-Team
|
||||
-------------------------------------------------------------------------------
|
||||
- Since 0.6.3, all end-of-queue actions failed.
|
||||
- Generic sort: failed to recognize years surounded by underscores.
|
||||
- When running the Wizard in German, the last page crashed.
|
||||
-------------------------------------------------------------------------------
|
||||
0.6.4Final by The SABnzbd-Team
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
SABnzbd 0.6.3
|
||||
SABnzbd 0.6.9
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
0) LICENSE
|
||||
@@ -49,6 +49,11 @@ You need to have Python installed and some modules.
|
||||
Unix/Linux/OSX
|
||||
Python-2.5, 2.6 or 2.7 http://www.python.org
|
||||
|
||||
OSX Leopard/SnowLeopard
|
||||
Python 2.6 http://www.activestate.com
|
||||
|
||||
OSX Lion Apple Python 2.7 (included in OSX)
|
||||
|
||||
Windows
|
||||
Python-2.5.latest http://www.activestate.com
|
||||
Python-2.6.latest
|
||||
|
||||
4
PKG-INFO
@@ -1,7 +1,7 @@
|
||||
Metadata-Version: 1.0
|
||||
Name: SABnzbd
|
||||
Version: 0.6.4
|
||||
Summary: SABnzbd-0.6.4
|
||||
Version: 0.6.9RC2
|
||||
Summary: SABnzbd-0.6.9RC2
|
||||
Home-page: http://sourceforge.net/projects/sabnzbdplus
|
||||
Author: The SABnzbd Team
|
||||
Author-email: team@sabnzbd.org
|
||||
|
||||
54
README.md
Normal file
@@ -0,0 +1,54 @@
|
||||
SABnzbd - The automated Usenet download tool
|
||||
============================================
|
||||
|
||||
SABnzbd is an Open Source Binary Newsreader written in Python.
|
||||
|
||||
It's totally free, incredibly easy to use, and works practically everywhere.
|
||||
|
||||
SABnzbd makes Usenet as simple and streamlined as possible by automating everything we can. All you have to do is add an .nzb. SABnzbd takes over from there, where it will be automatically downloaded, verified, repaired, extracted and filed away with zero human interaction.
|
||||
|
||||
If you want to know more you can head over to our website: http://sabnzbd.org.
|
||||
|
||||
## Resolving Dependencies
|
||||
|
||||
SABnzbd has a good deal of dependencies you'll need before you can get running. If you've previously run SABnzbd from one of the various Linux packages floating around (Ubuntu, Debian, Fedora, etc), then you likely already have all the needed dependencies. If not, here's what you're looking for:
|
||||
|
||||
- `python` (We support Python 2.5-2.7, preferably 2.6 or 2.7.)
|
||||
- `python-cheetah`
|
||||
- `python-configobj`
|
||||
- `python-feedparser`
|
||||
- `python-dbus`
|
||||
- `python-openssl`
|
||||
- `python-support`
|
||||
- `python-yenc`
|
||||
- `par2` (Multi-threaded par2 can be downloaded from [ChuChuSoft](http://chuchusoft.com/par2_tbb/download.html) )
|
||||
- `unrar` (Make sure you get the "official" non-free version of unrar)
|
||||
- `unzip`
|
||||
|
||||
Your package manager should supply these. If not, we've got links in our more in-depth [installation guide](https://github.com/sabnzbd/sabnzbd/blob/master/INSTALL.txt).
|
||||
|
||||
## Running SABnzbd from source
|
||||
|
||||
Once you've sorted out all the dependencies, simply run:
|
||||
|
||||
```
|
||||
python SABnzbd.py
|
||||
```
|
||||
|
||||
Or, if you want to run in the background:
|
||||
|
||||
```
|
||||
python -d -f /path/to/sabnzbd.ini
|
||||
```
|
||||
|
||||
If you want multi-language support, run:
|
||||
|
||||
```
|
||||
python tools/make_mo.py
|
||||
```
|
||||
|
||||
Our many other commandline options are explained in depth [here](http://wiki.sabnzbd.org/command-line-parameters).
|
||||
|
||||
## About Our Repo
|
||||
|
||||
We're going to be attempting to follow the [gitflow model](http://nvie.com/posts/a-successful-git-branching-model/), so you can consider "master" to be whatever our present stable release build is (presently 0.6.x) and "develop" to be whatever our next build will be (presently 0.7.x). Once we transition from unstable to stable dev builds we'll create release branches, and encourage you to follow along and help us test.
|
||||
31
README.rtf
@@ -1,13 +1,36 @@
|
||||
{\rtf1\ansi\ansicpg1252\cocoartf1038\cocoasubrtf350
|
||||
{\rtf1\ansi\ansicpg1252\cocoartf1038\cocoasubrtf360
|
||||
{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
|
||||
{\colortbl;\red255\green255\blue255;}
|
||||
\paperw11900\paperh16840\vieww16360\viewh15680\viewkind0
|
||||
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural
|
||||
|
||||
\f0\b\fs48 \cf0 SABnzbd 0.6.3\
|
||||
\f0\b\fs48 \cf0 SABnzbd 0.6.9RC2\
|
||||
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural\pardirnatural
|
||||
|
||||
\b0\fs26 \cf0 \
|
||||
|
||||
\b What's new
|
||||
\b0 \
|
||||
RC2\
|
||||
- Generic Sorter failed to uppercase first letter of title when starting with "the/a/to" etc.\
|
||||
- Add "hidden" option allow_64bit_tools (lost when going from 0.5.6 to 0.6.0)\
|
||||
- Improve handling of non-creatable final and category folders\
|
||||
- Fix and I18N the "Downloaded in X days Y hours Z seconds" text in the history report.\
|
||||
- Change the OSX DMG window size so that the optional "path bar" doesn't obsure part of the background image.\
|
||||
RC1\
|
||||
- Update Plush to solve minor browser incompatibilities\
|
||||
- On Windows the 64bit versions of par2 and unrar were never used\
|
||||
- Updated unrar to 4.01\
|
||||
- Using the "Download" button in newzbin.com RSS feeds produced malformed names.\
|
||||
- When removing job folders in the "temporary download folder", remove everything.\
|
||||
This is needed because some operating systems add spurious files and folders.\
|
||||
\
|
||||
- OSX has now a Leopard/SnowLeopard DMG and a Lion-only DMG\
|
||||
You can see the difference in the DMG's background image\
|
||||
\
|
||||
|
||||
\b About
|
||||
\b0 \
|
||||
SABnzbd is an open-source cross-platform binary newsreader.\
|
||||
It simplifies the process of downloading from Usenet dramatically,\
|
||||
thanks to its friendly web-based user interface and advanced\
|
||||
@@ -27,9 +50,7 @@ There is an extensive Wiki on the use of SABnzbd.\
|
||||
|
||||
\b Known problems and solutions\
|
||||
|
||||
\b0 Read the file
|
||||
\b
|
||||
\b0 "ISSUES.txt"
|
||||
\b0 Read the file"ISSUES.txt"
|
||||
\b \
|
||||
|
||||
\b0 \
|
||||
|
||||
82
README.txt
@@ -1,63 +1,29 @@
|
||||
*******************************************
|
||||
*** This is SABnzbd 0.6.3 ***
|
||||
*******************************************
|
||||
SABnzbd is an open-source cross-platform binary newsreader.
|
||||
It simplifies the process of downloading from Usenet dramatically,
|
||||
thanks to its friendly web-based user interface and advanced
|
||||
built-in post-processing options that automatically verify, repair,
|
||||
extract and clean up posts downloaded from Usenet.
|
||||
SABnzbd also has a fully customizable user interface,
|
||||
and offers a complete API for third-party applications to hook into.
|
||||
************************ SABnzbd 0.6.9RC2 ************************
|
||||
|
||||
There is an extensive Wiki on the use of SABnzbd.
|
||||
http://wiki.sabnzbd.org/
|
||||
What's new:
|
||||
RC2
|
||||
- Generic Sorter failed to uppercase first letter of title when starting with "the/a/to" etc.
|
||||
- Add "hidden" option allow_64bit_tools (lost when going from 0.5.6 to 0.6.0)
|
||||
- Improve handling of non-creatable final and category folders
|
||||
- Fix and I18N the "Downloaded in X days Y hours Z seconds" text in the history report.
|
||||
- Change the OSX DMG window size so that the optional "path bar" doesn't obsure part of the background image.
|
||||
RC1
|
||||
- Update Plush to solve minor browser incompatibilities
|
||||
- On Windows the 64bit versions of par2 and unrar were never used
|
||||
- Updated unrar to 4.01
|
||||
- Using the "Download" button in newzbin.com RSS feeds produced malformed names.
|
||||
- When removing job folders in the "temporary download folder", remove everything.
|
||||
This is needed because some operating systems add spurious files and folders.
|
||||
|
||||
IMPORTANT INFORMATION about release 0.6.0:
|
||||
http://wiki.sabnzbd.org/introducing-0-6-0
|
||||
- OSX has now a Leopard/SnowLeopard DMG and a Lion-only DMG
|
||||
You can see the difference in the DMG's background image
|
||||
|
||||
|
||||
Please also read the file "ISSUES.txt"
|
||||
About:
|
||||
SABnzbd is an open-source cross-platform binary newsreader.
|
||||
It simplifies the process of downloading from Usenet dramatically,
|
||||
thanks to its friendly web-based user interface and advanced
|
||||
built-in post-processing options that automatically verify, repair,
|
||||
extract and clean up posts downloaded from Usenet.
|
||||
|
||||
*******************************************
|
||||
*** Upgrading from 0.6.x ***
|
||||
*******************************************
|
||||
Stop SABnzbd.
|
||||
Install new version
|
||||
Start SABnzbd.
|
||||
|
||||
|
||||
*******************************************
|
||||
*** Upgrading from 0.5.x ***
|
||||
*******************************************
|
||||
Stop SABnzbd.
|
||||
Uninstall current version, keeping the data.
|
||||
Install new version
|
||||
Start SABnzbd.
|
||||
|
||||
The organization of the download queue is different from 0.5.x.
|
||||
0.6.x will finish downloading an existing queue, but you
|
||||
cannot go back to an older version without losing your queue.
|
||||
Also, your sabnzbd.ini file will be upgraded, making it
|
||||
incompatible with release 0.5.x
|
||||
|
||||
|
||||
*******************************************
|
||||
*** Upgrading from 0.4.x ***
|
||||
*******************************************
|
||||
|
||||
>>>>> PLEASE DOWNLOAD YOUR CURRENT QUEUE BEFORE UPGRADING <<<<<<
|
||||
|
||||
When upgrading from a 0.4.x release such as 0.4.12 your old settings will be kept.
|
||||
You will however be given a fresh queue and history. If you have items in your queue
|
||||
from the older version of SABnzbd, you can either re-import the nzb files if you kept
|
||||
an nzb backup folder, or temporarily go back to 0.4.x until your queue is complete.
|
||||
|
||||
The history is now stored in a better format meaning future upgrades should be backwards
|
||||
compatible.
|
||||
|
||||
|
||||
*******************************************
|
||||
*** Changes since 0.5.6 ***
|
||||
*******************************************
|
||||
|
||||
See: http://wiki.sabnzbd.org/introducing-0-6-0
|
||||
(c) Copyright 2007-2011 by "The SABnzbd-team" <team@sabnzbd.org>
|
||||
|
||||
94
SABnzbd.py
@@ -37,7 +37,7 @@ except ValueError:
|
||||
print "Sorry, requires Python module Cheetah 2.0rc7 or higher."
|
||||
sys.exit(1)
|
||||
except:
|
||||
print "The following modules need to be installed: Cheetah, cherrypy(included, unpack the zip)"
|
||||
print "The Python module Cheetah is required"
|
||||
sys.exit(1)
|
||||
|
||||
import cherrypy
|
||||
@@ -62,20 +62,22 @@ except:
|
||||
else:
|
||||
SQLITE_DLL = False
|
||||
|
||||
import sabnzbd.lang
|
||||
import sabnzbd
|
||||
import sabnzbd.lang
|
||||
import sabnzbd.interface
|
||||
from sabnzbd.constants import *
|
||||
import sabnzbd.newsunpack
|
||||
from sabnzbd.misc import get_user_shellfolders, launch_a_browser, real_path, \
|
||||
check_latest_version, panic_tmpl, panic_port, panic_host, panic_fwall, panic_sqlite, panic, exit_sab, \
|
||||
panic_xport, notify, split_host, get_ext, create_https_certificates, \
|
||||
from sabnzbd.misc import get_user_shellfolders, real_path, \
|
||||
check_latest_version, exit_sab, \
|
||||
split_host, get_ext, create_https_certificates, \
|
||||
windows_variant, ip_extract, set_serv_parms, get_serv_parms, globber
|
||||
from sabnzbd.panic import panic_tmpl, panic_port, panic_host, panic_fwall, \
|
||||
panic_sqlite, panic, launch_a_browser, panic_xport
|
||||
import sabnzbd.scheduler as scheduler
|
||||
import sabnzbd.config as config
|
||||
import sabnzbd.cfg
|
||||
import sabnzbd.downloader
|
||||
from sabnzbd.encoding import unicoder
|
||||
from sabnzbd.encoding import unicoder, latin1
|
||||
from sabnzbd.utils import osx
|
||||
|
||||
from threading import Thread
|
||||
@@ -639,9 +641,12 @@ def find_free_port(host, currentport):
|
||||
return 0
|
||||
|
||||
|
||||
def check_for_sabnzbd(url, upload_nzbs):
|
||||
def check_for_sabnzbd(url, upload_nzbs, allow_browser=True):
|
||||
""" Check for a running instance of sabnzbd(same version) on this port
|
||||
allow_browser==True|None will launch the browser, False will not.
|
||||
"""
|
||||
if allow_browser is None:
|
||||
allow_browser = True
|
||||
if is_sabnzbd_running(url):
|
||||
# Upload any specified nzb files to the running instance
|
||||
if upload_nzbs:
|
||||
@@ -650,8 +655,9 @@ def check_for_sabnzbd(url, upload_nzbs):
|
||||
upload_file(url, f)
|
||||
else:
|
||||
# Launch the web browser and quit since sabnzbd is already running
|
||||
# Trim away everything after the final slash in the URL
|
||||
url = url[:url.rfind('/')+1]
|
||||
launch_a_browser(url, force=True)
|
||||
launch_a_browser(url, force=allow_browser)
|
||||
exit_sab(0)
|
||||
return True
|
||||
return False
|
||||
@@ -742,6 +748,12 @@ def commandline_handler(frozen=True):
|
||||
serv_opts = [os.path.normpath(os.path.abspath(sys.argv[0]))]
|
||||
upload_nzbs = []
|
||||
|
||||
# OSX binary: get rid of the weird -psn_0_123456 parameter
|
||||
for arg in sys.argv:
|
||||
if arg.startswith('-psn_'):
|
||||
sys.argv.remove(arg)
|
||||
break
|
||||
|
||||
# Ugly hack to remove the extra "SABnzbd*" parameter the Windows binary
|
||||
# gets when it's restarted
|
||||
if len(sys.argv) > 1 and \
|
||||
@@ -761,7 +773,7 @@ def commandline_handler(frozen=True):
|
||||
'weblogging=', 'server=', 'templates',
|
||||
'template2', 'browser=', 'config-file=', 'force',
|
||||
'version', 'https=', 'autorestarted', 'repair', 'repair-all',
|
||||
'log-all', 'no-login', 'pid=', 'new',
|
||||
'log-all', 'no-login', 'pid=', 'new', 'sessions',
|
||||
# Below Win32 Service options
|
||||
'password=', 'username=', 'startup=', 'perfmonini=', 'perfmondll=',
|
||||
'interactive', 'wait=',
|
||||
@@ -808,6 +820,7 @@ def get_f_option(opts):
|
||||
#------------------------------------------------------------------------------
|
||||
def main():
|
||||
global LOG_FLAG
|
||||
import sabnzbd # Due to ApplePython bug
|
||||
|
||||
autobrowser = None
|
||||
autorestarted = False
|
||||
@@ -833,6 +846,7 @@ def main():
|
||||
re_argv = [sys.argv[0]]
|
||||
pid_path = None
|
||||
new_instance = False
|
||||
force_sessions = False
|
||||
|
||||
service, sab_opts, serv_opts, upload_nzbs = commandline_handler()
|
||||
|
||||
@@ -913,6 +927,8 @@ def main():
|
||||
re_argv.append(arg)
|
||||
elif opt in ('--new',):
|
||||
new_instance = True
|
||||
elif opt in ('--sessions',):
|
||||
force_sessions = True
|
||||
|
||||
sabnzbd.MY_FULLNAME = os.path.normpath(os.path.abspath(sabnzbd.MY_FULLNAME))
|
||||
sabnzbd.MY_NAME = os.path.basename(sabnzbd.MY_FULLNAME)
|
||||
@@ -951,6 +967,8 @@ def main():
|
||||
# Detect Windows variant
|
||||
if sabnzbd.WIN32:
|
||||
vista_plus, vista64 = windows_variant()
|
||||
sabnzbd.WIN64 = vista64
|
||||
|
||||
|
||||
if not SQLITE_DLL:
|
||||
panic_sqlite(sabnzbd.MY_FULLNAME)
|
||||
@@ -1020,7 +1038,7 @@ def main():
|
||||
url = None
|
||||
if sabnzbd.WIN32 and not new_instance:
|
||||
url = get_connection_info()
|
||||
if url and check_for_sabnzbd(url, upload_nzbs):
|
||||
if url and check_for_sabnzbd(url, upload_nzbs, autobrowser):
|
||||
exit_sab(0)
|
||||
|
||||
# If an instance of sabnzbd(same version) is already running on this port, launch the browser
|
||||
@@ -1038,7 +1056,7 @@ def main():
|
||||
else:
|
||||
if not url:
|
||||
url = 'https://%s:%s/sabnzbd/api?' % (browserhost, port)
|
||||
if new_instance or not check_for_sabnzbd(url, upload_nzbs):
|
||||
if new_instance or not check_for_sabnzbd(url, upload_nzbs, autobrowser):
|
||||
newport = find_free_port(browserhost, port)
|
||||
if newport > 0:
|
||||
sabnzbd.cfg.https_port.set(newport)
|
||||
@@ -1058,7 +1076,7 @@ def main():
|
||||
else:
|
||||
if not url:
|
||||
url = 'http://%s:%s/sabnzbd/api?' % (browserhost, cherryport)
|
||||
if new_instance or not check_for_sabnzbd(url, upload_nzbs):
|
||||
if new_instance or not check_for_sabnzbd(url, upload_nzbs, autobrowser):
|
||||
port = find_free_port(browserhost, cherryport)
|
||||
if port > 0:
|
||||
sabnzbd.cfg.cherryport.set(port)
|
||||
@@ -1164,7 +1182,6 @@ def main():
|
||||
suffix = ' (=Vista+)'
|
||||
if vista64:
|
||||
suffix = ' (=Vista+ x64)'
|
||||
sabnzbd.WIN64 = True
|
||||
try:
|
||||
logging.info('Platform=%s%s Class=%s', platform.platform(), suffix, os.name)
|
||||
except:
|
||||
@@ -1172,6 +1189,7 @@ def main():
|
||||
else:
|
||||
logging.info('Platform = %s', os.name)
|
||||
logging.info('Python-version = %s', sys.version)
|
||||
logging.info('Arguments = %s', sabnzbd.CMDLINE)
|
||||
|
||||
# OSX 10.5 I/O priority setting
|
||||
if sabnzbd.DARWIN:
|
||||
@@ -1225,21 +1243,8 @@ def main():
|
||||
# Save the INI file
|
||||
config.save_config(force=True)
|
||||
|
||||
logging.info('Starting %s-%s', sabnzbd.MY_NAME, sabnzbd.__version__)
|
||||
try:
|
||||
sabnzbd.start()
|
||||
except:
|
||||
logging.exception("Failed to start %s-%s", sabnzbd.MY_NAME, sabnzbd.__version__)
|
||||
sabnzbd.halt()
|
||||
|
||||
print_modules()
|
||||
|
||||
# Upload any nzb/zip/rar/nzb.gz files from file association
|
||||
if upload_nzbs:
|
||||
from sabnzbd.utils.upload import add_local
|
||||
for f in upload_nzbs:
|
||||
add_local(f)
|
||||
|
||||
cherrylogtoscreen = False
|
||||
sabnzbd.WEBLOGFILE = None
|
||||
|
||||
@@ -1285,6 +1290,14 @@ def main():
|
||||
sabnzbd.cfg.username.set('')
|
||||
sabnzbd.cfg.password.set('')
|
||||
|
||||
# Fix leakage in memory-based CherryPy session support by using file-based.
|
||||
# However, we don't really need session support.
|
||||
if force_sessions:
|
||||
sessions = sabnzbd.misc.create_real_path('sessions', sabnzbd.cfg.admin_dir.get_path(), 'sessions')[1]
|
||||
sabnzbd.misc.remove_all(sessions, 'session-*.lock', keep_folder=True)
|
||||
else:
|
||||
sessions = None
|
||||
|
||||
cherrypy.config.update({'server.environment': 'production',
|
||||
'server.socket_host': cherryhost,
|
||||
'server.socket_port': cherryport,
|
||||
@@ -1294,10 +1307,13 @@ def main():
|
||||
'engine.reexec_retry' : 100,
|
||||
'tools.encode.on' : True,
|
||||
'tools.gzip.on' : True,
|
||||
'tools.sessions.on' : True,
|
||||
'tools.sessions.on' : bool(sessions),
|
||||
'tools.sessions.storage_type' : 'file',
|
||||
'tools.sessions.storage_path' : sessions,
|
||||
'tools.sessions.timeout' : 60,
|
||||
'request.show_tracebacks': True,
|
||||
'checker.check_localhost' : bool(consoleLogging),
|
||||
'error_page.401': sabnzbd.misc.error_page_401
|
||||
'error_page.401': sabnzbd.panic.error_page_401
|
||||
})
|
||||
|
||||
|
||||
@@ -1369,7 +1385,9 @@ def main():
|
||||
sabnzbd.BROWSER_URL = browser_url
|
||||
if not autorestarted:
|
||||
launch_a_browser(browser_url)
|
||||
notify("SAB_Launched", None)
|
||||
if sabnzbd.FOUNDATION:
|
||||
import sabnzbd.osxmenu
|
||||
sabnzbd.osxmenu.notify("SAB_Launched", None)
|
||||
osx.sendGrowlMsg('SABnzbd %s' % (sabnzbd.__version__),"http://%s:%s/sabnzbd" % (browserhost, cherryport),osx.NOTIFICATION['startup'])
|
||||
# Now's the time to check for a new version
|
||||
check_latest_version()
|
||||
@@ -1399,6 +1417,20 @@ def main():
|
||||
if pid_path:
|
||||
sabnzbd.pid_file(pid_path, cherryport)
|
||||
|
||||
# Start all SABnzbd tasks
|
||||
logging.info('Starting %s-%s', sabnzbd.MY_NAME, sabnzbd.__version__)
|
||||
try:
|
||||
sabnzbd.start()
|
||||
except:
|
||||
logging.exception("Failed to start %s-%s", sabnzbd.MY_NAME, sabnzbd.__version__)
|
||||
sabnzbd.halt()
|
||||
|
||||
# Upload any nzb/zip/rar/nzb.gz files from file association
|
||||
if upload_nzbs:
|
||||
from sabnzbd.utils.upload import add_local
|
||||
for f in upload_nzbs:
|
||||
add_local(f)
|
||||
|
||||
# Have to keep this running, otherwise logging will terminate
|
||||
timer = 0
|
||||
while not sabnzbd.SABSTOP:
|
||||
@@ -1488,7 +1520,7 @@ def main():
|
||||
mail.send('stop')
|
||||
if sabnzbd.WIN32:
|
||||
del_connection_info()
|
||||
notify("SAB_Shutdown", None)
|
||||
if sabnzbd.FOUNDATION: sabnzbd.osxmenu.notify("SAB_Shutdown", None)
|
||||
logging.info('Leaving SABnzbd')
|
||||
sys.stderr.flush()
|
||||
sys.stdout.flush()
|
||||
@@ -1620,6 +1652,8 @@ def HandleCommandLine(allow_service=True):
|
||||
#
|
||||
if __name__ == '__main__':
|
||||
|
||||
sabnzbd.CMDLINE = ', '.join(['"%s"' % latin1(p) for p in sys.argv])
|
||||
|
||||
if sabnzbd.WIN32:
|
||||
if not HandleCommandLine(allow_service=not hasattr(sys, "frozen")):
|
||||
main()
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
<span class="SubMenu">
|
||||
<a href="./purge?session=$session" onclick="return confirm('$T('purgeHistConf').replace("'","`") ');">$T('purgeHist')</a> |
|
||||
<a href="./purge_failed?session=$session" onclick="return confirm('$T('purgeHistFailedConf').replace("'","`") ');">$T('purgeHistFailed')</a> |
|
||||
<a href="./purge_failed?session=$session&del_files=1" onclick="return confirm('$T('purgeFailed-Files').replace("'","`") ');">$T('purgeFailed-Files')</a> |
|
||||
<!--#if $isverbose#-->
|
||||
<a href="./tog_verbose?session=$session">$T('hideDetails')</a> |
|
||||
<!--#else#-->
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
<title>SABnzbd $version - $T('queued'): $mbleft $T('MB')</title>
|
||||
<link rel="alternate" type="application/rss+xml" title="RSS 2.0" href="${path}rss?mode=history"/>
|
||||
|
||||
<link rel="stylesheet" type="text/css" href="${path}static/stylesheets/jqueryui/overcast/jquery-ui-1.8.9.custom.css?$version"/>
|
||||
<link rel="stylesheet" type="text/css" href="${path}static/stylesheets/jqueryui/overcast/jquery-ui-1.8.15.custom.css?$version"/>
|
||||
#if $color_scheme#
|
||||
<link rel="shortcut icon" type="image/ico" href="${path}static/stylesheets/colorschemes/$color_scheme/images/sabnzbdplus.ico"/>
|
||||
<link rel="stylesheet" type="text/css" href="${path}static/stylesheets/colorschemes/$color_scheme/${color_scheme}.css?$version"/>
|
||||
|
||||
@@ -79,27 +79,27 @@ jQuery(document).ready(function($){
|
||||
|
||||
// selections
|
||||
$("#nzo_select_all").click(function(){
|
||||
$("INPUT[type='checkbox']").attr('checked', true).trigger('change');
|
||||
$("INPUT[type='checkbox']").prop('checked', true).trigger('change');
|
||||
});
|
||||
var last1, last2;
|
||||
$("#nzo_select_range").click(function(){
|
||||
if (last1 && last2 && last1 < last2)
|
||||
$("INPUT[type='checkbox']").slice(last1,last2).attr('checked', true).trigger('change');
|
||||
$("INPUT[type='checkbox']").slice(last1,last2).prop('checked', true).trigger('change');
|
||||
else if (last1 && last2)
|
||||
$("INPUT[type='checkbox']").slice(last2,last1).attr('checked', true).trigger('change');
|
||||
$("INPUT[type='checkbox']").slice(last2,last1).prop('checked', true).trigger('change');
|
||||
});
|
||||
$("#nzo_select_invert").click(function(){
|
||||
$("INPUT[type='checkbox']").each( function() {
|
||||
$(this).attr('checked', !$(this).attr('checked')).trigger('change');
|
||||
$(this).prop('checked', !$(this).prop('checked')).trigger('change');
|
||||
});
|
||||
});
|
||||
$("#nzo_select_none").click(function(){
|
||||
$("INPUT[type='checkbox']").attr('checked', false).trigger('change');
|
||||
$("INPUT[type='checkbox']").prop('checked', false).trigger('change');
|
||||
});
|
||||
|
||||
// click filenames to select
|
||||
$('#config_content .nzoTable .nzf_row').click(function(event) {
|
||||
$('#box-'+$(event.target).parent().attr('id')).attr('checked', !$('#box-'+$(event.target).parent().attr('id')).attr('checked')).trigger('change');
|
||||
$('#box-'+$(event.target).parent().attr('id')).prop('checked', !$('#box-'+$(event.target).parent().attr('id')).prop('checked')).trigger('change');
|
||||
|
||||
// range event interaction -- see further above
|
||||
if (last1) last2 = last1;
|
||||
@@ -108,7 +108,7 @@ jQuery(document).ready(function($){
|
||||
|
||||
//
|
||||
$('#config_content .nzoTable .nzf_row input').change(function(e){
|
||||
if ($(e.target).attr('checked'))
|
||||
if ($(e.target).prop('checked'))
|
||||
$(e.target).parent().parent().addClass("nzo_highlight");
|
||||
else
|
||||
$(e.target).parent().parent().removeClass("nzo_highlight");
|
||||
|
||||
@@ -161,20 +161,20 @@ jQuery(function($){
|
||||
}).trigger('change');
|
||||
|
||||
// Confirm Queue Deletions toggle
|
||||
$("#confirmDeleteQueue").attr('checked', $.plush.confirmDeleteQueue ).change( function() {
|
||||
$.plush.confirmDeleteQueue = $("#confirmDeleteQueue").attr('checked');
|
||||
$("#confirmDeleteQueue").prop('checked', $.plush.confirmDeleteQueue ).change( function() {
|
||||
$.plush.confirmDeleteQueue = $("#confirmDeleteQueue").prop('checked');
|
||||
$.cookie('plushConfirmDeleteQueue', $.plush.confirmDeleteQueue ? 1 : 0, { expires: 365, path: '/' });
|
||||
});
|
||||
|
||||
// Confirm History Deletions toggle
|
||||
$("#confirmDeleteHistory").attr('checked', $.plush.confirmDeleteHistory ).change( function() {
|
||||
$.plush.confirmDeleteHistory = $("#confirmDeleteHistory").attr('checked');
|
||||
$("#confirmDeleteHistory").prop('checked', $.plush.confirmDeleteHistory ).change( function() {
|
||||
$.plush.confirmDeleteHistory = $("#confirmDeleteHistory").prop('checked');
|
||||
$.cookie('plushConfirmDeleteHistory', $.plush.confirmDeleteHistory ? 1 : 0, { expires: 365, path: '/' });
|
||||
});
|
||||
|
||||
// Block Refreshes on Hover toggle
|
||||
$("#blockRefresh").attr('checked', $.plush.blockRefresh ).change( function() {
|
||||
$.plush.blockRefresh = $("#blockRefresh").attr('checked');
|
||||
$("#blockRefresh").prop('checked', $.plush.blockRefresh ).change( function() {
|
||||
$.plush.blockRefresh = $("#blockRefresh").prop('checked');
|
||||
$.cookie('plushBlockRefresh', $.plush.blockRefresh ? 1 : 0, { expires: 365, path: '/' });
|
||||
});
|
||||
|
||||
@@ -690,22 +690,22 @@ $.plush.queueprevslots = $.plush.queuenoofslots; // for the next refresh
|
||||
|
||||
// selections
|
||||
$("#multiops_select_all").click(function(){
|
||||
$("INPUT[type='checkbox']","#queueTable").attr('checked', true).trigger('change');
|
||||
$("INPUT[type='checkbox']","#queueTable").prop('checked', true).trigger('change');
|
||||
});
|
||||
var last1, last2;
|
||||
$("#multiops_select_range").click(function(){
|
||||
if (last1 && last2 && last1 < last2)
|
||||
$("INPUT[type='checkbox']","#queueTable").slice(last1,last2).attr('checked', true).trigger('change');
|
||||
$("INPUT[type='checkbox']","#queueTable").slice(last1,last2).prop('checked', true).trigger('change');
|
||||
else if (last1 && last2)
|
||||
$("INPUT[type='checkbox']","#queueTable").slice(last2,last1).attr('checked', true).trigger('change');
|
||||
$("INPUT[type='checkbox']","#queueTable").slice(last2,last1).prop('checked', true).trigger('change');
|
||||
});
|
||||
$("#multiops_select_invert").click(function(){
|
||||
$("INPUT[type='checkbox']","#queueTable").each( function() {
|
||||
$(this).attr('checked', !$(this).attr('checked')).trigger('change');
|
||||
$(this).prop('checked', !$(this).prop('checked')).trigger('change');
|
||||
});
|
||||
});
|
||||
$("#multiops_select_none").click(function(){
|
||||
$("INPUT[type='checkbox']","#queueTable").attr('checked', false).trigger('change');
|
||||
$("INPUT[type='checkbox']","#queueTable").prop('checked', false).trigger('change');
|
||||
});
|
||||
$("#queue").delegate('.multiops','change',function(event) {
|
||||
// range event interaction
|
||||
@@ -713,7 +713,7 @@ $.plush.queueprevslots = $.plush.queuenoofslots; // for the next refresh
|
||||
last1 = $(event.target).parent()[0].rowIndex ? $(event.target).parent()[0].rowIndex : $(event.target).parent().parent()[0].rowIndex;
|
||||
|
||||
// checkbox state persistence
|
||||
if ($(this).attr('checked'))
|
||||
if ($(this).prop('checked'))
|
||||
$.plush.multiOpsChecks[$(this).parent().parent().attr('id')] = true;
|
||||
else if ($.plush.multiOpsChecks[$(this).parent().parent().attr('id')])
|
||||
delete $.plush.multiOpsChecks[$(this).parent().parent().attr('id')];
|
||||
@@ -740,7 +740,7 @@ $("a","#multiops_inputs").click(function(e){
|
||||
nzo_ids = nzo_ids.substr(1);
|
||||
if (!nzo_ids) return;
|
||||
|
||||
$(this).attr('disabled',true);
|
||||
$(this).prop('disabled',true);
|
||||
|
||||
if ($('#multi_status').val())
|
||||
$.ajax({
|
||||
@@ -777,7 +777,7 @@ $("a","#multiops_inputs").click(function(e){
|
||||
data: {mode: 'change_script', value: nzo_ids, value2: $('#multi_script').val(), apikey: $.plush.apikey}
|
||||
});
|
||||
|
||||
$(this).attr('disabled',false);
|
||||
$(this).prop('disabled',false);
|
||||
$.plush.RefreshQueue();
|
||||
});
|
||||
|
||||
@@ -908,10 +908,10 @@ $("a","#multiops_inputs").click(function(e){
|
||||
$('#delete_nzb_modal_title').text( $(this).parent().prev().prev().children('a:first').text() );
|
||||
$('#delete_nzb_modal_job').val( $(this).parent().parent().attr('id') );
|
||||
$('#delete_nzb_modal_mode').val( 'history' );
|
||||
if ($(this).parent().parent().children('td:first').children().hasClass('sprite_hv_error'))
|
||||
$('#delete_nzb_modal_remove_files').button('enable');
|
||||
else
|
||||
if ($(this).parent().parent().children('td:first').children().hasClass('sprite_hv_star'))
|
||||
$('#delete_nzb_modal_remove_files').button('disable');
|
||||
else
|
||||
$('#delete_nzb_modal_remove_files').button('enable');
|
||||
$.colorbox({ inline:true, href:"#delete_nzb_modal", title:$(this).text(),
|
||||
innerWidth:"600px", innerHeight:"150px", initialWidth:"600px", initialHeight:"150px", speed:0, opacity:0.7
|
||||
});
|
||||
@@ -1073,7 +1073,7 @@ $.plush.histprevslots = $.plush.histnoofslots; // for the next refresh
|
||||
$('<input type="checkbox" class="multiops" />').appendTo('#queue tr td.nzb_status_col');
|
||||
if ($.plush.multiOpsChecks) // checkbox state persistence
|
||||
for (var nzo_id in $.plush.multiOpsChecks)
|
||||
$('#'+nzo_id+' .multiops').attr('checked',true);
|
||||
$('#'+nzo_id+' .multiops').prop('checked',true);
|
||||
|
||||
|
||||
$('#queue-pagination span').removeClass('loading'); // Remove spinner graphic from pagination
|
||||
|
||||
@@ -287,7 +287,7 @@ body {
|
||||
}
|
||||
|
||||
.navigation ul li a {
|
||||
color:#fff;
|
||||
color:#efefef;
|
||||
font-weight:bold;
|
||||
display: block;
|
||||
padding: 0 8px 0 0;
|
||||
@@ -297,9 +297,10 @@ body {
|
||||
line-height: 25px;
|
||||
background-color:#363636;
|
||||
/* background : -webkit-gradient(linear, right top, right bottom, from(rgb(168,168,168)), to(rgb(69,69,69)));
|
||||
background : -moz-linear-gradient(top, rgb(168,168,168), rgb(69,69,69)); */
|
||||
background : -moz-linear-gradient(top, rgb(168,168,168), rgb(69,69,69));
|
||||
-webkit-transition-property: background;
|
||||
-webkit-transition-duration: 700ms;
|
||||
*/
|
||||
-moz-transition-property: background;
|
||||
-moz-transition-duration: 700ms;
|
||||
}
|
||||
|
||||
|
Before Width: | Height: | Size: 105 B After Width: | Height: | Size: 129 B |
|
Before Width: | Height: | Size: 96 B After Width: | Height: | Size: 142 B |
|
Before Width: | Height: | Size: 4.3 KiB After Width: | Height: | Size: 5.2 KiB |
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* jQuery UI CSS Framework 1.8.9
|
||||
* jQuery UI CSS Framework 1.8.15
|
||||
*
|
||||
* Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
|
||||
* Dual licensed under the MIT or GPL Version 2 licenses.
|
||||
@@ -42,7 +42,7 @@
|
||||
|
||||
|
||||
/*
|
||||
* jQuery UI CSS Framework 1.8.9
|
||||
* jQuery UI CSS Framework 1.8.15
|
||||
*
|
||||
* Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
|
||||
* Dual licensed under the MIT or GPL Version 2 licenses.
|
||||
@@ -280,20 +280,44 @@
|
||||
----------------------------------*/
|
||||
|
||||
/* Corner radius */
|
||||
.ui-corner-tl { -moz-border-radius-topleft: 6px; -webkit-border-top-left-radius: 6px; border-top-left-radius: 6px; }
|
||||
.ui-corner-tr { -moz-border-radius-topright: 6px; -webkit-border-top-right-radius: 6px; border-top-right-radius: 6px; }
|
||||
.ui-corner-bl { -moz-border-radius-bottomleft: 6px; -webkit-border-bottom-left-radius: 6px; border-bottom-left-radius: 6px; }
|
||||
.ui-corner-br { -moz-border-radius-bottomright: 6px; -webkit-border-bottom-right-radius: 6px; border-bottom-right-radius: 6px; }
|
||||
.ui-corner-top { -moz-border-radius-topleft: 6px; -webkit-border-top-left-radius: 6px; border-top-left-radius: 6px; -moz-border-radius-topright: 6px; -webkit-border-top-right-radius: 6px; border-top-right-radius: 6px; }
|
||||
.ui-corner-bottom { -moz-border-radius-bottomleft: 6px; -webkit-border-bottom-left-radius: 6px; border-bottom-left-radius: 6px; -moz-border-radius-bottomright: 6px; -webkit-border-bottom-right-radius: 6px; border-bottom-right-radius: 6px; }
|
||||
.ui-corner-right { -moz-border-radius-topright: 6px; -webkit-border-top-right-radius: 6px; border-top-right-radius: 6px; -moz-border-radius-bottomright: 6px; -webkit-border-bottom-right-radius: 6px; border-bottom-right-radius: 6px; }
|
||||
.ui-corner-left { -moz-border-radius-topleft: 6px; -webkit-border-top-left-radius: 6px; border-top-left-radius: 6px; -moz-border-radius-bottomleft: 6px; -webkit-border-bottom-left-radius: 6px; border-bottom-left-radius: 6px; }
|
||||
.ui-corner-all { -moz-border-radius: 6px; -webkit-border-radius: 6px; border-radius: 6px; }
|
||||
.ui-corner-all, .ui-corner-top, .ui-corner-left, .ui-corner-tl { -moz-border-radius-topleft: 6px; -webkit-border-top-left-radius: 6px; -khtml-border-top-left-radius: 6px; border-top-left-radius: 6px; }
|
||||
.ui-corner-all, .ui-corner-top, .ui-corner-right, .ui-corner-tr { -moz-border-radius-topright: 6px; -webkit-border-top-right-radius: 6px; -khtml-border-top-right-radius: 6px; border-top-right-radius: 6px; }
|
||||
.ui-corner-all, .ui-corner-bottom, .ui-corner-left, .ui-corner-bl { -moz-border-radius-bottomleft: 6px; -webkit-border-bottom-left-radius: 6px; -khtml-border-bottom-left-radius: 6px; border-bottom-left-radius: 6px; }
|
||||
.ui-corner-all, .ui-corner-bottom, .ui-corner-right, .ui-corner-br { -moz-border-radius-bottomright: 6px; -webkit-border-bottom-right-radius: 6px; -khtml-border-bottom-right-radius: 6px; border-bottom-right-radius: 6px; }
|
||||
|
||||
/* Overlays */
|
||||
.ui-widget-overlay { background: #eeeeee url(images/ui-bg_flat_0_eeeeee_40x100.png) 50% 50% repeat-x; opacity: .80;filter:Alpha(Opacity=80); }
|
||||
.ui-widget-shadow { margin: -4px 0 0 -4px; padding: 4px; background: #aaaaaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x; opacity: .60;filter:Alpha(Opacity=60); -moz-border-radius: 0pxdow=0px; -webkit-border-radius: 0pxdow=0px; border-radius: 0pxdow=0px; }/*
|
||||
* jQuery UI Button 1.8.9
|
||||
.ui-widget-shadow { margin: -4px 0 0 -4px; padding: 4px; background: #aaaaaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x; opacity: .60;filter:Alpha(Opacity=60); -moz-border-radius: 0pxdow=0px; -khtml-border-radius: 0pxdow=0px; -webkit-border-radius: 0pxdow=0px; border-radius: 0pxdow=0px; }/*
|
||||
* jQuery UI Resizable 1.8.15
|
||||
*
|
||||
* Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
|
||||
* Dual licensed under the MIT or GPL Version 2 licenses.
|
||||
* http://jquery.org/license
|
||||
*
|
||||
* http://docs.jquery.com/UI/Resizable#theming
|
||||
*/
|
||||
.ui-resizable { position: relative;}
|
||||
.ui-resizable-handle { position: absolute;font-size: 0.1px;z-index: 99999; display: block; }
|
||||
.ui-resizable-disabled .ui-resizable-handle, .ui-resizable-autohide .ui-resizable-handle { display: none; }
|
||||
.ui-resizable-n { cursor: n-resize; height: 7px; width: 100%; top: -5px; left: 0; }
|
||||
.ui-resizable-s { cursor: s-resize; height: 7px; width: 100%; bottom: -5px; left: 0; }
|
||||
.ui-resizable-e { cursor: e-resize; width: 7px; right: -5px; top: 0; height: 100%; }
|
||||
.ui-resizable-w { cursor: w-resize; width: 7px; left: -5px; top: 0; height: 100%; }
|
||||
.ui-resizable-se { cursor: se-resize; width: 12px; height: 12px; right: 1px; bottom: 1px; }
|
||||
.ui-resizable-sw { cursor: sw-resize; width: 9px; height: 9px; left: -5px; bottom: -5px; }
|
||||
.ui-resizable-nw { cursor: nw-resize; width: 9px; height: 9px; left: -5px; top: -5px; }
|
||||
.ui-resizable-ne { cursor: ne-resize; width: 9px; height: 9px; right: -5px; top: -5px;}/*
|
||||
* jQuery UI Selectable 1.8.15
|
||||
*
|
||||
* Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
|
||||
* Dual licensed under the MIT or GPL Version 2 licenses.
|
||||
* http://jquery.org/license
|
||||
*
|
||||
* http://docs.jquery.com/UI/Selectable#theming
|
||||
*/
|
||||
.ui-selectable-helper { position: absolute; z-index: 100; border:1px dotted black; }
|
||||
/*
|
||||
* jQuery UI Button 1.8.15
|
||||
*
|
||||
* Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
|
||||
* Dual licensed under the MIT or GPL Version 2 licenses.
|
||||
@@ -331,7 +355,28 @@ input.ui-button { padding: .4em 1em; }
|
||||
/* workarounds */
|
||||
button.ui-button::-moz-focus-inner { border: 0; padding: 0; } /* reset extra padding in Firefox */
|
||||
/*
|
||||
* jQuery UI Tabs 1.8.9
|
||||
* jQuery UI Dialog 1.8.15
|
||||
*
|
||||
* Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
|
||||
* Dual licensed under the MIT or GPL Version 2 licenses.
|
||||
* http://jquery.org/license
|
||||
*
|
||||
* http://docs.jquery.com/UI/Dialog#theming
|
||||
*/
|
||||
.ui-dialog { position: absolute; padding: .2em; width: 300px; overflow: hidden; }
|
||||
.ui-dialog .ui-dialog-titlebar { padding: .4em 1em; position: relative; }
|
||||
.ui-dialog .ui-dialog-title { float: left; margin: .1em 16px .1em 0; }
|
||||
.ui-dialog .ui-dialog-titlebar-close { position: absolute; right: .3em; top: 50%; width: 19px; margin: -10px 0 0 0; padding: 1px; height: 18px; }
|
||||
.ui-dialog .ui-dialog-titlebar-close span { display: block; margin: 1px; }
|
||||
.ui-dialog .ui-dialog-titlebar-close:hover, .ui-dialog .ui-dialog-titlebar-close:focus { padding: 0; }
|
||||
.ui-dialog .ui-dialog-content { position: relative; border: 0; padding: .5em 1em; background: none; overflow: auto; zoom: 1; }
|
||||
.ui-dialog .ui-dialog-buttonpane { text-align: left; border-width: 1px 0 0 0; background-image: none; margin: .5em 0 0 0; padding: .3em 1em .5em .4em; }
|
||||
.ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset { float: right; }
|
||||
.ui-dialog .ui-dialog-buttonpane button { margin: .5em .4em .5em 0; cursor: pointer; }
|
||||
.ui-dialog .ui-resizable-se { width: 14px; height: 14px; right: 3px; bottom: 3px; }
|
||||
.ui-draggable .ui-dialog-titlebar { cursor: move; }
|
||||
/*
|
||||
* jQuery UI Tabs 1.8.15
|
||||
*
|
||||
* Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
|
||||
* Dual licensed under the MIT or GPL Version 2 licenses.
|
||||
@@ -8,6 +8,7 @@
|
||||
<div class="centerLinks"><br />
|
||||
<a onClick="if(confirm('$T('purgeHistConf')')){javascript:loadSearch('history/purge', 'historySearch', 'limit=$limit&start=0', -1,this.parentNode.parentNode.id);}">$T('smpl-purgehist')</a> |
|
||||
<a onClick="if(confirm('$T('smpl-purgefailhistOK?')')){javascript:loadSearch('history/purge_failed', 'historySearch', 'limit=$limit&start=0', -1,this.parentNode.parentNode.id);}">$T('smpl-purgefailhist')</a> |
|
||||
<a onClick="if(confirm('$T('smpl-purgefailhistOK?')')){javascript:loadSearch('history/purge_failed', 'historySearch', 'limit=$limit&start=0&del_files=1', -1,this.parentNode.parentNode.id);}">$T('purgeFailed-Files')</a> |
|
||||
<a onClick="javascript:loadSearch('history/tog_verbose', 'historySearch', 'limit=$limit&start=0', -1,this.parentNode.parentNode.id);"><!--#if $isverbose then $T('hideDetails') else $T('showDetails')#--></a> |
|
||||
<a onClick="javascript:loadSearch('history/tog_failed_only', 'historySearch', 'limit=$limit&start=0', -1,this.parentNode.parentNode.id);"><!--#if $failed_only then $T('showAllHis') else $T('showFailedHis')#--></a>
|
||||
</span>
|
||||
|
||||
@@ -1015,10 +1015,6 @@ function loadingJSON(){
|
||||
document.getElementById("mbtotal").innerHTML = info["mb"].toFixed(2);
|
||||
document.getElementById("ds1").innerHTML = info["diskspace1"].toFixed(2);
|
||||
document.getElementById("ds2").innerHTML = info["diskspace2"].toFixed(2);
|
||||
//var perc1 = 1 - (info["jobs"][0]["mbleft"].toFixed(2) / info["jobs"][0]["mb"].toFixed(2))
|
||||
//alert(info["jobs"][0]);
|
||||
if (info["jobs"]!="") document.getElementById("downloadinfo").innerHTML = "$T('smpl-downloading'): "+info["jobs"][0]["filename"];
|
||||
else document.getElementById("downloadinfo").innerHTML = "";
|
||||
document.getElementById("have_warnings").innerHTML = info["have_warnings"];
|
||||
load = document.getElementById("loadavg")
|
||||
if (load) load.innerHTML = info["loadavg"];
|
||||
@@ -1252,7 +1248,6 @@ function loadingJSON(){
|
||||
</div>
|
||||
<div id="Footer">
|
||||
<div id="divchart"><canvas id="graph" height="100" width="700"></canvas></div>
|
||||
<span id="downloadinfo"></span><br /><br />
|
||||
<p id="versions">$T("smpl-refreshr"): <select id="refreshrate" onchange="javascript:applyrefresh(this.options[this.selectedIndex].value)">
|
||||
<option value="2" >2 $T("seconds")</option>
|
||||
<option value="3" >3 $T("seconds")</option>
|
||||
|
||||
BIN
osx/image/sabnzbd_leopard.png
Normal file
|
After Width: | Height: | Size: 89 KiB |
BIN
osx/image/sabnzbd_lion.png
Normal file
|
After Width: | Height: | Size: 88 KiB |
BIN
osx/image/template.sparseimage.zip
Normal file
34
osx/unrar/license.txt
Normal file
@@ -0,0 +1,34 @@
|
||||
****** ***** ****** UnRAR - free utility for RAR archives
|
||||
** ** ** ** ** ** ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
****** ******* ****** License for use and distribution of
|
||||
** ** ** ** ** ** ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
** ** ** ** ** ** FREEWARE version
|
||||
~~~~~~~~~~~~~~~~
|
||||
|
||||
The UnRAR utility is freeware. This means:
|
||||
|
||||
1. All copyrights to RAR and the utility UnRAR are exclusively
|
||||
owned by the author - Alexander Roshal.
|
||||
|
||||
2. The UnRAR utility may be freely distributed. It is allowed
|
||||
to distribute UnRAR inside of other software packages.
|
||||
|
||||
3. THE RAR ARCHIVER AND THE UnRAR UTILITY ARE DISTRIBUTED "AS IS".
|
||||
NO WARRANTY OF ANY KIND IS EXPRESSED OR IMPLIED. YOU USE AT
|
||||
YOUR OWN RISK. THE AUTHOR WILL NOT BE LIABLE FOR DATA LOSS,
|
||||
DAMAGES, LOSS OF PROFITS OR ANY OTHER KIND OF LOSS WHILE USING
|
||||
OR MISUSING THIS SOFTWARE.
|
||||
|
||||
4. Neither RAR binary code, WinRAR binary code, UnRAR source or UnRAR
|
||||
binary code may be used or reverse engineered to re-create the RAR
|
||||
compression algorithm, which is proprietary, without written
|
||||
permission of the author.
|
||||
|
||||
5. If you don't agree with terms of the license you must remove
|
||||
UnRAR files from your storage devices and cease to use the
|
||||
utility.
|
||||
|
||||
Thank you for your interest in RAR and UnRAR.
|
||||
|
||||
|
||||
Alexander L. Roshal
|
||||
BIN
osx/unrar/unrar
151
package.py
@@ -48,7 +48,8 @@ def DeleteFiles(name):
|
||||
''' Delete one file or set of files from wild-card spec '''
|
||||
for f in glob.glob(name):
|
||||
try:
|
||||
os.remove(f)
|
||||
if os.path.exists(f):
|
||||
os.remove(f)
|
||||
except:
|
||||
print "Cannot remove file %s" % f
|
||||
exit(1)
|
||||
@@ -70,26 +71,38 @@ def CheckPath(name):
|
||||
|
||||
|
||||
def PatchVersion(name):
|
||||
""" Patch in the Bazaar baseline number, but only when this is
|
||||
""" Patch in the Git commit hash, but only when this is
|
||||
an unmodified checkout
|
||||
"""
|
||||
global my_version, my_baseline
|
||||
|
||||
commit = ''
|
||||
try:
|
||||
pipe = subprocess.Popen(BzrVersion, shell=True, stdout=subprocess.PIPE).stdout
|
||||
pipe = subprocess.Popen(GitVersion, shell=True, stdout=subprocess.PIPE).stdout
|
||||
for line in pipe.read().split('\n'):
|
||||
if 'revno: ' in line:
|
||||
bzr = line.split(' ')[1].strip()
|
||||
if 'commit ' in line:
|
||||
commit = line.split(' ')[1].strip()
|
||||
break
|
||||
pipe.close()
|
||||
except:
|
||||
pass
|
||||
print 'Cannot run %s' % GitVersion
|
||||
exit(1)
|
||||
|
||||
if not bzr:
|
||||
print "WARNING: Cannot run %s" % BzrVersion
|
||||
bzr = 'unknown'
|
||||
state = ' (not committed)'
|
||||
try:
|
||||
pipe = subprocess.Popen(GitStatus, shell=True, stdout=subprocess.PIPE).stdout
|
||||
for line in pipe.read().split('\n'):
|
||||
if 'nothing to commit' in line:
|
||||
state = ''
|
||||
break
|
||||
pipe.close()
|
||||
except:
|
||||
print 'Cannot run %s' % GitStatus
|
||||
exit(1)
|
||||
|
||||
if not (bzr and bzr.isdigit()):
|
||||
bzr = 'unknown'
|
||||
if not commit:
|
||||
print "WARNING: Cannot run %s" % GitVersion
|
||||
commit = 'unknown'
|
||||
|
||||
try:
|
||||
ver = open(VERSION_FILE, 'rb')
|
||||
@@ -99,12 +112,12 @@ def PatchVersion(name):
|
||||
print "WARNING: cannot patch " + VERSION_FILE
|
||||
return
|
||||
|
||||
my_baseline = bzr
|
||||
my_baseline = commit + state
|
||||
my_version = name
|
||||
|
||||
regex = re.compile(r'__baseline__\s+=\s+"\w*"')
|
||||
text = re.sub(r'__baseline__\s*=\s*"[^"]*"', '__baseline__ = "%s"' % bzr, text)
|
||||
text = re.sub(r'__version__\s*=\s*"[^"]*"', '__version__ = "%s"' % name, text)
|
||||
text = re.sub(r'__baseline__\s*=\s*"[^"]*"', '__baseline__ = "%s"' % my_baseline, text)
|
||||
text = re.sub(r'__version__\s*=\s*"[^"]*"', '__version__ = "%s"' % my_version, text)
|
||||
|
||||
try:
|
||||
ver = open(VERSION_FILE, 'wb')
|
||||
@@ -120,14 +133,14 @@ def PairList(src):
|
||||
A dir returns for its root and each of its subdirs
|
||||
(path, <list-of-files>)
|
||||
Always return paths with Unix slashes.
|
||||
Skip all Bazaar elements, .bak .pyc .pyo and *.~*
|
||||
Skip all Git elements, .bak .pyc .pyo and *.~*
|
||||
"""
|
||||
lst = []
|
||||
for item in src:
|
||||
if item.endswith('/'):
|
||||
for root, dirs, files in os.walk(item.rstrip('/\\')):
|
||||
path = root.replace('\\', '/')
|
||||
if path.find('.bzr') < 0:
|
||||
if path.find('.git') < 0:
|
||||
flist = []
|
||||
for file in files:
|
||||
if not (file.endswith('.bak') or file.endswith('.pyc') or file.endswith('.pyo') or '~' in file):
|
||||
@@ -239,18 +252,27 @@ def check_runtimes():
|
||||
if path:
|
||||
path = os.path.join(path, 'Bazaar')
|
||||
if not os.path.exists(path):
|
||||
path = None
|
||||
if not path:
|
||||
print 'Cannot find runtime libraries, have you installed Bazaar'
|
||||
print 'in %s ?' % path
|
||||
exit(1)
|
||||
print 'Cannot find runtime libraries, have you installed Bazaar'
|
||||
print 'in %s ?' % path
|
||||
exit(1)
|
||||
return path
|
||||
|
||||
def write_dll_message(path):
|
||||
f = open(path, 'w')
|
||||
f.write('''
|
||||
**** IMPORTANT ****
|
||||
|
||||
If you get a Windows error message, claiming that DLL files are missing,
|
||||
please install "Microsoft Visual C++ 2008 Redistributable Package (x86)".
|
||||
Download from http://www.microsoft.com/download/en/details.aspx?displaylang=en&id=29
|
||||
Install this and *not* the SP1 package (or install both).
|
||||
|
||||
''')
|
||||
f.close()
|
||||
|
||||
print sys.argv[0]
|
||||
|
||||
Bazaar = CheckPath('bzr')
|
||||
Git = CheckPath('git')
|
||||
ZipCmd = CheckPath('zip')
|
||||
UnZipCmd = CheckPath('unzip')
|
||||
if os.name == 'nt':
|
||||
@@ -258,12 +280,13 @@ if os.name == 'nt':
|
||||
else:
|
||||
NSIS = '-'
|
||||
|
||||
BzrRevertApp = Bazaar + ' revert '
|
||||
BzrUpdateApp = Bazaar + ' update '
|
||||
BzrRevert = Bazaar + ' revert ' + VERSION_FILE
|
||||
BzrVersion = Bazaar + ' version-info'
|
||||
GitRevertApp = Git + ' checkout -- '
|
||||
#GitUpdateApp = Git + ' update '
|
||||
GitRevertVersion = GitRevertApp + ' ' + VERSION_FILE
|
||||
GitVersion = Git + ' log -1'
|
||||
GitStatus = Git + ' status'
|
||||
|
||||
if not (BzrVersion and BzrRevert and ZipCmd and UnZipCmd and NSIS):
|
||||
if not (Git and ZipCmd and UnZipCmd and NSIS):
|
||||
exit(1)
|
||||
|
||||
if len(sys.argv) < 2:
|
||||
@@ -299,6 +322,7 @@ PatchVersion(release)
|
||||
|
||||
# List of data elements, directories end with a '/'
|
||||
data_files = [
|
||||
'ABOUT.txt',
|
||||
'README.txt',
|
||||
'INSTALL.txt',
|
||||
'GPL2.txt',
|
||||
@@ -307,6 +331,7 @@ data_files = [
|
||||
'COPYRIGHT.txt',
|
||||
'ISSUES.txt',
|
||||
'nzb.ico',
|
||||
'sabnzbd.ico',
|
||||
'Sample-PostProc.cmd',
|
||||
'Sample-PostProc.sh',
|
||||
'PKG-INFO',
|
||||
@@ -341,15 +366,29 @@ options = dict(
|
||||
if target == 'app':
|
||||
if not platform.system() == 'Darwin':
|
||||
print "Sorry, only works on Apple OSX!"
|
||||
os.system(BzrRevert)
|
||||
os.system(GitRevertVersion)
|
||||
exit(1)
|
||||
|
||||
# Check which Python flavour
|
||||
apple_py = 'ActiveState' not in sys.copyright
|
||||
|
||||
#Create sparseimage from template
|
||||
os.system("unzip sabnzbd-template.sparseimage.zip")
|
||||
os.rename('sabnzbd-template.sparseimage', fileImg)
|
||||
os.system("unzip osx/image/template.sparseimage.zip")
|
||||
os.rename('template.sparseimage', fileImg)
|
||||
|
||||
#mount sparseimage and modify volume label
|
||||
os.system("hdiutil mount %s | grep /Volumes/SABnzbd >mount.log" % (fileImg))
|
||||
|
||||
# Add OS version specific background image
|
||||
# Use cat-append to preserve the special attributes of the background image file
|
||||
if [int(n) for n in platform.mac_ver()[0].split('.')] >= [10, 7, 0]:
|
||||
# Lion and higher
|
||||
os.system('cat osx/image/sabnzbd_lion.png >>/Volumes/SABnzbd/sabnzbd.png')
|
||||
else:
|
||||
# Snow Leopard and lower
|
||||
os.system('cat osx/image/sabnzbd_leopard.png >>/Volumes/SABnzbd/sabnzbd.png')
|
||||
|
||||
# Rename the volume
|
||||
fp = open('mount.log', 'r')
|
||||
data = fp.read()
|
||||
fp.close()
|
||||
@@ -366,6 +405,11 @@ if target == 'app':
|
||||
#build SABnzbd.py
|
||||
sys.argv[1] = 'py2app'
|
||||
|
||||
# Due to ApplePython bug
|
||||
if apple_py:
|
||||
sys.argv.append('-p');
|
||||
sys.argv.append('email');
|
||||
|
||||
APP = ['SABnzbd.py']
|
||||
DATA_FILES = ['interfaces', 'locale', 'email', ('',glob.glob("osx/resources/*"))]
|
||||
|
||||
@@ -378,7 +422,7 @@ if target == 'app':
|
||||
LSTypeIsPackage = 0,
|
||||
NSPersistentStoreTypeKey = 'Binary',
|
||||
)
|
||||
OPTIONS = {'argv_emulation': True, 'iconfile': 'osx/resources/sabnzbdplus.icns','plist': {
|
||||
OPTIONS = {'argv_emulation': not apple_py, 'iconfile': 'osx/resources/sabnzbdplus.icns','plist': {
|
||||
'NSUIElement':1,
|
||||
'CFBundleShortVersionString':release,
|
||||
'NSHumanReadableCopyright':'The SABnzbd-Team',
|
||||
@@ -399,15 +443,15 @@ if target == 'app':
|
||||
os.system("cp -pR osx/par2/ dist/SABnzbd.app/Contents/Resources/osx/par2>/dev/null")
|
||||
os.system("mkdir dist/SABnzbd.app/Contents/Resources/osx/unrar>/dev/null")
|
||||
os.system("cp -pR osx/unrar/ dist/SABnzbd.app/Contents/Resources/osx/unrar>/dev/null")
|
||||
os.system("find dist/SABnzbd.app -name .bzr | xargs rm -rf")
|
||||
os.system("find dist/SABnzbd.app -name .git | xargs rm -rf")
|
||||
|
||||
#copy builded app to mounted sparseimage
|
||||
os.system("cp -r dist/SABnzbd.app /Volumes/%s/>/dev/null" % volume)
|
||||
|
||||
#Create src tar.gz
|
||||
#os.system('tar -czf %s --exclude ".bzr" --exclude "sab*.zip" --exclude "SAB*.tar.gz" --exclude "*.cmd" --exclude "*.pyc" '
|
||||
# '--exclude "*.sparseimage" --exclude "dist" --exclude "build" --exclude "*.nsi" --exclude "win"'
|
||||
# './ >/dev/null' % (fileOSr) )
|
||||
print 'Create src %s' % fileOSr
|
||||
os.system('tar -czf %s --exclude ".git*" --exclude "sab*.zip" --exclude "SAB*.tar.gz" --exclude "*.cmd" --exclude "*.pyc" '
|
||||
'--exclude "*.sparseimage" --exclude "dist" --exclude "build" --exclude "*.nsi" --exclude "win" --exclude "*.dmg" '
|
||||
'./ >/dev/null' % (fileOSr) )
|
||||
|
||||
# Copy README.txt
|
||||
os.system("cp README.rtf /Volumes/%s/" % volume)
|
||||
@@ -427,18 +471,17 @@ if target == 'app':
|
||||
os.system("hdiutil internet-enable %s" % fileDmg)
|
||||
|
||||
|
||||
os.system(BzrRevertApp + "NSIS_Installer.nsi")
|
||||
os.system(BzrRevertApp + VERSION_FILEAPP)
|
||||
os.system(BzrRevertApp + VERSION_FILE)
|
||||
os.system(BzrUpdateApp)
|
||||
os.system(GitRevertApp + "NSIS_Installer.nsi")
|
||||
os.system(GitRevertApp + VERSION_FILEAPP)
|
||||
os.system(GitRevertApp + VERSION_FILE)
|
||||
|
||||
elif target in ('binary', 'installer'):
|
||||
if not py2exe:
|
||||
print "Sorry, only works on Windows!"
|
||||
os.system(BzrRevert)
|
||||
os.system(GitRevertVersion)
|
||||
exit(1)
|
||||
|
||||
run_times = check_runtimes()
|
||||
#run_times = check_runtimes()
|
||||
|
||||
# Create MO files
|
||||
os.system('tools\\make_mo.py all')
|
||||
@@ -513,14 +556,21 @@ elif target in ('binary', 'installer'):
|
||||
rename_file('dist', Win32HelperName, Win32ServiceHelpName)
|
||||
|
||||
|
||||
############################
|
||||
# Remove unwanted system DLL files that Py2Exe copies when running on Win7
|
||||
DeleteFiles(r'dist\lib\API-MS-Win-*.dll')
|
||||
DeleteFiles(r'dist\lib\MSWSOCK.DLL')
|
||||
DeleteFiles(r'dist\lib\POWRPROF.DLL')
|
||||
|
||||
############################
|
||||
# Copy MS runtime files or Curl
|
||||
if run_times:
|
||||
# MS Runtimes for Python 2.6+
|
||||
shutil.copy2(os.path.join(run_times, r'Microsoft.VC90.CRT.manifest'), r'dist')
|
||||
shutil.copy2(os.path.join(run_times, r'msvcp90.dll'), r'dist')
|
||||
shutil.copy2(os.path.join(run_times, r'msvcr90.dll'), r'dist')
|
||||
shutil.copy2(os.path.join(run_times, r'lib\Microsoft.VC90.CRT.manifest'), r'dist\lib')
|
||||
if sys.version > (2, 5):
|
||||
#Won't work with OpenSSL DLLs :(
|
||||
#shutil.copy2(os.path.join(run_times, r'Microsoft.VC90.CRT.manifest'), r'dist')
|
||||
#shutil.copy2(os.path.join(run_times, r'msvcp90.dll'), r'dist')
|
||||
#shutil.copy2(os.path.join(run_times, r'msvcr90.dll'), r'dist')
|
||||
#shutil.copy2(os.path.join(run_times, r'lib\Microsoft.VC90.CRT.manifest'), r'dist\lib')
|
||||
pass
|
||||
else:
|
||||
# Curl for Python 2.5
|
||||
os.system(r'unzip -o win\curl\curl.zip -d dist\lib')
|
||||
@@ -534,12 +584,13 @@ elif target in ('binary', 'installer'):
|
||||
|
||||
|
||||
DeleteFiles(fileBin)
|
||||
write_dll_message('dist/IMPORTANT_MESSAGE.txt')
|
||||
os.rename('dist', prod)
|
||||
os.system('zip -9 -r -X %s %s' % (fileBin, prod))
|
||||
time.sleep(1.0)
|
||||
os.rename(prod, 'dist')
|
||||
|
||||
os.system(BzrRevert)
|
||||
os.system(GitRevertVersion)
|
||||
|
||||
############################
|
||||
# Check for uncompressed sqlite3.dll
|
||||
@@ -606,5 +657,5 @@ else:
|
||||
# Prepare the TAR.GZ pacakge
|
||||
CreateTar('srcdist', fileSrc, prod)
|
||||
|
||||
os.system(BzrRevert)
|
||||
os.system(GitRevertVersion)
|
||||
|
||||
|
||||
@@ -8,14 +8,14 @@ msgstr ""
|
||||
"Project-Id-Version: SABnzbd-0.6.x\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2011-01-15 19:19+0000\n"
|
||||
"PO-Revision-Date: 2011-01-16 09:57+0000\n"
|
||||
"Last-Translator: Fox Ace <Unknown>\n"
|
||||
"PO-Revision-Date: 2011-08-01 19:14+0000\n"
|
||||
"Last-Translator: shypike <Unknown>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2011-01-17 05:03+0000\n"
|
||||
"X-Generator: Launchpad (build 12177)\n"
|
||||
"X-Launchpad-Export-Date: 2011-08-02 04:50+0000\n"
|
||||
"X-Generator: Launchpad (build 13552)\n"
|
||||
"Language: fr\n"
|
||||
|
||||
#: email/email.tmpl:1
|
||||
@@ -150,14 +150,14 @@ msgstr ""
|
||||
"To: $to\n"
|
||||
"From: $from\n"
|
||||
"Date: $date\n"
|
||||
"Subject: SABnzbd a ajouté $ à la file d'attente\n"
|
||||
"Subject: SABnzbd a ajouté $amount fichier(s) à la file d'attente\n"
|
||||
"X-priority: 5\n"
|
||||
"X-MS-priority: 5\n"
|
||||
"## Après cela vient le contenu, la ligne vide est nécessaire!\n"
|
||||
"\n"
|
||||
"Bonjour,\n"
|
||||
"\n"
|
||||
"SABnzbd a ajouté $ à la file d'attente.\n"
|
||||
"SABnzbd a ajouté $amount fichier(s) à la file d'attente.\n"
|
||||
"Ils proviennent du Flux RSS \"$feed\".\n"
|
||||
"<!--#for $job in $jobs#-->\n"
|
||||
" $job <!--#slurp#-->\n"
|
||||
|
||||
@@ -65,32 +65,32 @@ msgid ""
|
||||
"<!--#end if#-->\n"
|
||||
msgstr ""
|
||||
"##\n"
|
||||
"## Șablon Email Original pentru SABnzbd\n"
|
||||
"## Acesta este un Șablon Cheetah\n"
|
||||
"## Documentație: http://sabnzbd.wikidot.com/email-templates\n"
|
||||
"## sablon Email Original pentru SABnzbd\n"
|
||||
"## Acesta este un sablon Cheetah\n"
|
||||
"## Documentatie: http://sabnzbd.wikidot.com/email-templates\n"
|
||||
"##\n"
|
||||
"##Rândurile noi și caracterele spațiu sunt importante!\n"
|
||||
"##Rândurile noi si caracterele spatiu sunt importante!\n"
|
||||
"##\n"
|
||||
"## Acestea sunt antetele email\n"
|
||||
"To: $to\n"
|
||||
"From: $from\n"
|
||||
"Date: $date\n"
|
||||
"Subject: SABnzbd <!--#if $status then \"a terminat\" else \"nu a reuşit\" #--"
|
||||
"Subject: SABnzbd <!--#if $status then \"a terminat\" else \"nu a reusit\" #--"
|
||||
"> sarcina $name\n"
|
||||
"X-priority: 5\n"
|
||||
"X-MS-priority: 5\n"
|
||||
"## După acesta urmează conţinutul, este necesar o linie goală!\n"
|
||||
"## Dupã acesta urmeazã continutul, este necesar o linie goalã!\n"
|
||||
"\n"
|
||||
"Salut,\n"
|
||||
"<!--#if $status #-->\n"
|
||||
"SABnzbd a descărcat \"$name\" <!--#if $msgid==\"\" then \"\" else \"(newzbin "
|
||||
"SABnzbd a descãrcat \"$name\" <!--#if $msgid==\"\" then \"\" else \"(newzbin "
|
||||
"#\" + $msgid + \")\"#-->\n"
|
||||
"<!--#else#-->\n"
|
||||
"SABnzbd nu a reuşit să descarce \"$name\" <!--#if $msgid==\"\" then \"\" "
|
||||
"SABnzbd nu a reusit sã descarce \"$name\" <!--#if $msgid==\"\" then \"\" "
|
||||
"else \"(newzbin #\" + $msgid + \")\"#-->\n"
|
||||
"<!--#end if#-->\n"
|
||||
"Terminat la $end_time\n"
|
||||
"Mărime $size\n"
|
||||
"Mãrime $size\n"
|
||||
"\n"
|
||||
"Rezultatele sarcinii:\n"
|
||||
"<!--#for $stage in $stages #-->\n"
|
||||
@@ -105,7 +105,7 @@ msgstr ""
|
||||
"$script_output\n"
|
||||
"<!--#end if#-->\n"
|
||||
"<!--#if $status #-->\n"
|
||||
"Bucuraţi-vă!\n"
|
||||
"Bucurati-vã!\n"
|
||||
"<!--#else#-->\n"
|
||||
"Ne pare rau!\n"
|
||||
"<!--#end if#-->\n"
|
||||
@@ -138,24 +138,24 @@ msgid ""
|
||||
"\n"
|
||||
"Bye\n"
|
||||
msgstr ""
|
||||
"## Şablon Email RSS pentru SABnzbd\n"
|
||||
"## Acesta este un şablon Cheetah \n"
|
||||
"## Documentaţie: http://sabnzbd.wikidot.com/email-templates\n"
|
||||
"## Sablon Email RSS pentru SABnzbd\n"
|
||||
"## Acesta este un sablon Cheetah \n"
|
||||
"## Documentatie: http://sabnzbd.wikidot.com/email-templates\n"
|
||||
"##\n"
|
||||
"## Rândurile noi și caracterele spațiu sunt importante!\n"
|
||||
"## Rândurile noi si caracterele spatiu sunt importante!\n"
|
||||
"##\n"
|
||||
"## Acestea sunt antetele email\n"
|
||||
"To: $to\n"
|
||||
"From: $from\n"
|
||||
"Date: $date\n"
|
||||
"Subject: SABnzbd a adăugat $amount sarcini în coadă\n"
|
||||
"Subject: SABnzbd a adãugat $amount sarcini în coadã\n"
|
||||
"X-priority: 5\n"
|
||||
"X-MS-priority: 5\n"
|
||||
"## După acesta urmează conţinutul, este necesar o linie goală!\n"
|
||||
"## Dupã acesta urmeazã continutul, este necesar o linie goalã!\n"
|
||||
"\n"
|
||||
"Salut,\n"
|
||||
"\n"
|
||||
"SABnzbd a adăugat $amount sarcină(e) în coadă.\n"
|
||||
"SABnzbd a adãugat $amount sarcinã(e) în coadã.\n"
|
||||
"Ele sunt din fluxuri RSS \"$feed\".\n"
|
||||
"<!--#for $job in $jobs#-->\n"
|
||||
" $job <!--#slurp#-->\n"
|
||||
|
||||
2554
po/main/SABnzbd.pot
2392
po/main/da.po
2435
po/main/de.po
2424
po/main/fr.po
2211
po/main/nb.po
2432
po/main/nl.po
2298
po/main/ro.px
2218
po/main/sv.po
@@ -13,55 +13,55 @@ msgstr ""
|
||||
"Content-Type: text/plain; charset=ASCII\n"
|
||||
"Content-Transfer-Encoding: 7bit\n"
|
||||
|
||||
#: NSIS_Installer.nsi:347
|
||||
msgid "Start SABnzbd (hidden)"
|
||||
#: NSIS_Installer.nsi:350
|
||||
msgid "Start SABnzbd (hidden)"
|
||||
msgstr ""
|
||||
|
||||
#: NSIS_Installer.nsi:355
|
||||
msgid "Show Release Notes"
|
||||
#: NSIS_Installer.nsi:359
|
||||
msgid "Show Release Notes"
|
||||
msgstr ""
|
||||
|
||||
#: NSIS_Installer.nsi:363
|
||||
msgid "Support the project, Donate!"
|
||||
#: NSIS_Installer.nsi:368
|
||||
msgid "Support the project, Donate!"
|
||||
msgstr ""
|
||||
|
||||
#: NSIS_Installer.nsi:371
|
||||
msgid "Please close \"SABnzbd.exe\" first"
|
||||
#: NSIS_Installer.nsi:377
|
||||
msgid "Please close \"SABnzbd.exe\" first"
|
||||
msgstr ""
|
||||
|
||||
#: NSIS_Installer.nsi:379
|
||||
msgid " >>>> WARNING <<<<\\r\\n\\r\\nPlease, first check the release notes or go to http://wiki.sabnzbd.org/introducing-0-6-0 !"
|
||||
msgstr ""
|
||||
|
||||
#: NSIS_Installer.nsi:387
|
||||
msgid "This will uninstall SABnzbd from your system"
|
||||
#: NSIS_Installer.nsi:386
|
||||
msgid " >>>> WARNING <<<<\\r\\n\\r\\nPlease, first check the release notes or go to http://wiki.sabnzbd.org/introducing-0-6-0 !"
|
||||
msgstr ""
|
||||
|
||||
#: NSIS_Installer.nsi:395
|
||||
msgid "Run at startup"
|
||||
msgid "This will uninstall SABnzbd from your system"
|
||||
msgstr ""
|
||||
|
||||
#: NSIS_Installer.nsi:403
|
||||
msgid "Desktop Icon"
|
||||
#: NSIS_Installer.nsi:404
|
||||
msgid "Run at startup"
|
||||
msgstr ""
|
||||
|
||||
#: NSIS_Installer.nsi:411
|
||||
msgid "NZB File association"
|
||||
#: NSIS_Installer.nsi:413
|
||||
msgid "Desktop Icon"
|
||||
msgstr ""
|
||||
|
||||
#: NSIS_Installer.nsi:419
|
||||
msgid "Delete Program"
|
||||
#: NSIS_Installer.nsi:422
|
||||
msgid "NZB File association"
|
||||
msgstr ""
|
||||
|
||||
#: NSIS_Installer.nsi:427
|
||||
msgid "Delete Settings"
|
||||
#: NSIS_Installer.nsi:431
|
||||
msgid "Delete Program"
|
||||
msgstr ""
|
||||
|
||||
#: NSIS_Installer.nsi:435
|
||||
msgid "Delete Logs"
|
||||
#: NSIS_Installer.nsi:440
|
||||
msgid "Delete Settings"
|
||||
msgstr ""
|
||||
|
||||
#: NSIS_Installer.nsi:443
|
||||
msgid "Delete Cache"
|
||||
#: NSIS_Installer.nsi:449
|
||||
msgid "Delete Logs"
|
||||
msgstr ""
|
||||
|
||||
#: NSIS_Installer.nsi:458
|
||||
msgid "Delete Cache"
|
||||
msgstr ""
|
||||
|
||||
|
||||
@@ -7,34 +7,34 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: SABnzbd-0.6.x\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2011-05-08 19:32+0000\n"
|
||||
"POT-Creation-Date: 2011-08-20 14:21+0000\n"
|
||||
"PO-Revision-Date: 2011-03-11 15:27+0000\n"
|
||||
"Last-Translator: Rene <Unknown>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2011-05-09 04:50+0000\n"
|
||||
"X-Generator: Launchpad (build 12959)\n"
|
||||
"X-Launchpad-Export-Date: 2011-08-21 04:51+0000\n"
|
||||
"X-Generator: Launchpad (build 13697)\n"
|
||||
"Language: da\n"
|
||||
|
||||
#: NSIS_Installer.nsi:347
|
||||
#: NSIS_Installer.nsi:408
|
||||
msgid "Start SABnzbd (hidden)"
|
||||
msgstr "Start SABnzbd"
|
||||
|
||||
#: NSIS_Installer.nsi:355
|
||||
#: NSIS_Installer.nsi:417
|
||||
msgid "Show Release Notes"
|
||||
msgstr "Vis udgivelsesbemærkninger"
|
||||
|
||||
#: NSIS_Installer.nsi:363
|
||||
#: NSIS_Installer.nsi:426
|
||||
msgid "Support the project, Donate!"
|
||||
msgstr "Støtte projektet, donere!"
|
||||
|
||||
#: NSIS_Installer.nsi:371
|
||||
#: NSIS_Installer.nsi:435
|
||||
msgid "Please close \"SABnzbd.exe\" first"
|
||||
msgstr "Luk 'SABnzbd.exe' først"
|
||||
|
||||
#: NSIS_Installer.nsi:379
|
||||
#: NSIS_Installer.nsi:444
|
||||
msgid ""
|
||||
" >>>> WARNING <<<<\\r\\n\\r\\nPlease, first check the "
|
||||
"release notes or go to http://wiki.sabnzbd.org/introducing-0-6-0 !"
|
||||
@@ -42,56 +42,34 @@ msgstr ""
|
||||
" >>>> WARNING <<<<\\r\\n\\r\\nVenligst, kontrollér først "
|
||||
"udgivelsesnoter eller gå til http://wiki.sabnzbd.org/introducing-0-6-0 !"
|
||||
|
||||
#: NSIS_Installer.nsi:387
|
||||
#: NSIS_Installer.nsi:453
|
||||
msgid "This will uninstall SABnzbd from your system"
|
||||
msgstr "Dette vil afinstallere SABnzbd fra dit system"
|
||||
|
||||
#: NSIS_Installer.nsi:395
|
||||
#: NSIS_Installer.nsi:462
|
||||
msgid "Run at startup"
|
||||
msgstr "Kør ved opstart"
|
||||
|
||||
#: NSIS_Installer.nsi:403
|
||||
#: NSIS_Installer.nsi:471
|
||||
msgid "Desktop Icon"
|
||||
msgstr "Skrivebords ikon"
|
||||
|
||||
#: NSIS_Installer.nsi:411
|
||||
#: NSIS_Installer.nsi:480
|
||||
msgid "NZB File association"
|
||||
msgstr "NZB filtilknytning"
|
||||
|
||||
#: NSIS_Installer.nsi:419
|
||||
#: NSIS_Installer.nsi:489
|
||||
msgid "Delete Program"
|
||||
msgstr "Slet program"
|
||||
|
||||
#: NSIS_Installer.nsi:427
|
||||
#: NSIS_Installer.nsi:498
|
||||
msgid "Delete Settings"
|
||||
msgstr "Slet instillinger"
|
||||
|
||||
#: NSIS_Installer.nsi:435
|
||||
#: NSIS_Installer.nsi:507
|
||||
msgid "Delete Logs"
|
||||
msgstr "Slet logs"
|
||||
|
||||
#: NSIS_Installer.nsi:443
|
||||
#: NSIS_Installer.nsi:516
|
||||
msgid "Delete Cache"
|
||||
msgstr "Slet hukommelse"
|
||||
|
||||
#~ msgid ""
|
||||
#~ " >>>> WARNING <<<<\r\n"
|
||||
#~ "\r\n"
|
||||
#~ "If not empty, download your current queue with the old program.\r\n"
|
||||
#~ "The new program will ignore your current queue!"
|
||||
#~ msgstr ""
|
||||
#~ " >>>> ADVARSEL <<<<\r\n"
|
||||
#~ "\r\n"
|
||||
#~ "Hvis ikke tom, skal du downloade din nuværende kø med det gamle program. \r\n"
|
||||
#~ "Det nye program vil ignorere din nuværende kø!"
|
||||
|
||||
#~ msgid ""
|
||||
#~ " >>>> WARNING <<<<\r\n"
|
||||
#~ "\r\n"
|
||||
#~ "Please, first check the release notes or go to "
|
||||
#~ "http://wiki.sabnzbd.org/introducing-0-6-0 !"
|
||||
#~ msgstr ""
|
||||
#~ " >>>> ADVARSEL <<<<\r\n"
|
||||
#~ "\r\n"
|
||||
#~ "Venligst, check først udgivelse notaer eller gå til "
|
||||
#~ "http://wiki.sabnzbd.org/introducing-0-6-0 !"
|
||||
|
||||
@@ -7,34 +7,34 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: SABnzbd-0.6.x\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2011-05-08 19:32+0000\n"
|
||||
"POT-Creation-Date: 2011-08-20 14:21+0000\n"
|
||||
"PO-Revision-Date: 2011-03-12 09:03+0000\n"
|
||||
"Last-Translator: shypike <Unknown>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2011-05-09 04:50+0000\n"
|
||||
"X-Generator: Launchpad (build 12959)\n"
|
||||
"X-Launchpad-Export-Date: 2011-08-21 04:51+0000\n"
|
||||
"X-Generator: Launchpad (build 13697)\n"
|
||||
"Language: de\n"
|
||||
|
||||
#: NSIS_Installer.nsi:347
|
||||
#: NSIS_Installer.nsi:408
|
||||
msgid "Start SABnzbd (hidden)"
|
||||
msgstr "SABnzbd starten (unsichtbar)"
|
||||
|
||||
#: NSIS_Installer.nsi:355
|
||||
#: NSIS_Installer.nsi:417
|
||||
msgid "Show Release Notes"
|
||||
msgstr "Versionshinweise anzeigen"
|
||||
|
||||
#: NSIS_Installer.nsi:363
|
||||
#: NSIS_Installer.nsi:426
|
||||
msgid "Support the project, Donate!"
|
||||
msgstr "Bitte unterstützen Sie das Projekt durch eine Spende!"
|
||||
|
||||
#: NSIS_Installer.nsi:371
|
||||
#: NSIS_Installer.nsi:435
|
||||
msgid "Please close \"SABnzbd.exe\" first"
|
||||
msgstr "Schliessen Sie bitte zuerst \"SABnzbd.exe\"."
|
||||
|
||||
#: NSIS_Installer.nsi:379
|
||||
#: NSIS_Installer.nsi:444
|
||||
msgid ""
|
||||
" >>>> WARNING <<<<\\r\\n\\r\\nPlease, first check the "
|
||||
"release notes or go to http://wiki.sabnzbd.org/introducing-0-6-0 !"
|
||||
@@ -43,56 +43,34 @@ msgstr ""
|
||||
"Versionsanmerkungen lesen oder \"http://wiki.sabnzbd.org/introducing-0-6-0 "
|
||||
"besuchen!\""
|
||||
|
||||
#: NSIS_Installer.nsi:387
|
||||
#: NSIS_Installer.nsi:453
|
||||
msgid "This will uninstall SABnzbd from your system"
|
||||
msgstr "Dies entfernt SABnzbd von Ihrem System"
|
||||
|
||||
#: NSIS_Installer.nsi:395
|
||||
#: NSIS_Installer.nsi:462
|
||||
msgid "Run at startup"
|
||||
msgstr "Beim Systemstart ausführen"
|
||||
|
||||
#: NSIS_Installer.nsi:403
|
||||
#: NSIS_Installer.nsi:471
|
||||
msgid "Desktop Icon"
|
||||
msgstr "Desktop-Symbol"
|
||||
|
||||
#: NSIS_Installer.nsi:411
|
||||
#: NSIS_Installer.nsi:480
|
||||
msgid "NZB File association"
|
||||
msgstr "Mit NZB-Dateien verknüpfen"
|
||||
|
||||
#: NSIS_Installer.nsi:419
|
||||
#: NSIS_Installer.nsi:489
|
||||
msgid "Delete Program"
|
||||
msgstr "Programm löschen"
|
||||
|
||||
#: NSIS_Installer.nsi:427
|
||||
#: NSIS_Installer.nsi:498
|
||||
msgid "Delete Settings"
|
||||
msgstr "Einstellungen löschen"
|
||||
|
||||
#: NSIS_Installer.nsi:435
|
||||
#: NSIS_Installer.nsi:507
|
||||
msgid "Delete Logs"
|
||||
msgstr "Protokoll löschen"
|
||||
|
||||
#: NSIS_Installer.nsi:443
|
||||
#: NSIS_Installer.nsi:516
|
||||
msgid "Delete Cache"
|
||||
msgstr "Cache löschen"
|
||||
|
||||
#~ msgid ""
|
||||
#~ " >>>> WARNING <<<<\r\n"
|
||||
#~ "\r\n"
|
||||
#~ "If not empty, download your current queue with the old program.\r\n"
|
||||
#~ "The new program will ignore your current queue!"
|
||||
#~ msgstr ""
|
||||
#~ " >>>> ACHTUNG <<<<\r\n"
|
||||
#~ "\r\n"
|
||||
#~ "Warten Sie, bis das alte Programm alle Downloads fertiggestellt hat.\r\n"
|
||||
#~ "Das neue Programm wird die noch ausstehenden Downloads ignorieren!"
|
||||
|
||||
#~ msgid ""
|
||||
#~ " >>>> WARNING <<<<\r\n"
|
||||
#~ "\r\n"
|
||||
#~ "Please, first check the release notes or go to "
|
||||
#~ "http://wiki.sabnzbd.org/introducing-0-6-0 !"
|
||||
#~ msgstr ""
|
||||
#~ " >>>> WARNUNG <<<<\r\n"
|
||||
#~ "\r\n"
|
||||
#~ "Bitte zuerst die Versionsanmerkungen lesen oder "
|
||||
#~ "http://wiki.sabnzbd.org/introducing-0-6-0 besuchen!"
|
||||
|
||||
@@ -7,34 +7,34 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: SABnzbd-0.6.x\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2011-05-08 19:32+0000\n"
|
||||
"POT-Creation-Date: 2011-08-20 14:21+0000\n"
|
||||
"PO-Revision-Date: 2011-03-10 21:33+0000\n"
|
||||
"Last-Translator: Fox Ace <Unknown>\n"
|
||||
"Language-Team: FRANCAIS <LL@li.org>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2011-05-09 04:50+0000\n"
|
||||
"X-Generator: Launchpad (build 12959)\n"
|
||||
"X-Launchpad-Export-Date: 2011-08-21 04:51+0000\n"
|
||||
"X-Generator: Launchpad (build 13697)\n"
|
||||
"Language: fr\n"
|
||||
|
||||
#: NSIS_Installer.nsi:347
|
||||
#: NSIS_Installer.nsi:408
|
||||
msgid "Start SABnzbd (hidden)"
|
||||
msgstr "Démarrer SABnzbd (caché)"
|
||||
|
||||
#: NSIS_Installer.nsi:355
|
||||
#: NSIS_Installer.nsi:417
|
||||
msgid "Show Release Notes"
|
||||
msgstr "Afficher les notes de version"
|
||||
|
||||
#: NSIS_Installer.nsi:363
|
||||
#: NSIS_Installer.nsi:426
|
||||
msgid "Support the project, Donate!"
|
||||
msgstr "Supportez le projet, faites un don !"
|
||||
|
||||
#: NSIS_Installer.nsi:371
|
||||
#: NSIS_Installer.nsi:435
|
||||
msgid "Please close \"SABnzbd.exe\" first"
|
||||
msgstr "Quittez \"SABnzbd.exe\" avant l'installation, SVP"
|
||||
|
||||
#: NSIS_Installer.nsi:379
|
||||
#: NSIS_Installer.nsi:444
|
||||
msgid ""
|
||||
" >>>> WARNING <<<<\\r\\n\\r\\nPlease, first check the "
|
||||
"release notes or go to http://wiki.sabnzbd.org/introducing-0-6-0 !"
|
||||
@@ -43,57 +43,34 @@ msgstr ""
|
||||
"vérifiez d'abord les notes de version ou visiter "
|
||||
"http://wiki.sabnzbd.org/introducing-0-6-0 !"
|
||||
|
||||
#: NSIS_Installer.nsi:387
|
||||
#: NSIS_Installer.nsi:453
|
||||
msgid "This will uninstall SABnzbd from your system"
|
||||
msgstr "Ceci désinstallera SABnzbd de votre système"
|
||||
|
||||
#: NSIS_Installer.nsi:395
|
||||
#: NSIS_Installer.nsi:462
|
||||
msgid "Run at startup"
|
||||
msgstr "Lancer au démarrage"
|
||||
|
||||
#: NSIS_Installer.nsi:403
|
||||
#: NSIS_Installer.nsi:471
|
||||
msgid "Desktop Icon"
|
||||
msgstr "Icône sur le Bureau"
|
||||
|
||||
#: NSIS_Installer.nsi:411
|
||||
#: NSIS_Installer.nsi:480
|
||||
msgid "NZB File association"
|
||||
msgstr "Association des fichiers NZB"
|
||||
|
||||
#: NSIS_Installer.nsi:419
|
||||
#: NSIS_Installer.nsi:489
|
||||
msgid "Delete Program"
|
||||
msgstr "Supprimer le programme"
|
||||
|
||||
#: NSIS_Installer.nsi:427
|
||||
#: NSIS_Installer.nsi:498
|
||||
msgid "Delete Settings"
|
||||
msgstr "Supprimer les Paramètres"
|
||||
|
||||
#: NSIS_Installer.nsi:435
|
||||
#: NSIS_Installer.nsi:507
|
||||
msgid "Delete Logs"
|
||||
msgstr "Supprimer les logs"
|
||||
|
||||
#: NSIS_Installer.nsi:443
|
||||
#: NSIS_Installer.nsi:516
|
||||
msgid "Delete Cache"
|
||||
msgstr "Supprimer le Cache"
|
||||
|
||||
#~ msgid ""
|
||||
#~ " >>>> WARNING <<<<\r\n"
|
||||
#~ "\r\n"
|
||||
#~ "If not empty, download your current queue with the old program.\r\n"
|
||||
#~ "The new program will ignore your current queue!"
|
||||
#~ msgstr ""
|
||||
#~ " >>>> ATTENTION <<<<\r\n"
|
||||
#~ "\r\n"
|
||||
#~ "si votre file d'attente de téléchargement n'est pas vide, terminez la avec "
|
||||
#~ "la version précédente du programme.\r\n"
|
||||
#~ "La nouvelle version l'ignorera!"
|
||||
|
||||
#~ msgid ""
|
||||
#~ " >>>> WARNING <<<<\r\n"
|
||||
#~ "\r\n"
|
||||
#~ "Please, first check the release notes or go to "
|
||||
#~ "http://wiki.sabnzbd.org/introducing-0-6-0 !"
|
||||
#~ msgstr ""
|
||||
#~ " >>>>ATTENTION<<<<\r\n"
|
||||
#~ "\r\n"
|
||||
#~ "S'il vous plaît, vérifiez d'abord les notes de version ou aller sur "
|
||||
#~ "http://wiki.sabnzbd.org/introducing-0-6-0 !"
|
||||
|
||||
@@ -7,67 +7,67 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: SABnzbd-0.6.x\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2011-05-08 19:32+0000\n"
|
||||
"POT-Creation-Date: 2011-08-20 14:21+0000\n"
|
||||
"PO-Revision-Date: 2010-10-06 21:37+0000\n"
|
||||
"Last-Translator: shypike@sabnzbd.org\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2011-05-09 04:50+0000\n"
|
||||
"X-Generator: Launchpad (build 12959)\n"
|
||||
"X-Launchpad-Export-Date: 2011-08-21 04:51+0000\n"
|
||||
"X-Generator: Launchpad (build 13697)\n"
|
||||
"Language: no\n"
|
||||
|
||||
#: NSIS_Installer.nsi:347
|
||||
#: NSIS_Installer.nsi:408
|
||||
msgid "Start SABnzbd (hidden)"
|
||||
msgstr ""
|
||||
|
||||
#: NSIS_Installer.nsi:355
|
||||
#: NSIS_Installer.nsi:417
|
||||
msgid "Show Release Notes"
|
||||
msgstr ""
|
||||
|
||||
#: NSIS_Installer.nsi:363
|
||||
#: NSIS_Installer.nsi:426
|
||||
msgid "Support the project, Donate!"
|
||||
msgstr ""
|
||||
|
||||
#: NSIS_Installer.nsi:371
|
||||
#: NSIS_Installer.nsi:435
|
||||
msgid "Please close \"SABnzbd.exe\" first"
|
||||
msgstr ""
|
||||
|
||||
#: NSIS_Installer.nsi:379
|
||||
#: NSIS_Installer.nsi:444
|
||||
msgid ""
|
||||
" >>>> WARNING <<<<\\r\\n\\r\\nPlease, first check the "
|
||||
"release notes or go to http://wiki.sabnzbd.org/introducing-0-6-0 !"
|
||||
msgstr ""
|
||||
|
||||
#: NSIS_Installer.nsi:387
|
||||
#: NSIS_Installer.nsi:453
|
||||
msgid "This will uninstall SABnzbd from your system"
|
||||
msgstr ""
|
||||
|
||||
#: NSIS_Installer.nsi:395
|
||||
#: NSIS_Installer.nsi:462
|
||||
msgid "Run at startup"
|
||||
msgstr ""
|
||||
|
||||
#: NSIS_Installer.nsi:403
|
||||
#: NSIS_Installer.nsi:471
|
||||
msgid "Desktop Icon"
|
||||
msgstr ""
|
||||
|
||||
#: NSIS_Installer.nsi:411
|
||||
#: NSIS_Installer.nsi:480
|
||||
msgid "NZB File association"
|
||||
msgstr ""
|
||||
|
||||
#: NSIS_Installer.nsi:419
|
||||
#: NSIS_Installer.nsi:489
|
||||
msgid "Delete Program"
|
||||
msgstr ""
|
||||
|
||||
#: NSIS_Installer.nsi:427
|
||||
#: NSIS_Installer.nsi:498
|
||||
msgid "Delete Settings"
|
||||
msgstr ""
|
||||
|
||||
#: NSIS_Installer.nsi:435
|
||||
#: NSIS_Installer.nsi:507
|
||||
msgid "Delete Logs"
|
||||
msgstr ""
|
||||
|
||||
#: NSIS_Installer.nsi:443
|
||||
#: NSIS_Installer.nsi:516
|
||||
msgid "Delete Cache"
|
||||
msgstr ""
|
||||
|
||||
@@ -7,34 +7,34 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: SABnzbd-0.6.x\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2011-05-08 19:32+0000\n"
|
||||
"POT-Creation-Date: 2011-08-20 14:21+0000\n"
|
||||
"PO-Revision-Date: 2011-03-10 17:18+0000\n"
|
||||
"Last-Translator: shypike <Unknown>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2011-05-09 04:50+0000\n"
|
||||
"X-Generator: Launchpad (build 12959)\n"
|
||||
"X-Launchpad-Export-Date: 2011-08-21 04:51+0000\n"
|
||||
"X-Generator: Launchpad (build 13697)\n"
|
||||
"Language: nl\n"
|
||||
|
||||
#: NSIS_Installer.nsi:347
|
||||
#: NSIS_Installer.nsi:408
|
||||
msgid "Start SABnzbd (hidden)"
|
||||
msgstr "Start SABnzbd (verborgen)"
|
||||
|
||||
#: NSIS_Installer.nsi:355
|
||||
#: NSIS_Installer.nsi:417
|
||||
msgid "Show Release Notes"
|
||||
msgstr "Toon vrijgave bericht"
|
||||
|
||||
#: NSIS_Installer.nsi:363
|
||||
#: NSIS_Installer.nsi:426
|
||||
msgid "Support the project, Donate!"
|
||||
msgstr "Steun het project, Doneer!"
|
||||
|
||||
#: NSIS_Installer.nsi:371
|
||||
#: NSIS_Installer.nsi:435
|
||||
msgid "Please close \"SABnzbd.exe\" first"
|
||||
msgstr "Sluit \"SABnzbd.exe\" eerst af"
|
||||
|
||||
#: NSIS_Installer.nsi:379
|
||||
#: NSIS_Installer.nsi:444
|
||||
msgid ""
|
||||
" >>>> WARNING <<<<\\r\\n\\r\\nPlease, first check the "
|
||||
"release notes or go to http://wiki.sabnzbd.org/introducing-0-6-0 !"
|
||||
@@ -42,56 +42,34 @@ msgstr ""
|
||||
" >>>> WAARSCHUWING <<<<\\r\\n\\r\\nLees eerst het vrijgave "
|
||||
"bericht of ga naar \"http://wiki.sabnzbd.org/introducing-0-6-0 !\""
|
||||
|
||||
#: NSIS_Installer.nsi:387
|
||||
#: NSIS_Installer.nsi:453
|
||||
msgid "This will uninstall SABnzbd from your system"
|
||||
msgstr "Dit verwijdert SABnzbd van je systeem"
|
||||
|
||||
#: NSIS_Installer.nsi:395
|
||||
#: NSIS_Installer.nsi:462
|
||||
msgid "Run at startup"
|
||||
msgstr "Opstarten bij systeem start"
|
||||
|
||||
#: NSIS_Installer.nsi:403
|
||||
#: NSIS_Installer.nsi:471
|
||||
msgid "Desktop Icon"
|
||||
msgstr "Pictogram op bureaublad"
|
||||
|
||||
#: NSIS_Installer.nsi:411
|
||||
#: NSIS_Installer.nsi:480
|
||||
msgid "NZB File association"
|
||||
msgstr "NZB bestanden koppelen aan SABnzbd"
|
||||
|
||||
#: NSIS_Installer.nsi:419
|
||||
#: NSIS_Installer.nsi:489
|
||||
msgid "Delete Program"
|
||||
msgstr "Verwijder programma"
|
||||
|
||||
#: NSIS_Installer.nsi:427
|
||||
#: NSIS_Installer.nsi:498
|
||||
msgid "Delete Settings"
|
||||
msgstr "Verwijder instellingen"
|
||||
|
||||
#: NSIS_Installer.nsi:435
|
||||
#: NSIS_Installer.nsi:507
|
||||
msgid "Delete Logs"
|
||||
msgstr "Verwijder logging"
|
||||
|
||||
#: NSIS_Installer.nsi:443
|
||||
#: NSIS_Installer.nsi:516
|
||||
msgid "Delete Cache"
|
||||
msgstr "Verwijder Cache"
|
||||
|
||||
#~ msgid ""
|
||||
#~ " >>>> WARNING <<<<\r\n"
|
||||
#~ "\r\n"
|
||||
#~ "If not empty, download your current queue with the old program.\r\n"
|
||||
#~ "The new program will ignore your current queue!"
|
||||
#~ msgstr ""
|
||||
#~ " >>>> WAARSCHUWING <<<<\r\n"
|
||||
#~ "\r\n"
|
||||
#~ "Indien niet leeg, download eerst de gehele huidige wachtrij met het oude "
|
||||
#~ "programma.\r\n"
|
||||
#~ "Het nieuwe programma zal je huidige wachtrij negeren!"
|
||||
|
||||
#~ msgid ""
|
||||
#~ " >>>> WARNING <<<<\r\n"
|
||||
#~ "\r\n"
|
||||
#~ "Please, first check the release notes or go to "
|
||||
#~ "http://wiki.sabnzbd.org/introducing-0-6-0 !"
|
||||
#~ msgstr ""
|
||||
#~ " >>>> WAARSCHUWING <<<<\r\n"
|
||||
#~ "Lees eerst het vrijgave bericht of ga naar "
|
||||
#~ "http://wiki.sabnzbd.org/introducing-0-6-0 !"
|
||||
|
||||
@@ -7,33 +7,33 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: sabnzbd\n"
|
||||
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"POT-Creation-Date: 2011-05-08 19:32+0000\n"
|
||||
"POT-Creation-Date: 2011-08-20 14:21+0000\n"
|
||||
"PO-Revision-Date: 2011-05-07 04:50+0000\n"
|
||||
"Last-Translator: nicusor <Unknown>\n"
|
||||
"Language-Team: Romanian <ro@li.org>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2011-05-09 04:50+0000\n"
|
||||
"X-Generator: Launchpad (build 12959)\n"
|
||||
"X-Launchpad-Export-Date: 2011-08-21 04:51+0000\n"
|
||||
"X-Generator: Launchpad (build 13697)\n"
|
||||
|
||||
#: NSIS_Installer.nsi:347
|
||||
#: NSIS_Installer.nsi:408
|
||||
msgid "Start SABnzbd (hidden)"
|
||||
msgstr "Porneşte SABnzbd (ascuns)"
|
||||
|
||||
#: NSIS_Installer.nsi:355
|
||||
#: NSIS_Installer.nsi:417
|
||||
msgid "Show Release Notes"
|
||||
msgstr "Arată Notele de Publicare"
|
||||
|
||||
#: NSIS_Installer.nsi:363
|
||||
#: NSIS_Installer.nsi:426
|
||||
msgid "Support the project, Donate!"
|
||||
msgstr "Susţine proiectul, Donează!"
|
||||
|
||||
#: NSIS_Installer.nsi:371
|
||||
#: NSIS_Installer.nsi:435
|
||||
msgid "Please close \"SABnzbd.exe\" first"
|
||||
msgstr "Închideţi mai întâi \"SABnzbd.exe\""
|
||||
|
||||
#: NSIS_Installer.nsi:379
|
||||
#: NSIS_Installer.nsi:444
|
||||
msgid ""
|
||||
" >>>> WARNING <<<<\\r\\n\\r\\nPlease, first check the "
|
||||
"release notes or go to http://wiki.sabnzbd.org/introducing-0-6-0 !"
|
||||
@@ -42,34 +42,34 @@ msgstr ""
|
||||
"întâi notele de publicare sau mergeţi la http://wiki.sabnzbd.org/introducing-"
|
||||
"0-6-0 !"
|
||||
|
||||
#: NSIS_Installer.nsi:387
|
||||
#: NSIS_Installer.nsi:453
|
||||
msgid "This will uninstall SABnzbd from your system"
|
||||
msgstr "Acest lucru va dezinstala SABnzbd din sistem"
|
||||
|
||||
#: NSIS_Installer.nsi:395
|
||||
#: NSIS_Installer.nsi:462
|
||||
msgid "Run at startup"
|
||||
msgstr "Executare la pornire"
|
||||
|
||||
#: NSIS_Installer.nsi:403
|
||||
#: NSIS_Installer.nsi:471
|
||||
msgid "Desktop Icon"
|
||||
msgstr "Icoană Desktop"
|
||||
|
||||
#: NSIS_Installer.nsi:411
|
||||
#: NSIS_Installer.nsi:480
|
||||
msgid "NZB File association"
|
||||
msgstr "Asociere cu Fişierele NZB"
|
||||
|
||||
#: NSIS_Installer.nsi:419
|
||||
#: NSIS_Installer.nsi:489
|
||||
msgid "Delete Program"
|
||||
msgstr "Şterge Program"
|
||||
|
||||
#: NSIS_Installer.nsi:427
|
||||
#: NSIS_Installer.nsi:498
|
||||
msgid "Delete Settings"
|
||||
msgstr "Ştergeţi Setări"
|
||||
|
||||
#: NSIS_Installer.nsi:435
|
||||
#: NSIS_Installer.nsi:507
|
||||
msgid "Delete Logs"
|
||||
msgstr "Ştergeţi Activitate"
|
||||
|
||||
#: NSIS_Installer.nsi:443
|
||||
#: NSIS_Installer.nsi:516
|
||||
msgid "Delete Cache"
|
||||
msgstr "Ştergeţi Cache"
|
||||
|
||||
@@ -7,34 +7,34 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: SABnzbd-0.6.x\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2011-05-08 19:32+0000\n"
|
||||
"POT-Creation-Date: 2011-08-20 14:21+0000\n"
|
||||
"PO-Revision-Date: 2011-05-09 12:25+0000\n"
|
||||
"Last-Translator: Jerry Malmström <Unknown>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2011-05-10 05:44+0000\n"
|
||||
"X-Generator: Launchpad (build 12959)\n"
|
||||
"X-Launchpad-Export-Date: 2011-08-21 04:51+0000\n"
|
||||
"X-Generator: Launchpad (build 13697)\n"
|
||||
"Language: sv\n"
|
||||
|
||||
#: NSIS_Installer.nsi:347
|
||||
#: NSIS_Installer.nsi:408
|
||||
msgid "Start SABnzbd (hidden)"
|
||||
msgstr "Starta SABnzbd (dold)"
|
||||
|
||||
#: NSIS_Installer.nsi:355
|
||||
#: NSIS_Installer.nsi:417
|
||||
msgid "Show Release Notes"
|
||||
msgstr "Visa release noteringar"
|
||||
|
||||
#: NSIS_Installer.nsi:363
|
||||
#: NSIS_Installer.nsi:426
|
||||
msgid "Support the project, Donate!"
|
||||
msgstr "Donera och stöd detta projekt!"
|
||||
|
||||
#: NSIS_Installer.nsi:371
|
||||
#: NSIS_Installer.nsi:435
|
||||
msgid "Please close \"SABnzbd.exe\" first"
|
||||
msgstr "Var vänlig stäng \"SABnzbd.exe\" först"
|
||||
|
||||
#: NSIS_Installer.nsi:379
|
||||
#: NSIS_Installer.nsi:444
|
||||
msgid ""
|
||||
" >>>> WARNING <<<<\\r\\n\\r\\nPlease, first check the "
|
||||
"release notes or go to http://wiki.sabnzbd.org/introducing-0-6-0 !"
|
||||
@@ -42,45 +42,34 @@ msgstr ""
|
||||
" >>>> VARNING <<<<\\r\\n\\r\\nVar vänlig och läs versions "
|
||||
"noteringarna eller gå till http://wiki.sabnzbd.org/introducing-0-6-0 !"
|
||||
|
||||
#: NSIS_Installer.nsi:387
|
||||
#: NSIS_Installer.nsi:453
|
||||
msgid "This will uninstall SABnzbd from your system"
|
||||
msgstr "Detta kommer att avinstallera SABnzbd från systemet"
|
||||
|
||||
#: NSIS_Installer.nsi:395
|
||||
#: NSIS_Installer.nsi:462
|
||||
msgid "Run at startup"
|
||||
msgstr "Kör vid uppstart"
|
||||
|
||||
#: NSIS_Installer.nsi:403
|
||||
#: NSIS_Installer.nsi:471
|
||||
msgid "Desktop Icon"
|
||||
msgstr "Skrivbordsikon"
|
||||
|
||||
#: NSIS_Installer.nsi:411
|
||||
#: NSIS_Installer.nsi:480
|
||||
msgid "NZB File association"
|
||||
msgstr "NZB Filassosication"
|
||||
|
||||
#: NSIS_Installer.nsi:419
|
||||
#: NSIS_Installer.nsi:489
|
||||
msgid "Delete Program"
|
||||
msgstr "Ta bort programmet"
|
||||
|
||||
#: NSIS_Installer.nsi:427
|
||||
#: NSIS_Installer.nsi:498
|
||||
msgid "Delete Settings"
|
||||
msgstr "Ta bort inställningar"
|
||||
|
||||
#: NSIS_Installer.nsi:435
|
||||
#: NSIS_Installer.nsi:507
|
||||
msgid "Delete Logs"
|
||||
msgstr "Ta bort logg"
|
||||
|
||||
#: NSIS_Installer.nsi:443
|
||||
#: NSIS_Installer.nsi:516
|
||||
msgid "Delete Cache"
|
||||
msgstr "Ta bort temporär-mapp"
|
||||
|
||||
#~ msgid ""
|
||||
#~ " >>>> WARNING <<<<\r\n"
|
||||
#~ "\r\n"
|
||||
#~ "If not empty, download your current queue with the old program.\r\n"
|
||||
#~ "The new program will ignore your current queue!"
|
||||
#~ msgstr ""
|
||||
#~ " >>>> VARNING <<<<\r\n"
|
||||
#~ "\r\n"
|
||||
#~ "Om kön inte är tom, hämta din nuvarande kö med det gamla programmet.\r\n"
|
||||
#~ "Det nya programmet kommer att ignorera din nuvarande kö!"
|
||||
|
||||
@@ -68,6 +68,7 @@ from sabnzbd.downloader import Downloader
|
||||
from sabnzbd.assembler import Assembler
|
||||
from sabnzbd.newzbin import Bookmarks, MSGIDGrabber
|
||||
import sabnzbd.misc as misc
|
||||
import sabnzbd.powersup as powersup
|
||||
from sabnzbd.dirscanner import DirScanner, ProcessArchiveFile, ProcessSingleFile
|
||||
from sabnzbd.urlgrabber import URLGrabber
|
||||
import sabnzbd.scheduler as scheduler
|
||||
@@ -85,7 +86,7 @@ import sabnzbd.api
|
||||
from sabnzbd.decorators import *
|
||||
from sabnzbd.constants import *
|
||||
|
||||
LINUX_POWER = misc.HAVE_DBUS
|
||||
LINUX_POWER = powersup.HAVE_DBUS
|
||||
|
||||
START = datetime.datetime.now()
|
||||
|
||||
@@ -103,7 +104,6 @@ DIR_PID = None
|
||||
QUEUECOMPLETE = None #stores the nice name of the action
|
||||
QUEUECOMPLETEACTION = None #stores the name of the function to be called
|
||||
QUEUECOMPLETEARG = None #stores an extra arguments that need to be passed
|
||||
QUEUECOMPLETEACTION_GO = False # Booleen value whether to run an action or not at the queue end.
|
||||
|
||||
DAEMON = None
|
||||
|
||||
@@ -115,6 +115,7 @@ LOG_ALL = False
|
||||
AMBI_LOCALHOST = False
|
||||
WIN_SERVICE = None # Instance of our Win32 Service Class
|
||||
BROWSER_URL = None
|
||||
CMDLINE = '' # Rendering of original command line arguments
|
||||
|
||||
WEB_DIR = None
|
||||
WEB_DIR2 = None
|
||||
@@ -249,12 +250,12 @@ def initialize(pause_downloader = False, clean_up = False, evalSched=False, repa
|
||||
pause_downloader = True
|
||||
else:
|
||||
# Check crash detection file
|
||||
if load_admin(TERM_FLAG_FILE, remove=True):
|
||||
#if load_admin(TERM_FLAG_FILE, remove=True):
|
||||
# Repair mode 2 is a bit over an over-reaction!
|
||||
pass # repair = 2
|
||||
pass # repair = 2
|
||||
|
||||
# Set crash detection file
|
||||
save_admin(1, TERM_FLAG_FILE)
|
||||
#save_admin(1, TERM_FLAG_FILE)
|
||||
|
||||
###
|
||||
### Initialize threads
|
||||
@@ -369,7 +370,11 @@ def halt():
|
||||
pass
|
||||
|
||||
## Save State ##
|
||||
save_state(flag=True)
|
||||
try:
|
||||
save_state(flag=True)
|
||||
except:
|
||||
logging.error('Fatal error at saving state', exc_info=True)
|
||||
|
||||
|
||||
# The Scheduler cannot be stopped when the stop was scheduled.
|
||||
# Since all warm-restarts have been removed, it's not longer
|
||||
@@ -453,9 +458,9 @@ def save_state(flag=False):
|
||||
Bookmarks.do.save()
|
||||
DirScanner.do.save()
|
||||
PostProcessor.do.save()
|
||||
if flag:
|
||||
# Remove crash detector
|
||||
load_admin(TERM_FLAG_FILE, remove=True)
|
||||
#if flag:
|
||||
# # Remove crash detector
|
||||
# load_admin(TERM_FLAG_FILE, remove=True)
|
||||
|
||||
def pause_all():
|
||||
""" Pause all activities than cause disk access
|
||||
@@ -608,33 +613,33 @@ def system_shutdown():
|
||||
time.sleep(1.0)
|
||||
|
||||
if sabnzbd.WIN32:
|
||||
misc.win_shutdown()
|
||||
powersup.win_shutdown()
|
||||
elif DARWIN:
|
||||
misc.osx_shutdown()
|
||||
powersup.osx_shutdown()
|
||||
else:
|
||||
misc.linux_shutdown()
|
||||
powersup.linux_shutdown()
|
||||
|
||||
|
||||
def system_hibernate():
|
||||
""" Hibernate system """
|
||||
logging.info("Performing system hybernation")
|
||||
if sabnzbd.WIN32:
|
||||
misc.win_hibernate()
|
||||
powersup.win_hibernate()
|
||||
elif DARWIN:
|
||||
misc.osx_hibernate()
|
||||
powersup.osx_hibernate()
|
||||
else:
|
||||
misc.linux_hibernate()
|
||||
powersup.linux_hibernate()
|
||||
|
||||
|
||||
def system_standby():
|
||||
""" Standby system """
|
||||
logging.info("Performing system standby")
|
||||
if sabnzbd.WIN32:
|
||||
misc.win_standby()
|
||||
powersup.win_standby()
|
||||
elif DARWIN:
|
||||
misc.osx_standby()
|
||||
powersup.osx_standby()
|
||||
else:
|
||||
misc.linux_standby()
|
||||
powersup.linux_standby()
|
||||
|
||||
|
||||
def shutdown_program():
|
||||
@@ -767,11 +772,16 @@ def save_data(data, _id, path, do_pickle = True, silent=False):
|
||||
try:
|
||||
_f = open(path, 'wb')
|
||||
if do_pickle:
|
||||
cPickle.dump(data, _f, 2)
|
||||
pickler = cPickle.Pickler(_f, 2)
|
||||
pickler.dump(data)
|
||||
_f.flush()
|
||||
_f.close()
|
||||
pickler.clear_memo()
|
||||
del pickler
|
||||
else:
|
||||
_f.write(data)
|
||||
_f.flush()
|
||||
_f.close()
|
||||
_f.flush()
|
||||
_f.close()
|
||||
except:
|
||||
logging.error(Ta('Saving %s failed'), path)
|
||||
logging.info("Traceback: ", exc_info = True)
|
||||
@@ -828,13 +838,18 @@ def save_admin(data, _id, do_pickle=True):
|
||||
logging.info("Saving data for %s in %s", _id, path)
|
||||
|
||||
try:
|
||||
f = open(path, 'wb')
|
||||
_f = open(path, 'wb')
|
||||
if do_pickle:
|
||||
cPickle.dump(data, f, 2)
|
||||
pickler = cPickle.Pickler(_f, 2)
|
||||
pickler.dump(data)
|
||||
_f.flush()
|
||||
_f.close()
|
||||
pickler.clear_memo()
|
||||
del pickler
|
||||
else:
|
||||
f.write(data)
|
||||
f.flush()
|
||||
f.close()
|
||||
_f.write(data)
|
||||
_f.flush()
|
||||
_f.close()
|
||||
except:
|
||||
logging.error(Ta('Saving %s failed'), path)
|
||||
logging.info("Traceback: ", exc_info = True)
|
||||
|
||||
@@ -45,7 +45,7 @@ from sabnzbd.utils.rsslib import RSS, Item
|
||||
from sabnzbd.utils.json import JsonWriter
|
||||
from sabnzbd.utils.pathbrowser import folders_at_path
|
||||
from sabnzbd.misc import loadavg, to_units, diskfree, disktotal, get_ext, \
|
||||
get_filename, int_conv, globber, time_format
|
||||
get_filename, int_conv, globber, time_format, remove_all
|
||||
from sabnzbd.encoding import xml_name, unicoder, special_fixer, platform_encode
|
||||
from sabnzbd.postproc import PostProcessor
|
||||
from sabnzbd.articlecache import ArticleCache
|
||||
@@ -70,6 +70,13 @@ _MSG_NO_SUCH_CONFIG = 'Config item does not exist'
|
||||
_MSG_BAD_SERVER_PARMS = 'Incorrect server settings'
|
||||
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# For Windows: determine executable extensions
|
||||
if os.name == 'nt':
|
||||
PATHEXT = os.environ.get('PATHEXT', '').lower().split(';')
|
||||
else:
|
||||
PATHEXT = []
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
def api_handler(kwargs):
|
||||
""" API Dispatcher
|
||||
@@ -393,15 +400,17 @@ def _api_history(name, output, kwargs):
|
||||
|
||||
if name == 'delete':
|
||||
special = value.lower()
|
||||
del_files = bool(int_conv(kwargs.get('del_files')))
|
||||
if special in ('all', 'failed', 'completed'):
|
||||
history_db = cherrypy.thread_data.history_db
|
||||
if value in ('all', 'failed'):
|
||||
if special in ('all', 'failed'):
|
||||
if del_files:
|
||||
del_job_files(history_db.get_failed_paths())
|
||||
history_db.remove_failed()
|
||||
if value in ('all', 'completed'):
|
||||
if special in ('all', 'completed'):
|
||||
history_db.remove_completed()
|
||||
return report(output)
|
||||
elif value:
|
||||
del_files = bool(int_conv(kwargs.get('del_files')))
|
||||
jobs = value.split(',')
|
||||
for job in jobs:
|
||||
del_hist_job(job, del_files)
|
||||
@@ -1031,6 +1040,8 @@ def build_queue(web_dir=None, root=None, verbose=False, prim=True, verbose_list=
|
||||
slot['status'] = "%s" % (status)
|
||||
if priority == TOP_PRIORITY:
|
||||
slot['priority'] = 'Force'
|
||||
elif priority == REPAIR_PRIORITY:
|
||||
slot['priority'] = 'Repair'
|
||||
elif priority == HIGH_PRIORITY:
|
||||
slot['priority'] = 'High'
|
||||
elif priority == LOW_PRIORITY:
|
||||
@@ -1367,17 +1378,29 @@ def retry_job(job, new_nzb):
|
||||
return False
|
||||
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
def del_job_files(job_paths):
|
||||
""" Remove files of each path in the list """
|
||||
for path in job_paths:
|
||||
if path and path.lower().startswith(cfg.download_dir.get_path().lower()):
|
||||
remove_all(path, recursive=True)
|
||||
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
def del_hist_job(job, del_files):
|
||||
""" Remove history element """
|
||||
if job:
|
||||
history_db = cherrypy.thread_data.history_db
|
||||
path = history_db.get_path(job)
|
||||
PostProcessor.do.delete(job, del_files=del_files)
|
||||
history_db.remove_history(job)
|
||||
path = PostProcessor.do.get_path(job)
|
||||
if path:
|
||||
PostProcessor.do.delete(job, del_files=del_files)
|
||||
else:
|
||||
history_db = cherrypy.thread_data.history_db
|
||||
path = history_db.get_path(job)
|
||||
PostProcessor.do.delete(job, del_files=del_files)
|
||||
history_db.remove_history(job)
|
||||
|
||||
if path and del_files and path.lower().startswith(cfg.download_dir.get_path().lower()):
|
||||
nzbstuff.clean_folder(os.path.join(path, JOB_ADMIN))
|
||||
nzbstuff.clean_folder(path)
|
||||
remove_all(path, recursive=True)
|
||||
return True
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
@@ -1393,7 +1416,7 @@ def Tspec(txt):
|
||||
_SKIN_CACHE = {} # Stores pre-translated acronyms
|
||||
|
||||
# This special is to be used in interface.py for template processing
|
||||
# to be paased for the $T function: so { ..., 'T' : Ttemplate, ...}
|
||||
# to be passed for the $T function: so { ..., 'T' : Ttemplate, ...}
|
||||
def Ttemplate(txt):
|
||||
""" Translation function for Skin texts
|
||||
"""
|
||||
@@ -1506,10 +1529,6 @@ def build_header(prim):
|
||||
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
def get_history_size():
|
||||
history_db = cherrypy.thread_data.history_db
|
||||
bytes, month, week = history_db.get_history_size()
|
||||
return (format_bytes(bytes), format_bytes(month), format_bytes(week))
|
||||
|
||||
def build_history(start=None, limit=None, verbose=False, verbose_list=None, search=None, failed_only=0):
|
||||
|
||||
@@ -1756,7 +1775,8 @@ def list_scripts(default=False):
|
||||
if path and os.access(path, os.R_OK):
|
||||
for script in globber(path):
|
||||
if os.path.isfile(script):
|
||||
if (sabnzbd.WIN32 and not (win32api.GetFileAttributes(script) & win32file.FILE_ATTRIBUTE_HIDDEN)) or \
|
||||
if (sabnzbd.WIN32 and os.path.splitext(script)[1].lower() in PATHEXT and \
|
||||
not (win32api.GetFileAttributes(script) & win32file.FILE_ATTRIBUTE_HIDDEN)) or \
|
||||
(not sabnzbd.WIN32 and os.access(script, os.X_OK) and not os.path.basename(script).startswith('.')):
|
||||
lst.append(os.path.basename(script))
|
||||
lst.insert(0, 'None')
|
||||
|
||||
@@ -91,11 +91,13 @@ class Assembler(Thread):
|
||||
logging.error(Ta('Disk full! Forcing Pause'))
|
||||
else:
|
||||
logging.error(Ta('Disk error on creating file %s'), latin1(filepath))
|
||||
sabnzbd.downloader.pause_downloader()
|
||||
# Pause without saving
|
||||
sabnzbd.downloader.Downloader.do.pause(save=False)
|
||||
except:
|
||||
logging.error('Fatal error in Assembler', exc_info = True)
|
||||
break
|
||||
|
||||
nzf.remove_admin()
|
||||
setname = nzf.setname
|
||||
if nzf.is_par2 and (nzo.md5packs.get(setname) is None):
|
||||
pack = GetMD5Hashes(filepath)
|
||||
|
||||
@@ -35,8 +35,8 @@ from sabnzbd.config import OptionBool, OptionNumber, OptionPassword, \
|
||||
#
|
||||
RE_VAL = re.compile('[^@ ]+@[^.@ ]+\.[^.@ ]')
|
||||
def validate_email(value):
|
||||
global email_endjob, email_full
|
||||
if email_endjob() or email_full():
|
||||
global email_endjob, email_full, email_rss
|
||||
if email_endjob() or email_full() or email_rss():
|
||||
if isinstance(value, list):
|
||||
values = value
|
||||
else:
|
||||
@@ -49,8 +49,8 @@ def validate_email(value):
|
||||
|
||||
def validate_server(value):
|
||||
""" Check if server non-empty"""
|
||||
global email_endjob, email_full
|
||||
if value == '' and (email_endjob() or email_full()):
|
||||
global email_endjob, email_full, email_rss
|
||||
if value == '' and (email_endjob() or email_full() or email_rss()):
|
||||
return T('Server address required'), None
|
||||
else:
|
||||
return None, value
|
||||
@@ -97,6 +97,7 @@ nice = OptionStr('misc', 'nice', '', validation=no_nonsense)
|
||||
ionice = OptionStr('misc', 'ionice', '', validation=no_nonsense)
|
||||
ignore_wrong_unrar = OptionBool('misc', 'ignore_wrong_unrar', False)
|
||||
par2_multicore = OptionBool('misc', 'par2_multicore', True)
|
||||
allow_64bit_tools = OptionBool('misc', 'allow_64bit_tools', True)
|
||||
allow_streaming = OptionBool('misc', 'allow_streaming', False)
|
||||
|
||||
newzbin_username = OptionStr('newzbin', 'username')
|
||||
@@ -105,7 +106,7 @@ newzbin_bookmarks = OptionBool('newzbin', 'bookmarks', False)
|
||||
newzbin_unbookmark = OptionBool('newzbin', 'unbookmark', True)
|
||||
bookmark_rate = OptionNumber('newzbin', 'bookmark_rate', 60, minval=15, maxval=24*60)
|
||||
|
||||
top_only = OptionBool('misc', 'top_only', True)
|
||||
top_only = OptionBool('misc', 'top_only', False)
|
||||
autodisconnect = OptionBool('misc', 'auto_disconnect', True)
|
||||
queue_complete = OptionStr('misc', 'queue_complete')
|
||||
queue_complete_pers = OptionBool('misc', 'queue_complete_pers', False)
|
||||
|
||||
@@ -186,30 +186,26 @@ class OptionDir(Option):
|
||||
""" Set new root, is assumed to be valid """
|
||||
self.__root = root
|
||||
|
||||
def set(self, value):
|
||||
def set(self, value, create=False):
|
||||
""" Set new dir value, validate and create if needed
|
||||
Return None when directory is accepted
|
||||
Return error-string when not accepted, value will not be changed
|
||||
'create' means try to create (but don't set permanent create flag)
|
||||
"""
|
||||
error = None
|
||||
if value != None and value != self.get():
|
||||
if value != None and (create or value != self.get()):
|
||||
value = value.strip()
|
||||
if self.__validation:
|
||||
error, value = self.__validation(self.__root, value, self._Option__default_val)
|
||||
if not error:
|
||||
if value and self.__create:
|
||||
if value and (self.__create or create):
|
||||
res, path = sabnzbd.misc.create_real_path(self.ident()[1], self.__root, value, self.__apply_umask)
|
||||
if not res:
|
||||
error = "Cannot create %s folder %s" % (self.ident()[1], path)
|
||||
error = Ta("Cannot create %s folder %s") % (self.ident()[1], path)
|
||||
if not error:
|
||||
self._Option__set(value)
|
||||
return error
|
||||
|
||||
def set_create(self):
|
||||
""" Enable auto-creation and create now """
|
||||
self.__create = True
|
||||
self.get_path()
|
||||
|
||||
|
||||
class OptionList(Option):
|
||||
""" List option class """
|
||||
@@ -318,6 +314,8 @@ def delete_from_database(section, keyword):
|
||||
""" Remove section/keyword from INI database """
|
||||
global database, CFG, modified
|
||||
del database[section][keyword]
|
||||
if section == 'servers' and '[' in keyword:
|
||||
keyword = keyword.replace('[', '{').replace(']', '}')
|
||||
try:
|
||||
del CFG[section][keyword]
|
||||
except KeyError:
|
||||
|
||||
@@ -104,6 +104,7 @@ MIN_DECODE_QUEUE = 5
|
||||
MAX_DECODE_QUEUE = 10
|
||||
MAX_WARNINGS = 20
|
||||
|
||||
REPAIR_PRIORITY = 3
|
||||
TOP_PRIORITY = 2
|
||||
HIGH_PRIORITY = 1
|
||||
NORMAL_PRIORITY = 0
|
||||
|
||||
@@ -143,6 +143,14 @@ class HistoryDB(object):
|
||||
def remove_completed(self):
|
||||
return self.execute("""DELETE FROM history WHERE status = 'Completed'""", save=True)
|
||||
|
||||
def get_failed_paths(self):
|
||||
""" Return list of all storage paths of failed jobs (may contain non-existing or empty paths) """
|
||||
fetch_ok = self.execute("""SELECT path FROM history WHERE status = 'Failed'""")
|
||||
if fetch_ok:
|
||||
return [item.get('path') for item in self.c.fetchall()]
|
||||
else:
|
||||
return []
|
||||
|
||||
def remove_failed(self):
|
||||
return self.execute("""DELETE FROM history WHERE status = 'Failed'""", save=True)
|
||||
|
||||
|
||||
@@ -759,7 +759,7 @@ def clues_login(text):
|
||||
""" Check for any "failed login" clues in the response code
|
||||
"""
|
||||
text = text.lower()
|
||||
for clue in ('username', 'password', 'invalid', 'authen'):
|
||||
for clue in ('username', 'password', 'invalid', 'authen', 'access denied'):
|
||||
if clue in text:
|
||||
return True
|
||||
return False
|
||||
|
||||
@@ -33,6 +33,9 @@ from sabnzbd.misc import to_units, split_host, time_format
|
||||
from sabnzbd.encoding import EmailFilter, latin1
|
||||
import sabnzbd.cfg as cfg
|
||||
|
||||
def errormsg(msg):
|
||||
logging.error(latin1(msg))
|
||||
return msg
|
||||
|
||||
################################################################################
|
||||
# EMAIL_SEND
|
||||
@@ -41,9 +44,6 @@ import sabnzbd.cfg as cfg
|
||||
################################################################################
|
||||
def send(message, recipient):
|
||||
""" Send message if message non-empty and email-parms are set """
|
||||
def errormsg(msg):
|
||||
logging.error(latin1(msg))
|
||||
return msg
|
||||
|
||||
if not message.strip('\n\r\t '):
|
||||
return "Skipped empty message"
|
||||
@@ -99,7 +99,7 @@ def send(message, recipient):
|
||||
return errormsg(T('Failed to authenticate to mail server'))
|
||||
|
||||
try:
|
||||
mailconn.sendmail(cfg.email_from(), cfg.email_to(), message)
|
||||
mailconn.sendmail(cfg.email_from(), recipient, message)
|
||||
msg = None
|
||||
except smtplib.SMTPHeloError:
|
||||
msg = errormsg('The server didn\'t reply properly to the helo greeting.')
|
||||
@@ -160,22 +160,30 @@ def send_with_template(prefix, parm):
|
||||
else:
|
||||
lst = [os.path.join(path, '%s-en.tmpl' % prefix)]
|
||||
|
||||
ret = T('No email templates found')
|
||||
sent = False
|
||||
for temp in lst:
|
||||
if os.access(temp, os.R_OK):
|
||||
source = _decode_file(temp)
|
||||
if source:
|
||||
for recipient in cfg.email_to():
|
||||
parm['to'] = recipient
|
||||
message = Template(source=source,
|
||||
searchList=[parm],
|
||||
filter=EmailFilter,
|
||||
compilerSettings={'directiveStartToken': '<!--#',
|
||||
'directiveEndToken': '#-->'})
|
||||
ret = send(message.respond(), recipient)
|
||||
del message
|
||||
sent = True
|
||||
if len(cfg.email_to()):
|
||||
for recipient in cfg.email_to():
|
||||
parm['to'] = recipient
|
||||
message = Template(source=source,
|
||||
searchList=[parm],
|
||||
filter=EmailFilter,
|
||||
compilerSettings={'directiveStartToken': '<!--#',
|
||||
'directiveEndToken': '#-->'})
|
||||
ret = send(message.respond(), recipient)
|
||||
del message
|
||||
else:
|
||||
ret = T('No recipients given, no email sent')
|
||||
else:
|
||||
ret = T('Invalid encoding of email template %s') % temp
|
||||
errormsg(ret)
|
||||
if not sent:
|
||||
ret = T('No email templates found')
|
||||
errormsg(ret)
|
||||
return ret
|
||||
|
||||
|
||||
|
||||
@@ -36,7 +36,8 @@ from Cheetah.Template import Template
|
||||
import sabnzbd.emailer as emailer
|
||||
from sabnzbd.misc import real_path, to_units, \
|
||||
diskfree, sanitize_foldername, time_format, HAVE_AMPM, \
|
||||
cat_to_opts, int_conv, panic_old_queue, globber, clean_folder
|
||||
cat_to_opts, int_conv, globber, remove_all
|
||||
from sabnzbd.panic import panic_old_queue
|
||||
from sabnzbd.newswrapper import GetServerParms
|
||||
from sabnzbd.newzbin import Bookmarks
|
||||
from sabnzbd.bpsmeter import BPSMeter
|
||||
@@ -56,7 +57,7 @@ from sabnzbd.lang import list_languages, set_language
|
||||
|
||||
from sabnzbd.api import list_scripts, list_cats, del_from_section, \
|
||||
api_handler, build_queue, rss_qstatus, \
|
||||
retry_job, build_header, build_history, \
|
||||
retry_job, build_header, build_history, del_job_files, \
|
||||
format_bytes, calc_age, std_time, report, del_hist_job, Ttemplate
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
@@ -913,7 +914,10 @@ class HistoryPage(object):
|
||||
def purge_failed(self, **kwargs):
|
||||
msg = check_session(kwargs)
|
||||
if msg: return msg
|
||||
del_files = bool(int_conv(kwargs.get('del_files')))
|
||||
history_db = cherrypy.thread_data.history_db
|
||||
if del_files:
|
||||
del_job_files(history_db.get_failed_paths())
|
||||
history_db.remove_failed()
|
||||
raise queueRaiser(self.__root, kwargs)
|
||||
|
||||
@@ -1056,8 +1060,7 @@ def orphan_delete(kwargs):
|
||||
path = kwargs.get('name')
|
||||
if path:
|
||||
path = os.path.join(cfg.download_dir.get_path(), path)
|
||||
clean_folder(os.path.join(path, JOB_ADMIN))
|
||||
clean_folder(path)
|
||||
remove_all(path, recursive=True)
|
||||
|
||||
def orphan_add(kwargs):
|
||||
path = kwargs.get('name')
|
||||
@@ -1104,12 +1107,14 @@ class ConfigDirectories(object):
|
||||
msg = check_session(kwargs)
|
||||
if msg: return msg
|
||||
|
||||
cfg.complete_dir.set_create()
|
||||
for kw in LIST_DIRPAGE:
|
||||
value = kwargs.get(kw)
|
||||
if value != None:
|
||||
value = platform_encode(value)
|
||||
msg = config.get_config('misc', kw).set(value)
|
||||
if kw == 'complete_dir':
|
||||
msg = config.get_config('misc', kw).set(value, create=True)
|
||||
else:
|
||||
msg = config.get_config('misc', kw).set(value)
|
||||
if msg:
|
||||
return badParameterResponse(msg)
|
||||
|
||||
@@ -1560,6 +1565,8 @@ class ConfigRss(object):
|
||||
self.__refresh_ignore = False
|
||||
msg = sabnzbd.rss.run_feed(active_feed, download=self.__refresh_download, force=self.__refresh_force, \
|
||||
ignoreFirst=self.__refresh_ignore, readout=readout)
|
||||
if readout:
|
||||
sabnzbd.rss.save()
|
||||
self.__refresh_readout = None
|
||||
conf['error'] = msg
|
||||
|
||||
@@ -1681,6 +1688,7 @@ class ConfigRss(object):
|
||||
kwargs['section'] = 'rss'
|
||||
kwargs['keyword'] = kwargs.get('feed')
|
||||
del_from_section(kwargs)
|
||||
sabnzbd.rss.clear_feed(kwargs.get('feed'))
|
||||
raise dcRaiser(self.__root, kwargs)
|
||||
|
||||
@cherrypy.expose
|
||||
@@ -2038,7 +2046,10 @@ class ConfigCats(object):
|
||||
name = newname.lower()
|
||||
if kwargs.get('dir'):
|
||||
kwargs['dir'] = platform_encode(kwargs['dir'])
|
||||
config.ConfigCat(name, kwargs)
|
||||
folder = config.ConfigCat(name, kwargs).dir
|
||||
msg = folder.set(folder(), create=True)
|
||||
if msg:
|
||||
return badParameterResponse(msg)
|
||||
|
||||
config.save_config()
|
||||
raise dcRaiser(self.__root, kwargs)
|
||||
@@ -2336,15 +2347,15 @@ def ShowOK(url):
|
||||
def GetRssLog(feed):
|
||||
def make_item(job):
|
||||
url = job.get('url', '')
|
||||
title = job.get('title', '')
|
||||
title = xml_name(job.get('title', ''))
|
||||
if url.isdigit():
|
||||
title = '<a href="https://www.newzbin.com/browse/post/%s/" target="_blank">%s</a>' % (url, title)
|
||||
else:
|
||||
title = xml_name(title)
|
||||
title = title
|
||||
if sabnzbd.rss.special_rss_site(url):
|
||||
nzbname = ""
|
||||
else:
|
||||
nzbname = sanitize_foldername(xml_name(title))
|
||||
nzbname = xml_name(sanitize_foldername(job.get('title', '')))
|
||||
return url, \
|
||||
title, \
|
||||
'*' * int(job.get('status', '').endswith('*')), \
|
||||
|
||||
564
sabnzbd/misc.py
@@ -24,8 +24,6 @@ import sys
|
||||
import logging
|
||||
import urllib
|
||||
import re
|
||||
import webbrowser
|
||||
import tempfile
|
||||
import shutil
|
||||
import threading
|
||||
import subprocess
|
||||
@@ -40,23 +38,10 @@ import sabnzbd.config as config
|
||||
import sabnzbd.cfg as cfg
|
||||
from sabnzbd.encoding import unicoder, latin1
|
||||
|
||||
if sabnzbd.FOUNDATION:
|
||||
import Foundation
|
||||
|
||||
RE_VERSION = re.compile('(\d+)\.(\d+)\.(\d+)([a-zA-Z]*)(\d*)')
|
||||
RE_UNITS = re.compile('(\d+\.*\d*)\s*([KMGTP]{0,1})', re.I)
|
||||
TAB_UNITS = ('', 'K', 'M', 'G', 'T', 'P')
|
||||
|
||||
PANIC_NONE = 0
|
||||
PANIC_PORT = 1
|
||||
PANIC_TEMPL = 2
|
||||
PANIC_QUEUE = 3
|
||||
PANIC_FWALL = 4
|
||||
PANIC_OTHER = 5
|
||||
PANIC_XPORT = 6
|
||||
PANIC_SQLITE = 7
|
||||
PANIC_HOST = 8
|
||||
|
||||
# Check if strings are defined for AM and PM
|
||||
HAVE_AMPM = bool(time.strftime('%p', time.localtime()))
|
||||
|
||||
@@ -227,7 +212,7 @@ def sanitize_filename(name):
|
||||
return name + ext
|
||||
|
||||
FL_ILLEGAL = CH_ILLEGAL + ':\x92"'
|
||||
FL_LEGAL = CH_LEGAL + ";''"
|
||||
FL_LEGAL = CH_LEGAL + "-''"
|
||||
uFL_ILLEGAL = FL_ILLEGAL.decode('latin-1')
|
||||
uFL_LEGAL = FL_LEGAL.decode('latin-1')
|
||||
|
||||
@@ -482,237 +467,6 @@ def set_serv_parms(service, args):
|
||||
|
||||
|
||||
|
||||
################################################################################
|
||||
# Launch a browser for various purposes
|
||||
# including panic messages
|
||||
#
|
||||
################################################################################
|
||||
def MSG_BAD_NEWS():
|
||||
return r'''
|
||||
<html>
|
||||
<head>
|
||||
<title>''' + Ta('Problem with') + ''' %s %s</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1><font color="#0000FF"> %s %s</font></h1>
|
||||
<p align="center"> </p>
|
||||
<p align="center"><font size="5">
|
||||
<blockquote>
|
||||
%s
|
||||
</blockquote>
|
||||
<br>%s<br>
|
||||
</body>
|
||||
</html>
|
||||
'''
|
||||
|
||||
def MSG_BAD_FWALL():
|
||||
return Ta(r'''
|
||||
SABnzbd is not compatible with some software firewalls.<br>
|
||||
%s<br>
|
||||
Sorry, but we cannot solve this incompatibility right now.<br>
|
||||
Please file a complaint at your firewall supplier.<br>
|
||||
<br>
|
||||
''')
|
||||
|
||||
def MSG_BAD_PORT():
|
||||
return Ta(r'''
|
||||
SABnzbd needs a free tcp/ip port for its internal web server.<br>
|
||||
Port %s on %s was tried , but it is not available.<br>
|
||||
Some other software uses the port or SABnzbd is already running.<br>
|
||||
<br>
|
||||
Please restart SABnzbd with a different port number.''') + \
|
||||
'''<br>
|
||||
<br>
|
||||
%s<br>
|
||||
%s --server %s:%s<br>
|
||||
<br>''' + \
|
||||
Ta(r'If you get this error message again, please try a different number.<br>')
|
||||
|
||||
def MSG_ILL_PORT():
|
||||
return Ta(r'''
|
||||
SABnzbd needs a free tcp/ip port for its internal web server.<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>
|
||||
%s<br>
|
||||
%s --server %s:%s<br>
|
||||
<br>''' + \
|
||||
Ta(r'If you get this error message again, please try a different number.<br>')
|
||||
|
||||
def MSG_BAD_HOST():
|
||||
return Ta(r'''
|
||||
SABnzbd needs a valid host address for its internal web server.<br>
|
||||
You have specified an invalid address.<br>
|
||||
Safe values are <b>localhost</b> and <b>0.0.0.0</b><br>
|
||||
<br>
|
||||
Please restart SABnzbd with a proper host address.''') + \
|
||||
'''<br>
|
||||
<br>
|
||||
%s<br>
|
||||
%s --server %s:%s<br>
|
||||
<br>
|
||||
'''
|
||||
|
||||
def MSG_BAD_QUEUE():
|
||||
return Ta(r'''
|
||||
SABnzbd detected saved data from an other SABnzbd version<br>
|
||||
but cannot re-use the data of the other program.<br><br>
|
||||
You may want to finish your queue first with the other program.<br><br>
|
||||
After that, start this program with the "--clean" option.<br>
|
||||
This will erase the current queue and history!<br>
|
||||
SABnzbd read the file "%s".''') + \
|
||||
'''<br>
|
||||
<br>
|
||||
%s<br>
|
||||
%s --clean<br>
|
||||
<br>
|
||||
'''
|
||||
|
||||
def MSG_BAD_TEMPL():
|
||||
return Ta(r'''
|
||||
SABnzbd cannot find its web interface files in %s.<br>
|
||||
Please install the program again.<br>
|
||||
<br>
|
||||
''')
|
||||
|
||||
def MSG_OTHER():
|
||||
return Ta('SABnzbd detected a fatal error:') + '<br>%s<br><br>%s<br>'
|
||||
|
||||
def MSG_OLD_QUEUE():
|
||||
return Ta(r'''
|
||||
SABnzbd detected a Queue and History from an older (0.4.x) release.<br><br>
|
||||
Both queue and history will be ignored and may get lost!<br><br>
|
||||
You may choose to stop SABnzbd and finish the queue with the older program.<br><br>
|
||||
Click OK to proceed to SABnzbd''') + \
|
||||
('''<br><br><FORM><input type="button" onclick="this.form.action='/.'; this.form.submit(); return false;" value="%s"/></FORM>''' % Ta('OK'))
|
||||
|
||||
def MSG_SQLITE():
|
||||
return Ta(r'''
|
||||
SABnzbd detected that the file sqlite3.dll is missing.<br><br>
|
||||
Some poorly designed virus-scanners remove this file.<br>
|
||||
Please check your virus-scanner, try to re-install SABnzbd and complain to your virus-scanner vendor.<br>
|
||||
<br>
|
||||
''')
|
||||
|
||||
def panic_message(panic, a=None, b=None):
|
||||
"""Create the panic message from templates
|
||||
"""
|
||||
if sabnzbd.WIN32:
|
||||
os_str = Ta('Press Startkey+R and type the line (example):')
|
||||
prog_path = '"%s"' % sabnzbd.MY_FULLNAME
|
||||
else:
|
||||
os_str = Ta('Open a Terminal window and type the line (example):')
|
||||
prog_path = sabnzbd.MY_FULLNAME
|
||||
|
||||
if panic == PANIC_PORT:
|
||||
newport = int(b) + 1
|
||||
newport = "%s" % newport
|
||||
msg = MSG_BAD_PORT() % (b, a, os_str, prog_path, a, newport)
|
||||
elif panic == PANIC_XPORT:
|
||||
if int(b) < 1023:
|
||||
newport = 1024
|
||||
else:
|
||||
newport = int(b) + 1
|
||||
newport = "%s" % newport
|
||||
msg = MSG_ILL_PORT() % (b, a, os_str, prog_path, a, newport)
|
||||
elif panic == PANIC_TEMPL:
|
||||
msg = MSG_BAD_TEMPL() % a
|
||||
elif panic == PANIC_QUEUE:
|
||||
msg = MSG_BAD_QUEUE() % (a, os_str, prog_path)
|
||||
elif panic == PANIC_FWALL:
|
||||
if a:
|
||||
msg = MSG_BAD_FWALL() % Ta('It is likely that you are using ZoneAlarm on Vista.<br>')
|
||||
else:
|
||||
msg = MSG_BAD_FWALL() % "<br>"
|
||||
elif panic == PANIC_SQLITE:
|
||||
msg = MSG_SQLITE()
|
||||
elif panic == PANIC_HOST:
|
||||
msg = MSG_BAD_HOST() % (os_str, prog_path, 'localhost', b)
|
||||
else:
|
||||
msg = MSG_OTHER() % (a, b)
|
||||
|
||||
msg = MSG_BAD_NEWS() % (sabnzbd.MY_NAME, sabnzbd.__version__, sabnzbd.MY_NAME, sabnzbd.__version__,
|
||||
msg, Ta('Program did not start!'))
|
||||
|
||||
if sabnzbd.WIN_SERVICE:
|
||||
sabnzbd.WIN_SERVICE.ErrLogger('Panic exit', msg)
|
||||
|
||||
if (not cfg.autobrowser()) or sabnzbd.DAEMON:
|
||||
return
|
||||
|
||||
msgfile, url = tempfile.mkstemp(suffix='.html')
|
||||
os.write(msgfile, msg)
|
||||
os.close(msgfile)
|
||||
return url
|
||||
|
||||
|
||||
def panic_fwall(vista):
|
||||
launch_a_browser(panic_message(PANIC_FWALL, vista))
|
||||
|
||||
def panic_port(host, port):
|
||||
launch_a_browser(panic_message(PANIC_PORT, host, port))
|
||||
|
||||
def panic_host(host, port):
|
||||
launch_a_browser(panic_message(PANIC_HOST, host, port))
|
||||
|
||||
def panic_xport(host, port):
|
||||
launch_a_browser(panic_message(PANIC_XPORT, host, port))
|
||||
logging.error(Ta('You have no permisson to use port %s'), port)
|
||||
|
||||
def panic_queue(name):
|
||||
launch_a_browser(panic_message(PANIC_QUEUE, name, 0))
|
||||
|
||||
def panic_tmpl(name):
|
||||
launch_a_browser(panic_message(PANIC_TEMPL, name, 0))
|
||||
|
||||
def panic_sqlite(name):
|
||||
launch_a_browser(panic_message(PANIC_SQLITE, name, 0))
|
||||
|
||||
def panic_old_queue():
|
||||
msg = MSG_OLD_QUEUE()
|
||||
return MSG_BAD_NEWS() % (sabnzbd.MY_NAME, sabnzbd.__version__, sabnzbd.MY_NAME, sabnzbd.__version__, msg, '')
|
||||
|
||||
def panic(reason, remedy=""):
|
||||
print "\n%s:\n %s\n%s" % (Ta('Fatal error'), reason, remedy)
|
||||
launch_a_browser(panic_message(PANIC_OTHER, reason, remedy))
|
||||
|
||||
|
||||
def launch_a_browser(url, force=False):
|
||||
"""Launch a browser pointing to the URL
|
||||
"""
|
||||
if not force and not cfg.autobrowser() or sabnzbd.DAEMON:
|
||||
return
|
||||
|
||||
if cfg.enable_https() and not cfg.https_port.get_int():
|
||||
# Must use https, because http is not available
|
||||
url = url.replace('http:', 'https:')
|
||||
|
||||
logging.info("Lauching browser with %s", url)
|
||||
try:
|
||||
webbrowser.open(url, 2, 1)
|
||||
except:
|
||||
logging.warning(Ta('Cannot launch the browser, probably not found'))
|
||||
logging.info("Traceback: ", exc_info = True)
|
||||
|
||||
|
||||
def error_page_401(status, message, traceback, version):
|
||||
""" Custom handler for 401 error """
|
||||
title = T('Access denied')
|
||||
body = T('Error %s: You need to provide a valid username and password.') % status
|
||||
return r'''
|
||||
<html>
|
||||
<head>
|
||||
<title>%s</title>
|
||||
</head>
|
||||
<body>
|
||||
<br/><br/>
|
||||
<font color="#0000FF">%s</font>
|
||||
</body>
|
||||
</html>
|
||||
''' % (title, body)
|
||||
|
||||
|
||||
|
||||
@@ -888,16 +642,6 @@ def exit_sab(value):
|
||||
sys.exit(value)
|
||||
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
def notify(notificationName, message):
|
||||
""" Send a notification to the OS (OSX-only) """
|
||||
if sabnzbd.FOUNDATION:
|
||||
pool = Foundation.NSAutoreleasePool.alloc().init()
|
||||
nc = Foundation.NSDistributedNotificationCenter.defaultCenter()
|
||||
nc.postNotificationName_object_(notificationName, message)
|
||||
del pool
|
||||
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
def split_host(srv):
|
||||
""" Split host:port notation, allowing for IPV6 """
|
||||
@@ -1140,12 +884,9 @@ def on_cleanup_list(filename, skip_nzb=False):
|
||||
"""
|
||||
lst = cfg.cleanup_list()
|
||||
if lst:
|
||||
ext = os.path.splitext(filename)[1].strip().strip('.')
|
||||
if sabnzbd.WIN32:
|
||||
ext = ext.lower()
|
||||
|
||||
ext = os.path.splitext(filename)[1].strip().strip('.').lower()
|
||||
for k in lst:
|
||||
item = k.strip().strip('.')
|
||||
item = k.strip().strip('.').lower()
|
||||
if item == ext and not (skip_nzb and item == 'nzb'):
|
||||
return True
|
||||
return False
|
||||
@@ -1221,34 +962,9 @@ def int_conv(value):
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# Diskfree
|
||||
try:
|
||||
os.statvfs
|
||||
import statvfs
|
||||
# posix diskfree
|
||||
def diskfree(_dir):
|
||||
""" Return amount of free diskspace in GBytes
|
||||
"""
|
||||
try:
|
||||
s = os.statvfs(_dir)
|
||||
return (s[statvfs.F_BAVAIL] * s[statvfs.F_FRSIZE]) / GIGI
|
||||
except OSError:
|
||||
return 0.0
|
||||
def disktotal(_dir):
|
||||
""" Return amount of total diskspace in GBytes
|
||||
"""
|
||||
try:
|
||||
s = os.statvfs(_dir)
|
||||
return (s[statvfs.F_BLOCKS] * s[statvfs.F_FRSIZE]) / GIGI
|
||||
except OSError:
|
||||
return 0.0
|
||||
|
||||
except AttributeError:
|
||||
|
||||
try:
|
||||
import win32api
|
||||
except ImportError:
|
||||
pass
|
||||
if sabnzbd.WIN32:
|
||||
# windows diskfree
|
||||
import win32api
|
||||
def diskfree(_dir):
|
||||
""" Return amount of free diskspace in GBytes
|
||||
"""
|
||||
@@ -1265,6 +981,37 @@ except AttributeError:
|
||||
return disk_size / GIGI
|
||||
except:
|
||||
return 0.0
|
||||
else:
|
||||
try:
|
||||
os.statvfs
|
||||
# posix diskfree
|
||||
def diskfree(_dir):
|
||||
""" Return amount of free diskspace in GBytes
|
||||
"""
|
||||
try:
|
||||
s = os.statvfs(_dir)
|
||||
if s.f_bavail < 0:
|
||||
return float(sys.maxint) * float(s.f_frsize) / GIGI
|
||||
else:
|
||||
return float(s.f_bavail) * float(s.f_frsize) / GIGI
|
||||
except OSError:
|
||||
return 0.0
|
||||
def disktotal(_dir):
|
||||
""" Return amount of total diskspace in GBytes
|
||||
"""
|
||||
try:
|
||||
s = os.statvfs(_dir)
|
||||
if s.f_blocks < 0:
|
||||
return float(sys.maxint) * float(s.f_frsize) / GIGI
|
||||
else:
|
||||
return float(s.f_blocks) * float(s.f_frsize) / GIGI
|
||||
except OSError:
|
||||
return 0.0
|
||||
except ImportError:
|
||||
def diskfree(_dir):
|
||||
return 10.0
|
||||
def disktotal(_dir):
|
||||
return 20.0
|
||||
|
||||
|
||||
def create_https_certificates(ssl_cert, ssl_key):
|
||||
@@ -1355,208 +1102,6 @@ def ip_extract():
|
||||
return ips
|
||||
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# Power management for Windows
|
||||
|
||||
def win_hibernate():
|
||||
""" Hibernate Windows system, returns after wakeup
|
||||
"""
|
||||
try:
|
||||
subprocess.Popen("rundll32 powrprof.dll,SetSuspendState Hibernate")
|
||||
time.sleep(10)
|
||||
except:
|
||||
logging.error(Ta('Failed to hibernate system'))
|
||||
logging.info("Traceback: ", exc_info = True)
|
||||
|
||||
|
||||
def win_standby():
|
||||
""" Standby Windows system, returns after wakeup
|
||||
"""
|
||||
try:
|
||||
subprocess.Popen("rundll32 powrprof.dll,SetSuspendState Standby")
|
||||
time.sleep(10)
|
||||
except:
|
||||
logging.error(Ta('Failed to standby system'))
|
||||
logging.info("Traceback: ", exc_info = True)
|
||||
|
||||
|
||||
def win_shutdown():
|
||||
""" Shutdown Windows system, never returns
|
||||
"""
|
||||
try:
|
||||
import win32security
|
||||
import win32api
|
||||
import ntsecuritycon
|
||||
|
||||
flags = ntsecuritycon.TOKEN_ADJUST_PRIVILEGES | ntsecuritycon.TOKEN_QUERY
|
||||
htoken = win32security.OpenProcessToken(win32api.GetCurrentProcess(), flags)
|
||||
id_ = win32security.LookupPrivilegeValue(None, ntsecuritycon.SE_SHUTDOWN_NAME)
|
||||
newPrivileges = [(id_, ntsecuritycon.SE_PRIVILEGE_ENABLED)]
|
||||
win32security.AdjustTokenPrivileges(htoken, 0, newPrivileges)
|
||||
win32api.InitiateSystemShutdown("", "", 30, 1, 0)
|
||||
finally:
|
||||
os._exit(0)
|
||||
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# Power management for OSX
|
||||
|
||||
def osx_shutdown():
|
||||
""" Shutdown OSX system, never returns
|
||||
"""
|
||||
try:
|
||||
subprocess.call(['osascript', '-e', 'tell app "System Events" to shut down'])
|
||||
except:
|
||||
logging.error(Ta('Error while shutting down system'))
|
||||
logging.info("Traceback: ", exc_info = True)
|
||||
os._exit(0)
|
||||
|
||||
|
||||
def osx_standby():
|
||||
""" Make OSX system sleep, returns after wakeup
|
||||
"""
|
||||
try:
|
||||
subprocess.call(['osascript', '-e','tell app "System Events" to sleep'])
|
||||
time.sleep(10)
|
||||
except:
|
||||
logging.error(Ta('Failed to standby system'))
|
||||
logging.info("Traceback: ", exc_info = True)
|
||||
|
||||
|
||||
def osx_hibernate():
|
||||
""" Make OSX system sleep, returns after wakeup
|
||||
"""
|
||||
osx_standby()
|
||||
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# Power management for linux.
|
||||
#
|
||||
# Requires DBus plus either HAL [1] or the more modern ConsoleKit [2] and
|
||||
# DeviceKit(-power) [3]. HAL will eventually be deprecated but older systems
|
||||
# might still use it.
|
||||
# [1] http://people.freedesktop.org/~hughsient/temp/dbus-interface.html
|
||||
# [2] http://www.freedesktop.org/software/ConsoleKit/doc/ConsoleKit.html
|
||||
# [3] http://hal.freedesktop.org/docs/DeviceKit-power/
|
||||
#
|
||||
# Original code was contributed by Marcel de Vries <marceldevries@phannet.cc>
|
||||
#
|
||||
|
||||
try:
|
||||
import dbus
|
||||
HAVE_DBUS = True
|
||||
except ImportError:
|
||||
HAVE_DBUS = False
|
||||
|
||||
|
||||
def _get_sessionproxy():
|
||||
""" Return (proxy-object, interface), (None, None) if not available
|
||||
"""
|
||||
name = 'org.freedesktop.PowerManagement'
|
||||
path = '/org/freedesktop/PowerManagement'
|
||||
interface = 'org.freedesktop.PowerManagement'
|
||||
try:
|
||||
bus = dbus.SessionBus()
|
||||
return bus.get_object(name, path), interface
|
||||
except dbus.exceptions.DBusException:
|
||||
return None, None
|
||||
|
||||
def _get_systemproxy(method):
|
||||
""" Return (proxy-object, interface, pinterface), (None, None, None) if not available
|
||||
"""
|
||||
if method == 'ConsoleKit':
|
||||
name = 'org.freedesktop.ConsoleKit'
|
||||
path = '/org/freedesktop/ConsoleKit/Manager'
|
||||
interface = 'org.freedesktop.ConsoleKit.Manager'
|
||||
pinterface = None
|
||||
elif method == 'DeviceKit':
|
||||
name = 'org.freedesktop.DeviceKit.Power'
|
||||
path = '/org/freedesktop/DeviceKit/Power'
|
||||
interface = 'org.freedesktop.DeviceKit.Power'
|
||||
pinterface = 'org.freedesktop.DBus.Properties'
|
||||
elif method == 'UPower':
|
||||
name = 'org.freedesktop.UPower'
|
||||
path = '/org/freedesktop/UPower'
|
||||
interface = 'org.freedesktop.UPower'
|
||||
pinterface = 'org.freedesktop.DBus.Properties'
|
||||
try:
|
||||
bus = dbus.SystemBus()
|
||||
return bus.get_object(name, path), interface, pinterface
|
||||
except dbus.exceptions.DBusException, msg:
|
||||
logging.info('DBus not reachable (%s)', msg)
|
||||
return None, None, None
|
||||
|
||||
|
||||
def linux_shutdown():
|
||||
""" Make Linux system shutdown, never returns
|
||||
"""
|
||||
if not HAVE_DBUS: os._exit(0)
|
||||
|
||||
proxy, interface = _get_sessionproxy()
|
||||
if proxy:
|
||||
if proxy.CanShutdown():
|
||||
proxy.Shutdown(dbus_interface=interface)
|
||||
else:
|
||||
proxy, interface, pinterface = _get_systemproxy('ConsoleKit')
|
||||
if proxy:
|
||||
if proxy.CanStop(dbus_interface=interface):
|
||||
try:
|
||||
proxy.Stop(dbus_interface=interface)
|
||||
except dbus.exceptions.DBusException, msg:
|
||||
logging.info('Received a DBus exception %s', latin1(msg))
|
||||
else:
|
||||
logging.info('DBus does not support Stop (shutdown)')
|
||||
os._exit(0)
|
||||
|
||||
|
||||
def linux_hibernate():
|
||||
""" Make Linux system go into hibernate, returns after wakeup
|
||||
"""
|
||||
if not HAVE_DBUS: return
|
||||
|
||||
proxy, interface = _get_sessionproxy()
|
||||
if proxy:
|
||||
if proxy.CanHibernate():
|
||||
proxy.Hibernate(dbus_interface=interface)
|
||||
else:
|
||||
proxy, interface, pinterface = _get_systemproxy('UPower')
|
||||
if not proxy:
|
||||
proxy, interface, pinterface = _get_systemproxy('DeviceKit')
|
||||
if proxy:
|
||||
if proxy.Get(interface, 'can-hibernate', dbus_interface=pinterface):
|
||||
try:
|
||||
proxy.Hibernate(dbus_interface=interface)
|
||||
except dbus.exceptions.DBusException, msg:
|
||||
logging.info('Received a DBus exception %s', latin1(msg))
|
||||
else:
|
||||
logging.info('DBus does not support Hibernate')
|
||||
time.sleep(10)
|
||||
|
||||
|
||||
def linux_standby():
|
||||
""" Make Linux system go into standby, returns after wakeup
|
||||
"""
|
||||
if not HAVE_DBUS: return
|
||||
|
||||
proxy, interface = _get_sessionproxy()
|
||||
if proxy:
|
||||
if proxy.CanSuspend():
|
||||
proxy.Suspend(dbus_interface=interface)
|
||||
else:
|
||||
proxy, interface, pinterface = _get_systemproxy('UPower')
|
||||
if not proxy:
|
||||
proxy, interface, pinterface = _get_systemproxy('DeviceKit')
|
||||
if proxy:
|
||||
if proxy.Get(interface, 'can-suspend', dbus_interface=pinterface):
|
||||
try:
|
||||
proxy.Suspend(dbus_interface=interface)
|
||||
except dbus.exceptions.DBusException, msg:
|
||||
logging.info('Received a DBus exception %s', latin1(msg))
|
||||
else:
|
||||
logging.info('DBus does not support Suspend (standby)')
|
||||
time.sleep(10)
|
||||
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
|
||||
def renamer(old, new):
|
||||
@@ -1599,26 +1144,25 @@ def remove_dir(path):
|
||||
os.rmdir(path)
|
||||
|
||||
|
||||
def remove_all(path, pattern='*'):
|
||||
""" Remove folder and all its content
|
||||
def remove_all(path, pattern='*', keep_folder=False, recursive=False):
|
||||
""" Remove folder and all its content (optionally recursive)
|
||||
"""
|
||||
if os.path.exists(path):
|
||||
for f in globber(path, pattern):
|
||||
os.remove(f)
|
||||
try:
|
||||
os.rmdir(path)
|
||||
except:
|
||||
pass
|
||||
files = globber(path, pattern)
|
||||
if pattern == '*' and not sabnzbd.WIN32:
|
||||
files.extend(globber(path, '.*'))
|
||||
|
||||
for f in files:
|
||||
if os.path.isfile(f):
|
||||
try:
|
||||
os.remove(f)
|
||||
except:
|
||||
logging.info('Cannot remove file %s', f)
|
||||
elif recursive:
|
||||
remove_all(f, pattern, False, True)
|
||||
if not keep_folder:
|
||||
try:
|
||||
os.rmdir(path)
|
||||
except:
|
||||
logging.info('Cannot remove folder %s', path)
|
||||
|
||||
def clean_folder(path, pattern='*'):
|
||||
""" Remove all files in root of folder, remove folder if empty afterwards """
|
||||
for file in globber(path, pattern):
|
||||
try:
|
||||
os.remove(file)
|
||||
except:
|
||||
pass
|
||||
try:
|
||||
os.rmdir(path)
|
||||
except:
|
||||
pass
|
||||
|
||||
@@ -96,7 +96,7 @@ def find_programs(curdir):
|
||||
sabnzbd.newsunpack.RAR_COMMAND = check(curdir, 'osx/unrar/unrar')
|
||||
|
||||
if sabnzbd.WIN32:
|
||||
if sabnzbd.WIN64:
|
||||
if sabnzbd.WIN64 and cfg.allow_64bit_tools.get():
|
||||
sabnzbd.newsunpack.PAR2_COMMAND = check(curdir, 'win/par2/x64/par2.exe')
|
||||
sabnzbd.newsunpack.RAR_COMMAND = check(curdir, 'win/unrar/x64/UnRAR.exe')
|
||||
if not sabnzbd.newsunpack.PAR2_COMMAND:
|
||||
@@ -949,7 +949,7 @@ def PAR_Verify(parfile, parfile_nzf, nzo, setname, joinables, classic=False):
|
||||
|
||||
extrapars = parfile_nzf.extrapars
|
||||
|
||||
logging.info("%s", extrapars)
|
||||
logging.info("Extra pars = %s", extrapars)
|
||||
|
||||
## Look for the smallest par2file
|
||||
block_table = {}
|
||||
@@ -964,6 +964,13 @@ def PAR_Verify(parfile, parfile_nzf, nzo, setname, joinables, classic=False):
|
||||
nzo.add_parfile(nzf)
|
||||
## mark for readd
|
||||
readd = True
|
||||
else:
|
||||
msg = T('Invalid par2 files, cannot verify or repair')
|
||||
nzo.fail_msg = msg
|
||||
msg = u'[%s] %s' % (unicoder(setname), msg)
|
||||
nzo.set_unpack_info('Repair', msg, set=setname)
|
||||
nzo.status = 'Failed'
|
||||
|
||||
|
||||
elif line.startswith('You need'):
|
||||
chunks = line.split()
|
||||
|
||||
@@ -263,6 +263,13 @@ class NewsWrapper(object):
|
||||
self.pass_sent = True
|
||||
self.pass_ok = True
|
||||
|
||||
if code == '501' and self.user_sent:
|
||||
# Server asked for username, we sent empty one,
|
||||
# but it doesn't accept
|
||||
code = '481'
|
||||
self.user_ok = True
|
||||
self.pass_sent = True
|
||||
|
||||
if code == '480':
|
||||
self.force_login = True
|
||||
self.connected = False
|
||||
@@ -271,7 +278,7 @@ class NewsWrapper(object):
|
||||
self.pass_sent = False
|
||||
self.pass_ok = False
|
||||
|
||||
if code == '400':
|
||||
if code in ('400', '502'):
|
||||
raise NNTPPermanentError(self.lines[0])
|
||||
elif not self.user_sent:
|
||||
command = 'authinfo user %s\r\n' % (self.server.username)
|
||||
@@ -280,6 +287,12 @@ class NewsWrapper(object):
|
||||
elif not self.user_ok:
|
||||
if code == '381':
|
||||
self.user_ok = True
|
||||
elif code == '281':
|
||||
# No login required
|
||||
self.user_ok = True
|
||||
self.pass_sent = True
|
||||
self.pass_ok = True
|
||||
self.connected = True
|
||||
|
||||
if self.user_ok and not self.pass_sent:
|
||||
command = 'authinfo pass %s\r\n' % (self.server.password)
|
||||
|
||||
@@ -27,13 +27,14 @@ import datetime
|
||||
import sabnzbd
|
||||
from sabnzbd.trylist import TryList
|
||||
from sabnzbd.nzbstuff import NzbObject
|
||||
from sabnzbd.misc import panic_queue, exit_sab, cat_to_opts, \
|
||||
from sabnzbd.misc import exit_sab, cat_to_opts, \
|
||||
get_admin_path, remove_all, globber
|
||||
from sabnzbd.panic import panic_queue
|
||||
import sabnzbd.database as database
|
||||
from sabnzbd.decorators import NZBQUEUE_LOCK, synchronized, synchronized_CV
|
||||
from sabnzbd.constants import QUEUE_FILE_NAME, QUEUE_VERSION, FUTURE_Q_FOLDER, JOB_ADMIN, \
|
||||
LOW_PRIORITY, NORMAL_PRIORITY, HIGH_PRIORITY, TOP_PRIORITY, \
|
||||
PNFO_BYTES_FIELD, PNFO_BYTES_LEFT_FIELD
|
||||
REPAIR_PRIORITY, PNFO_BYTES_FIELD, PNFO_BYTES_LEFT_FIELD
|
||||
import sabnzbd.cfg as cfg
|
||||
from sabnzbd.articlecache import ArticleCache
|
||||
import sabnzbd.downloader
|
||||
@@ -57,7 +58,6 @@ class NzbQueue(TryList):
|
||||
self.__nzo_list = []
|
||||
self.__nzo_table = {}
|
||||
|
||||
self.__auto_sort = cfg.auto_sort()
|
||||
NzbQueue.do = self
|
||||
|
||||
def read_queue(self, repair):
|
||||
@@ -230,7 +230,7 @@ class NzbQueue(TryList):
|
||||
future.priority = None
|
||||
self.set_priority(future.nzo_id, priority)
|
||||
|
||||
if self.__auto_sort:
|
||||
if cfg.auto_sort():
|
||||
self.sort_by_avg_age()
|
||||
|
||||
self.reset_try_list()
|
||||
@@ -278,8 +278,6 @@ class NzbQueue(TryList):
|
||||
@synchronized(NZBQUEUE_LOCK)
|
||||
def add(self, nzo, save=True, quiet=False):
|
||||
assert isinstance(nzo, NzbObject)
|
||||
sabnzbd.QUEUECOMPLETEACTION_GO = False
|
||||
|
||||
if not nzo.nzo_id:
|
||||
nzo.nzo_id = sabnzbd.get_new_id('nzo', nzo.workpath, self.__nzo_table)
|
||||
|
||||
@@ -297,9 +295,8 @@ class NzbQueue(TryList):
|
||||
nzo.deleted = False
|
||||
priority = nzo.priority
|
||||
self.__nzo_table[nzo.nzo_id] = nzo
|
||||
if priority == TOP_PRIORITY:
|
||||
#A top priority item (usually a completed download fetching pars)
|
||||
#is added to the top of the queue
|
||||
if priority > HIGH_PRIORITY:
|
||||
#Top and repair priority items are added to the top of the queue
|
||||
self.__nzo_list.insert(0, nzo)
|
||||
elif priority == LOW_PRIORITY:
|
||||
self.__nzo_list.append(nzo)
|
||||
@@ -314,9 +311,9 @@ class NzbQueue(TryList):
|
||||
for position in self.__nzo_list:
|
||||
if position.priority < priority:
|
||||
self.__nzo_list.insert(pos, nzo)
|
||||
added=True
|
||||
added = True
|
||||
break
|
||||
pos+=1
|
||||
pos += 1
|
||||
if not added:
|
||||
#if there are no other items classed as a lower priority
|
||||
#then it will be added to the bottom of the queue
|
||||
@@ -330,7 +327,7 @@ class NzbQueue(TryList):
|
||||
if not (quiet or nzo.status in ('Fetching',)):
|
||||
osx.sendGrowlMsg(T('NZB added to queue'), nzo.filename, osx.NOTIFICATION['download'])
|
||||
|
||||
if self.__auto_sort:
|
||||
if cfg.auto_sort():
|
||||
self.sort_by_avg_age()
|
||||
|
||||
@synchronized(NZBQUEUE_LOCK)
|
||||
@@ -688,20 +685,28 @@ class NzbQueue(TryList):
|
||||
logging.warning(Ta('%s -> Unknown encoding'), filename)
|
||||
|
||||
if post_done:
|
||||
if not self.__nzo_list:
|
||||
# Close server connections
|
||||
if cfg.autodisconnect():
|
||||
sabnzbd.downloader.Downloader.do.disconnect()
|
||||
|
||||
# Sets the end-of-queue back on if disabled
|
||||
# adding an nzb and re-adding for more blocks disables it
|
||||
if sabnzbd.QUEUECOMPLETEACTION:
|
||||
sabnzbd.QUEUECOMPLETEACTION_GO = True
|
||||
if self.actives(grabs=False) < 2 and cfg.autodisconnect():
|
||||
# This was the last job, close server connections
|
||||
sabnzbd.downloader.Downloader.do.disconnect()
|
||||
|
||||
# Notify assembler to call postprocessor
|
||||
Assembler.do.process((nzo, None))
|
||||
|
||||
|
||||
@synchronized(NZBQUEUE_LOCK)
|
||||
def actives(self, grabs=True):
|
||||
""" Return amount of non-paused jobs, optionally with 'grabbing' items
|
||||
"""
|
||||
n = 0
|
||||
for nzo in self.__nzo_list:
|
||||
# Ignore any items that are paused
|
||||
if grabs and nzo.status == 'Grabbing':
|
||||
n += 1
|
||||
elif nzo.status not in ('Paused', 'Grabbing'):
|
||||
n += 1
|
||||
return n
|
||||
|
||||
|
||||
@synchronized(NZBQUEUE_LOCK)
|
||||
def queue_info(self, for_cli = False):
|
||||
bytes_left = 0
|
||||
@@ -778,17 +783,20 @@ def _nzo_size_cmp(nzo1, nzo2):
|
||||
return cmp(nzo1.bytes, nzo2.bytes)
|
||||
|
||||
def sort_queue_function(nzo_list, method, reverse):
|
||||
ultra_high_priority = [nzo for nzo in nzo_list if nzo.priority == REPAIR_PRIORITY]
|
||||
super_high_priority = [nzo for nzo in nzo_list if nzo.priority == TOP_PRIORITY]
|
||||
high_priority = [nzo for nzo in nzo_list if nzo.priority == HIGH_PRIORITY]
|
||||
normal_priority = [nzo for nzo in nzo_list if nzo.priority == NORMAL_PRIORITY]
|
||||
low_priority = [nzo for nzo in nzo_list if nzo.priority == LOW_PRIORITY]
|
||||
|
||||
ultra_high_priority.sort(cmp=method, reverse=reverse)
|
||||
super_high_priority.sort(cmp=method, reverse=reverse)
|
||||
high_priority.sort(cmp=method, reverse=reverse)
|
||||
normal_priority.sort(cmp=method, reverse=reverse)
|
||||
low_priority.sort(cmp=method, reverse=reverse)
|
||||
|
||||
new_list = super_high_priority
|
||||
new_list = ultra_high_priority
|
||||
new_list.extend(super_high_priority)
|
||||
new_list.extend(high_priority)
|
||||
new_list.extend(normal_priority)
|
||||
new_list.extend(low_priority)
|
||||
|
||||
@@ -38,7 +38,7 @@ from sabnzbd.constants import sample_match, GIGI, ATTRIB_FILE, JOB_ADMIN, \
|
||||
DEFAULT_PRIORITY, LOW_PRIORITY, NORMAL_PRIORITY, \
|
||||
HIGH_PRIORITY, PAUSED_PRIORITY, TOP_PRIORITY, DUP_PRIORITY
|
||||
from sabnzbd.misc import to_units, cat_to_opts, cat_convert, sanitize_foldername, \
|
||||
get_unique_path, get_admin_path, remove_all, clean_folder, \
|
||||
get_unique_path, get_admin_path, remove_all, \
|
||||
sanitize_filename, globber, sanitize_foldername, int_conv
|
||||
import sabnzbd.cfg as cfg
|
||||
from sabnzbd.trylist import TryList
|
||||
@@ -200,7 +200,7 @@ class NzbFile(TryList):
|
||||
""" Load the article objects from disk """
|
||||
logging.debug("Finishing import on %s", self.subject)
|
||||
|
||||
article_db = sabnzbd.load_data(self.nzf_id, self.nzo.workpath)
|
||||
article_db = sabnzbd.load_data(self.nzf_id, self.nzo.workpath, remove=False)
|
||||
if article_db:
|
||||
for partnum in article_db:
|
||||
art_id = article_db[partnum][0]
|
||||
@@ -271,6 +271,13 @@ class NzbFile(TryList):
|
||||
""" Get lowest article number of this file """
|
||||
return min(self.decodetable)
|
||||
|
||||
def remove_admin(self):
|
||||
""" Remove article database from disk (sabnzbd_nzf_<id>)"""
|
||||
try:
|
||||
os.remove(os.path.join(self.nzo.workpath, self.nzf_id))
|
||||
except:
|
||||
pass
|
||||
|
||||
def __getstate__(self):
|
||||
""" Save to pickle file, translating attributes """
|
||||
dict_ = {}
|
||||
@@ -297,7 +304,7 @@ class NzbFile(TryList):
|
||||
################################################################################
|
||||
class NzbParser(xml.sax.handler.ContentHandler):
|
||||
""" Forgiving parser for NZB's """
|
||||
def __init__ (self, nzo):
|
||||
def __init__ (self, nzo, remove_samples=False):
|
||||
self.nzo = nzo
|
||||
assert isinstance(self.nzo, NzbObject)
|
||||
self.in_nzb = False
|
||||
@@ -312,9 +319,10 @@ class NzbParser(xml.sax.handler.ContentHandler):
|
||||
self.skipped_files = 0
|
||||
self.nzf_list = []
|
||||
self.groups = []
|
||||
self.filter = remove_samples
|
||||
|
||||
def startDocument(self):
|
||||
self.filter = cfg.ignore_samples()
|
||||
pass
|
||||
|
||||
def startElement(self, name, attrs):
|
||||
if name == 'segment' and self.in_nzb and self.in_file and self.in_segments:
|
||||
@@ -338,7 +346,7 @@ class NzbParser(xml.sax.handler.ContentHandler):
|
||||
else:
|
||||
self.filename = subject.strip()
|
||||
|
||||
if self.filter == 2 and RE_SAMPLE.search(subject):
|
||||
if self.filter and RE_SAMPLE.search(subject):
|
||||
logging.info('Skipping sample file %s', subject)
|
||||
else:
|
||||
self.in_file = True
|
||||
@@ -635,7 +643,7 @@ class NzbObject(TryList):
|
||||
if 'A&A)' in nzb:
|
||||
# Fix needed to compensate for some dumb NZB posters
|
||||
nzb = nzb.replace('A&A)', 'A&A)')
|
||||
handler = NzbParser(self)
|
||||
handler = NzbParser(self, cfg.ignore_samples() == 2 and not reuse)
|
||||
parser = xml.sax.make_parser()
|
||||
parser.setFeature(xml.sax.handler.feature_external_ges, 0)
|
||||
parser.setContentHandler(handler)
|
||||
@@ -1116,12 +1124,12 @@ class NzbObject(TryList):
|
||||
|
||||
if self.new_caching and not self.futuretype:
|
||||
if keep_basic:
|
||||
clean_folder(wpath, 'SABnzbd_nz?_*')
|
||||
clean_folder(wpath, 'SABnzbd_article_*')
|
||||
remove_all(wpath, 'SABnzbd_nz?_*')
|
||||
remove_all(wpath, 'SABnzbd_article_*')
|
||||
else:
|
||||
clean_folder(wpath)
|
||||
remove_all(wpath, recursive=True)
|
||||
if del_files:
|
||||
clean_folder(self.downpath)
|
||||
remove_all(self.downpath, recursive=True)
|
||||
else:
|
||||
try:
|
||||
os.rmdir(self.downpath)
|
||||
@@ -1344,33 +1352,33 @@ def split_filename(name):
|
||||
|
||||
def format_time_string(seconds, days=0):
|
||||
""" Given seconds and days, return formatted day/hour/min/sec string
|
||||
LACKS I18N !!
|
||||
"""
|
||||
def unit(n, single):
|
||||
if n == 1:
|
||||
return n, Tx(single)
|
||||
else:
|
||||
return n, Tx(single + 's')
|
||||
try:
|
||||
seconds = int(seconds)
|
||||
except:
|
||||
except ValueError:
|
||||
seconds = 0
|
||||
|
||||
completestr = ''
|
||||
if days:
|
||||
completestr += '%s day%s ' % (days, s_returner(days))
|
||||
completestr += '%s %s ' % unit(days, 'day')
|
||||
if (seconds/3600) >= 1:
|
||||
completestr += '%s hour%s ' % (seconds/3600, s_returner((seconds/3600)))
|
||||
completestr += '%s %s ' % unit(seconds/3600, 'hour')
|
||||
seconds -= (seconds/3600)*3600
|
||||
if (seconds/60) >= 1:
|
||||
completestr += '%s minute%s ' % (seconds/60, s_returner((seconds/60)))
|
||||
completestr += '%s %s ' % unit(seconds/60, 'minute')
|
||||
seconds -= (seconds/60)*60
|
||||
if seconds > 0:
|
||||
completestr += '%s second%s ' % (seconds, s_returner(seconds))
|
||||
completestr += '%s %s ' % unit(seconds, 'second')
|
||||
else:
|
||||
completestr += '%s %s' % unit(0, 'second')
|
||||
|
||||
return completestr.strip()
|
||||
|
||||
def s_returner(value):
|
||||
if value > 1:
|
||||
return 's'
|
||||
else:
|
||||
return ''
|
||||
|
||||
|
||||
RE_PASSWORD1 = re.compile(r'([^/\\]+)[/\\](.+)')
|
||||
RE_PASSWORD2 = re.compile(r'(.+){{([^{}]+)}}$')
|
||||
|
||||
@@ -38,7 +38,8 @@ import sabnzbd
|
||||
import sabnzbd.cfg
|
||||
|
||||
from sabnzbd.constants import *
|
||||
from sabnzbd.misc import launch_a_browser,get_filename,get_ext,diskfree
|
||||
from sabnzbd.misc import get_filename, get_ext, diskfree
|
||||
from sabnzbd.panic import launch_a_browser
|
||||
from sabnzbd.utils import osx
|
||||
|
||||
from sabnzbd.nzbqueue import NzbQueue
|
||||
@@ -53,7 +54,7 @@ from sabnzbd.api import check_trans
|
||||
|
||||
status_icons = {'idle':'../Resources/sab_idle.png','pause':'../Resources/sab_pause.png','clicked':'../Resources/sab_clicked.png'}
|
||||
start_time = NSDate.date()
|
||||
debug = 1
|
||||
debug = 0
|
||||
|
||||
|
||||
class SABnzbdDelegate(NSObject):
|
||||
@@ -704,22 +705,18 @@ class SABnzbdDelegate(NSObject):
|
||||
def application_openFiles_(self, nsapp, filenames):
|
||||
#logging.info('[osx] file open')
|
||||
#logging.info('[osx] file : %s' % (filenames))
|
||||
pp = None
|
||||
script = None
|
||||
cat = None
|
||||
priority = None
|
||||
for name in filenames :
|
||||
#logging.info('[osx] processing : %s' % (name))
|
||||
logging.info('[osx] receiving from OSX : %s' % name)
|
||||
if os.path.exists(name):
|
||||
fn = get_filename(name)
|
||||
#logging.info('[osx] filename : %s' % (fn))
|
||||
if fn:
|
||||
if get_ext(name) in ('.zip','.rar', '.gz'):
|
||||
if get_ext(name) in ('.zip', '.rar'):
|
||||
#logging.info('[osx] archive')
|
||||
dirscanner.ProcessArchiveFile(fn, name, pp=pp, script=script, cat=cat, priority=priority, keep=True)
|
||||
elif get_ext(name) in ('.nzb'):
|
||||
dirscanner.ProcessArchiveFile(fn, name, keep=True)
|
||||
elif get_ext(name) in ('.nzb', '.gz'):
|
||||
#logging.info('[osx] nzb')
|
||||
dirscanner.ProcessSingleFile(fn, name, pp=pp, script=script, cat=cat, priority=priority, keep=True)
|
||||
dirscanner.ProcessSingleFile(fn, name, keep=True)
|
||||
#logging.info('opening done')
|
||||
|
||||
def applicationShouldTerminate_(self, sender):
|
||||
@@ -737,3 +734,13 @@ class SABnzbdDelegate(NSObject):
|
||||
sys.stdout.flush()
|
||||
return NSTerminateNow
|
||||
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
def notify(notificationName, message):
|
||||
""" Send a notification to the OS (OSX-only) """
|
||||
if sabnzbd.FOUNDATION:
|
||||
pool = Foundation.NSAutoreleasePool.alloc().init()
|
||||
nc = Foundation.NSDistributedNotificationCenter.defaultCenter()
|
||||
nc.postNotificationName_object_(notificationName, message)
|
||||
del pool
|
||||
|
||||
|
||||
265
sabnzbd/panic.py
Normal file
@@ -0,0 +1,265 @@
|
||||
#!/usr/bin/python -OO
|
||||
# Copyright 2008-2011 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.panic - Send panic message to the browser
|
||||
"""
|
||||
|
||||
import os
|
||||
import logging
|
||||
import webbrowser
|
||||
import tempfile
|
||||
|
||||
import sabnzbd
|
||||
import sabnzbd.cfg as cfg
|
||||
|
||||
PANIC_NONE = 0
|
||||
PANIC_PORT = 1
|
||||
PANIC_TEMPL = 2
|
||||
PANIC_QUEUE = 3
|
||||
PANIC_FWALL = 4
|
||||
PANIC_OTHER = 5
|
||||
PANIC_XPORT = 6
|
||||
PANIC_SQLITE = 7
|
||||
PANIC_HOST = 8
|
||||
|
||||
def MSG_BAD_NEWS():
|
||||
return r'''
|
||||
<html>
|
||||
<head>
|
||||
<title>''' + Ta('Problem with') + ''' %s %s</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1><font color="#0000FF"> %s %s</font></h1>
|
||||
<p align="center"> </p>
|
||||
<p align="center"><font size="5">
|
||||
<blockquote>
|
||||
%s
|
||||
</blockquote>
|
||||
<br>%s<br>
|
||||
</body>
|
||||
</html>
|
||||
'''
|
||||
|
||||
def MSG_BAD_FWALL():
|
||||
return Ta(r'''
|
||||
SABnzbd is not compatible with some software firewalls.<br>
|
||||
%s<br>
|
||||
Sorry, but we cannot solve this incompatibility right now.<br>
|
||||
Please file a complaint at your firewall supplier.<br>
|
||||
<br>
|
||||
''')
|
||||
|
||||
def MSG_BAD_PORT():
|
||||
return Ta(r'''
|
||||
SABnzbd needs a free tcp/ip port for its internal web server.<br>
|
||||
Port %s on %s was tried , but it is not available.<br>
|
||||
Some other software uses the port or SABnzbd is already running.<br>
|
||||
<br>
|
||||
Please restart SABnzbd with a different port number.''') + \
|
||||
'''<br>
|
||||
<br>
|
||||
%s<br>
|
||||
%s --server %s:%s<br>
|
||||
<br>''' + \
|
||||
Ta(r'If you get this error message again, please try a different number.<br>')
|
||||
|
||||
def MSG_ILL_PORT():
|
||||
return Ta(r'''
|
||||
SABnzbd needs a free tcp/ip port for its internal web server.<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>
|
||||
%s<br>
|
||||
%s --server %s:%s<br>
|
||||
<br>''' + \
|
||||
Ta(r'If you get this error message again, please try a different number.<br>')
|
||||
|
||||
def MSG_BAD_HOST():
|
||||
return Ta(r'''
|
||||
SABnzbd needs a valid host address for its internal web server.<br>
|
||||
You have specified an invalid address.<br>
|
||||
Safe values are <b>localhost</b> and <b>0.0.0.0</b><br>
|
||||
<br>
|
||||
Please restart SABnzbd with a proper host address.''') + \
|
||||
'''<br>
|
||||
<br>
|
||||
%s<br>
|
||||
%s --server %s:%s<br>
|
||||
<br>
|
||||
'''
|
||||
|
||||
def MSG_BAD_QUEUE():
|
||||
return Ta(r'''
|
||||
SABnzbd detected saved data from an other SABnzbd version<br>
|
||||
but cannot re-use the data of the other program.<br><br>
|
||||
You may want to finish your queue first with the other program.<br><br>
|
||||
After that, start this program with the "--clean" option.<br>
|
||||
This will erase the current queue and history!<br>
|
||||
SABnzbd read the file "%s".''') + \
|
||||
'''<br>
|
||||
<br>
|
||||
%s<br>
|
||||
%s --clean<br>
|
||||
<br>
|
||||
'''
|
||||
|
||||
def MSG_BAD_TEMPL():
|
||||
return Ta(r'''
|
||||
SABnzbd cannot find its web interface files in %s.<br>
|
||||
Please install the program again.<br>
|
||||
<br>
|
||||
''')
|
||||
|
||||
def MSG_OTHER():
|
||||
return Ta('SABnzbd detected a fatal error:') + '<br>%s<br><br>%s<br>'
|
||||
|
||||
def MSG_OLD_QUEUE():
|
||||
return Ta(r'''
|
||||
SABnzbd detected a Queue and History from an older (0.4.x) release.<br><br>
|
||||
Both queue and history will be ignored and may get lost!<br><br>
|
||||
You may choose to stop SABnzbd and finish the queue with the older program.<br><br>
|
||||
Click OK to proceed to SABnzbd''') + \
|
||||
('''<br><br><FORM><input type="button" onclick="this.form.action='/.'; this.form.submit(); return false;" value="%s"/></FORM>''' % Ta('OK'))
|
||||
|
||||
def MSG_SQLITE():
|
||||
return Ta(r'''
|
||||
SABnzbd detected that the file sqlite3.dll is missing.<br><br>
|
||||
Some poorly designed virus-scanners remove this file.<br>
|
||||
Please check your virus-scanner, try to re-install SABnzbd and complain to your virus-scanner vendor.<br>
|
||||
<br>
|
||||
''')
|
||||
|
||||
def panic_message(panic, a=None, b=None):
|
||||
"""Create the panic message from templates
|
||||
"""
|
||||
if sabnzbd.WIN32:
|
||||
os_str = Ta('Press Startkey+R and type the line (example):')
|
||||
prog_path = '"%s"' % sabnzbd.MY_FULLNAME
|
||||
else:
|
||||
os_str = Ta('Open a Terminal window and type the line (example):')
|
||||
prog_path = sabnzbd.MY_FULLNAME
|
||||
|
||||
if panic == PANIC_PORT:
|
||||
newport = int(b) + 1
|
||||
newport = "%s" % newport
|
||||
msg = MSG_BAD_PORT() % (b, a, os_str, prog_path, a, newport)
|
||||
elif panic == PANIC_XPORT:
|
||||
if int(b) < 1023:
|
||||
newport = 1024
|
||||
else:
|
||||
newport = int(b) + 1
|
||||
newport = "%s" % newport
|
||||
msg = MSG_ILL_PORT() % (b, a, os_str, prog_path, a, newport)
|
||||
elif panic == PANIC_TEMPL:
|
||||
msg = MSG_BAD_TEMPL() % a
|
||||
elif panic == PANIC_QUEUE:
|
||||
msg = MSG_BAD_QUEUE() % (a, os_str, prog_path)
|
||||
elif panic == PANIC_FWALL:
|
||||
if a:
|
||||
msg = MSG_BAD_FWALL() % Ta('It is likely that you are using ZoneAlarm on Vista.<br>')
|
||||
else:
|
||||
msg = MSG_BAD_FWALL() % "<br>"
|
||||
elif panic == PANIC_SQLITE:
|
||||
msg = MSG_SQLITE()
|
||||
elif panic == PANIC_HOST:
|
||||
msg = MSG_BAD_HOST() % (os_str, prog_path, 'localhost', b)
|
||||
else:
|
||||
msg = MSG_OTHER() % (a, b)
|
||||
|
||||
msg = MSG_BAD_NEWS() % (sabnzbd.MY_NAME, sabnzbd.__version__, sabnzbd.MY_NAME, sabnzbd.__version__,
|
||||
msg, Ta('Program did not start!'))
|
||||
|
||||
if sabnzbd.WIN_SERVICE:
|
||||
sabnzbd.WIN_SERVICE.ErrLogger('Panic exit', msg)
|
||||
|
||||
if (not cfg.autobrowser()) or sabnzbd.DAEMON:
|
||||
return
|
||||
|
||||
msgfile, url = tempfile.mkstemp(suffix='.html')
|
||||
os.write(msgfile, msg)
|
||||
os.close(msgfile)
|
||||
return url
|
||||
|
||||
|
||||
def panic_fwall(vista):
|
||||
launch_a_browser(panic_message(PANIC_FWALL, vista))
|
||||
|
||||
def panic_port(host, port):
|
||||
launch_a_browser(panic_message(PANIC_PORT, host, port))
|
||||
|
||||
def panic_host(host, port):
|
||||
launch_a_browser(panic_message(PANIC_HOST, host, port))
|
||||
|
||||
def panic_xport(host, port):
|
||||
launch_a_browser(panic_message(PANIC_XPORT, host, port))
|
||||
logging.error(Ta('You have no permisson to use port %s'), port)
|
||||
|
||||
def panic_queue(name):
|
||||
launch_a_browser(panic_message(PANIC_QUEUE, name, 0))
|
||||
|
||||
def panic_tmpl(name):
|
||||
launch_a_browser(panic_message(PANIC_TEMPL, name, 0))
|
||||
|
||||
def panic_sqlite(name):
|
||||
launch_a_browser(panic_message(PANIC_SQLITE, name, 0))
|
||||
|
||||
def panic_old_queue():
|
||||
msg = MSG_OLD_QUEUE()
|
||||
return MSG_BAD_NEWS() % (sabnzbd.MY_NAME, sabnzbd.__version__, sabnzbd.MY_NAME, sabnzbd.__version__, msg, '')
|
||||
|
||||
def panic(reason, remedy=""):
|
||||
print "\n%s:\n %s\n%s" % (Ta('Fatal error'), reason, remedy)
|
||||
launch_a_browser(panic_message(PANIC_OTHER, reason, remedy))
|
||||
|
||||
|
||||
def launch_a_browser(url, force=False):
|
||||
"""Launch a browser pointing to the URL
|
||||
"""
|
||||
if not force and not cfg.autobrowser() or sabnzbd.DAEMON:
|
||||
return
|
||||
|
||||
if cfg.enable_https() and not cfg.https_port.get_int():
|
||||
# Must use https, because http is not available
|
||||
url = url.replace('http:', 'https:')
|
||||
|
||||
logging.info("Lauching browser with %s", url)
|
||||
try:
|
||||
webbrowser.open(url, 2, 1)
|
||||
except:
|
||||
logging.warning(Ta('Cannot launch the browser, probably not found'))
|
||||
logging.info("Traceback: ", exc_info = True)
|
||||
|
||||
|
||||
def error_page_401(status, message, traceback, version):
|
||||
""" Custom handler for 401 error """
|
||||
title = T('Access denied')
|
||||
body = T('Error %s: You need to provide a valid username and password.') % status
|
||||
return r'''
|
||||
<html>
|
||||
<head>
|
||||
<title>%s</title>
|
||||
</head>
|
||||
<body>
|
||||
<br/><br/>
|
||||
<font color="#0000FF">%s</font>
|
||||
</body>
|
||||
</html>
|
||||
''' % (title, body)
|
||||
@@ -34,7 +34,7 @@ from sabnzbd.misc import real_path, get_unique_path, create_dirs, move_to_path,
|
||||
get_unique_filename, make_script_path, \
|
||||
on_cleanup_list, renamer, remove_dir, remove_all, globber
|
||||
from sabnzbd.tvsort import Sorter
|
||||
from sabnzbd.constants import TOP_PRIORITY, POSTPROC_QUEUE_FILE_NAME, \
|
||||
from sabnzbd.constants import REPAIR_PRIORITY, POSTPROC_QUEUE_FILE_NAME, \
|
||||
POSTPROC_QUEUE_VERSION, sample_match, JOB_ADMIN
|
||||
from sabnzbd.encoding import TRANS, unicoder
|
||||
from sabnzbd.newzbin import Bookmarks
|
||||
@@ -88,6 +88,8 @@ class PostProcessor(Thread):
|
||||
self.history_queue = []
|
||||
logging.info("Loading postproc queue")
|
||||
data = sabnzbd.load_admin(POSTPROC_QUEUE_FILE_NAME)
|
||||
if data is None:
|
||||
return
|
||||
try:
|
||||
version, history_queue = data
|
||||
if POSTPROC_QUEUE_VERSION != version:
|
||||
@@ -138,21 +140,39 @@ class PostProcessor(Thread):
|
||||
""" Return list of NZOs that still need to be processed """
|
||||
return [nzo for nzo in self.history_queue if nzo.work_name]
|
||||
|
||||
def get_path(self, nzo_id):
|
||||
""" Return download path for given nzo_id or None when not found """
|
||||
for nzo in self.history_queue:
|
||||
if nzo.nzo_id == nzo_id:
|
||||
return nzo.downpath
|
||||
return None
|
||||
|
||||
def run(self):
|
||||
""" Actual processing """
|
||||
while 1:
|
||||
check_eoq = False
|
||||
|
||||
while not self.__stop:
|
||||
self.__busy = False
|
||||
if self.queue.empty(): handle_empty_queue()
|
||||
|
||||
while (not self.__stop) and self.paused:
|
||||
if self.paused:
|
||||
time.sleep(5)
|
||||
continue
|
||||
|
||||
## Get a job from the queue, quit on empty job
|
||||
nzo = self.queue.get()
|
||||
if not nzo: break
|
||||
try:
|
||||
nzo = self.queue.get(timeout=3)
|
||||
except Queue.Empty:
|
||||
if check_eoq:
|
||||
check_eoq = False
|
||||
handle_empty_queue()
|
||||
continue
|
||||
|
||||
## This job was already deleted.
|
||||
## Stop job
|
||||
if not nzo:
|
||||
continue
|
||||
|
||||
## Job was already deleted.
|
||||
if not nzo.work_name:
|
||||
check_eoq = True
|
||||
continue
|
||||
|
||||
## Flag NZO as being processed
|
||||
@@ -161,11 +181,11 @@ class PostProcessor(Thread):
|
||||
## Pause downloader, if users wants that
|
||||
if cfg.pause_on_post_processing():
|
||||
sabnzbd.downloader.Downloader.do.wait_for_postproc()
|
||||
cfg.complete_dir.set_create()
|
||||
|
||||
self.__busy = True
|
||||
if process_job(nzo):
|
||||
self.remove(nzo)
|
||||
check_eoq = True
|
||||
|
||||
## Allow download to proceed
|
||||
sabnzbd.downloader.Downloader.do.resume_from_postproc()
|
||||
@@ -321,7 +341,11 @@ def process_job(nzo):
|
||||
cleanup_list(tmp_workdir_complete, True)
|
||||
|
||||
## Check if this is an NZB-only download, if so redirect to queue
|
||||
nzb_list = nzb_redirect(tmp_workdir_complete, nzo.final_name, nzo.pp, script, cat, priority=nzo.priority)
|
||||
## except when PP was Download-only
|
||||
if flag_repair:
|
||||
nzb_list = nzb_redirect(tmp_workdir_complete, nzo.final_name, nzo.pp, script, cat, priority=nzo.priority)
|
||||
else:
|
||||
nzb_list = None
|
||||
if nzb_list:
|
||||
nzo.set_unpack_info('Download', T('Sent %s to queue') % unicoder(nzb_list))
|
||||
try:
|
||||
@@ -456,8 +480,7 @@ def process_job(nzo):
|
||||
try:
|
||||
if os.path.exists(workdir):
|
||||
logging.debug('Removing workdir %s', workdir)
|
||||
remove_all(os.path.join(workdir, JOB_ADMIN))
|
||||
remove_dir(workdir)
|
||||
remove_all(workdir, recursive=True)
|
||||
except:
|
||||
logging.error(Ta('Error removing workdir (%s)'), workdir)
|
||||
logging.info("Traceback: ", exc_info = True)
|
||||
@@ -497,8 +520,7 @@ def parring(nzo, workdir):
|
||||
|
||||
if re_add:
|
||||
logging.info('Readded %s to queue', filename)
|
||||
sabnzbd.QUEUECOMPLETEACTION_GO = False
|
||||
nzo.priority = TOP_PRIORITY
|
||||
nzo.priority = REPAIR_PRIORITY
|
||||
sabnzbd.nzbqueue.add_nzo(nzo)
|
||||
sabnzbd.downloader.Downloader.do.resume_from_postproc()
|
||||
|
||||
@@ -575,7 +597,7 @@ def addPrefixes(path, dirprefix):
|
||||
|
||||
def handle_empty_queue():
|
||||
""" Check if empty queue calls for action """
|
||||
if sabnzbd.QUEUECOMPLETEACTION_GO:
|
||||
if sabnzbd.nzbqueue.NzbQueue.do.actives() == 0:
|
||||
sabnzbd.save_state()
|
||||
logging.info("Queue has finished, launching: %s (%s)", \
|
||||
sabnzbd.QUEUECOMPLETEACTION, sabnzbd.QUEUECOMPLETEARG)
|
||||
@@ -584,7 +606,6 @@ def handle_empty_queue():
|
||||
else:
|
||||
Thread(target=sabnzbd.QUEUECOMPLETEACTION).start()
|
||||
|
||||
sabnzbd.QUEUECOMPLETEACTION_GO = False
|
||||
sabnzbd.change_queue_complete_action(cfg.queue_complete(), new=False)
|
||||
|
||||
|
||||
@@ -596,15 +617,18 @@ def cleanup_list(wdir, skip_nzb):
|
||||
files = os.listdir(wdir)
|
||||
except:
|
||||
files = ()
|
||||
for file_ in files:
|
||||
if on_cleanup_list(file_, skip_nzb):
|
||||
path = os.path.join(wdir, file_)
|
||||
try:
|
||||
logging.info("Removing unwanted file %s", path)
|
||||
os.remove(path)
|
||||
except:
|
||||
logging.error(Ta('Removing %s failed'), path)
|
||||
logging.info("Traceback: ", exc_info = True)
|
||||
for file in files:
|
||||
path = os.path.join(wdir, file)
|
||||
if os.path.isdir(path):
|
||||
cleanup_list(path, skip_nzb)
|
||||
else:
|
||||
if on_cleanup_list(file, skip_nzb):
|
||||
try:
|
||||
logging.info("Removing unwanted file %s", path)
|
||||
os.remove(path)
|
||||
except:
|
||||
logging.error(Ta('Removing %s failed'), path)
|
||||
logging.info("Traceback: ", exc_info = True)
|
||||
|
||||
|
||||
def prefix(path, pre):
|
||||
|
||||
228
sabnzbd/powersup.py
Normal file
@@ -0,0 +1,228 @@
|
||||
#!/usr/bin/python -OO
|
||||
# Copyright 2008-2011 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.powersup - System power management support
|
||||
"""
|
||||
|
||||
import os
|
||||
import subprocess
|
||||
import logging
|
||||
import time
|
||||
|
||||
from sabnzbd.encoding import latin1
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# Power management for Windows
|
||||
|
||||
def win_hibernate():
|
||||
""" Hibernate Windows system, returns after wakeup
|
||||
"""
|
||||
try:
|
||||
subprocess.Popen("rundll32 powrprof.dll,SetSuspendState Hibernate")
|
||||
time.sleep(10)
|
||||
except:
|
||||
logging.error(Ta('Failed to hibernate system'))
|
||||
logging.info("Traceback: ", exc_info = True)
|
||||
|
||||
|
||||
def win_standby():
|
||||
""" Standby Windows system, returns after wakeup
|
||||
"""
|
||||
try:
|
||||
subprocess.Popen("rundll32 powrprof.dll,SetSuspendState Standby")
|
||||
time.sleep(10)
|
||||
except:
|
||||
logging.error(Ta('Failed to standby system'))
|
||||
logging.info("Traceback: ", exc_info = True)
|
||||
|
||||
|
||||
def win_shutdown():
|
||||
""" Shutdown Windows system, never returns
|
||||
"""
|
||||
try:
|
||||
import win32security
|
||||
import win32api
|
||||
import ntsecuritycon
|
||||
|
||||
flags = ntsecuritycon.TOKEN_ADJUST_PRIVILEGES | ntsecuritycon.TOKEN_QUERY
|
||||
htoken = win32security.OpenProcessToken(win32api.GetCurrentProcess(), flags)
|
||||
id_ = win32security.LookupPrivilegeValue(None, ntsecuritycon.SE_SHUTDOWN_NAME)
|
||||
newPrivileges = [(id_, ntsecuritycon.SE_PRIVILEGE_ENABLED)]
|
||||
win32security.AdjustTokenPrivileges(htoken, 0, newPrivileges)
|
||||
win32api.InitiateSystemShutdown("", "", 30, 1, 0)
|
||||
finally:
|
||||
os._exit(0)
|
||||
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# Power management for OSX
|
||||
|
||||
def osx_shutdown():
|
||||
""" Shutdown OSX system, never returns
|
||||
"""
|
||||
try:
|
||||
subprocess.call(['osascript', '-e', 'tell app "System Events" to shut down'])
|
||||
except:
|
||||
logging.error(Ta('Error while shutting down system'))
|
||||
logging.info("Traceback: ", exc_info = True)
|
||||
os._exit(0)
|
||||
|
||||
|
||||
def osx_standby():
|
||||
""" Make OSX system sleep, returns after wakeup
|
||||
"""
|
||||
try:
|
||||
subprocess.call(['osascript', '-e','tell app "System Events" to sleep'])
|
||||
time.sleep(10)
|
||||
except:
|
||||
logging.error(Ta('Failed to standby system'))
|
||||
logging.info("Traceback: ", exc_info = True)
|
||||
|
||||
|
||||
def osx_hibernate():
|
||||
""" Make OSX system sleep, returns after wakeup
|
||||
"""
|
||||
osx_standby()
|
||||
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# Power management for linux.
|
||||
#
|
||||
# Requires DBus plus either HAL [1] or the more modern ConsoleKit [2] and
|
||||
# DeviceKit(-power) [3]. HAL will eventually be deprecated but older systems
|
||||
# might still use it.
|
||||
# [1] http://people.freedesktop.org/~hughsient/temp/dbus-interface.html
|
||||
# [2] http://www.freedesktop.org/software/ConsoleKit/doc/ConsoleKit.html
|
||||
# [3] http://hal.freedesktop.org/docs/DeviceKit-power/
|
||||
#
|
||||
# Original code was contributed by Marcel de Vries <marceldevries@phannet.cc>
|
||||
#
|
||||
|
||||
try:
|
||||
import dbus
|
||||
HAVE_DBUS = True
|
||||
except ImportError:
|
||||
HAVE_DBUS = False
|
||||
|
||||
|
||||
def _get_sessionproxy():
|
||||
""" Return (proxy-object, interface), (None, None) if not available
|
||||
"""
|
||||
name = 'org.freedesktop.PowerManagement'
|
||||
path = '/org/freedesktop/PowerManagement'
|
||||
interface = 'org.freedesktop.PowerManagement'
|
||||
try:
|
||||
bus = dbus.SessionBus()
|
||||
return bus.get_object(name, path), interface
|
||||
except dbus.exceptions.DBusException:
|
||||
return None, None
|
||||
|
||||
def _get_systemproxy(method):
|
||||
""" Return (proxy-object, interface, pinterface), (None, None, None) if not available
|
||||
"""
|
||||
if method == 'ConsoleKit':
|
||||
name = 'org.freedesktop.ConsoleKit'
|
||||
path = '/org/freedesktop/ConsoleKit/Manager'
|
||||
interface = 'org.freedesktop.ConsoleKit.Manager'
|
||||
pinterface = None
|
||||
elif method == 'DeviceKit':
|
||||
name = 'org.freedesktop.DeviceKit.Power'
|
||||
path = '/org/freedesktop/DeviceKit/Power'
|
||||
interface = 'org.freedesktop.DeviceKit.Power'
|
||||
pinterface = 'org.freedesktop.DBus.Properties'
|
||||
elif method == 'UPower':
|
||||
name = 'org.freedesktop.UPower'
|
||||
path = '/org/freedesktop/UPower'
|
||||
interface = 'org.freedesktop.UPower'
|
||||
pinterface = 'org.freedesktop.DBus.Properties'
|
||||
try:
|
||||
bus = dbus.SystemBus()
|
||||
return bus.get_object(name, path), interface, pinterface
|
||||
except dbus.exceptions.DBusException, msg:
|
||||
logging.info('DBus not reachable (%s)', msg)
|
||||
return None, None, None
|
||||
|
||||
|
||||
def linux_shutdown():
|
||||
""" Make Linux system shutdown, never returns
|
||||
"""
|
||||
if not HAVE_DBUS: os._exit(0)
|
||||
|
||||
proxy, interface = _get_sessionproxy()
|
||||
if proxy:
|
||||
if proxy.CanShutdown():
|
||||
proxy.Shutdown(dbus_interface=interface)
|
||||
else:
|
||||
proxy, interface, pinterface = _get_systemproxy('ConsoleKit')
|
||||
if proxy:
|
||||
if proxy.CanStop(dbus_interface=interface):
|
||||
try:
|
||||
proxy.Stop(dbus_interface=interface)
|
||||
except dbus.exceptions.DBusException, msg:
|
||||
logging.info('Received a DBus exception %s', latin1(msg))
|
||||
else:
|
||||
logging.info('DBus does not support Stop (shutdown)')
|
||||
os._exit(0)
|
||||
|
||||
|
||||
def linux_hibernate():
|
||||
""" Make Linux system go into hibernate, returns after wakeup
|
||||
"""
|
||||
if not HAVE_DBUS: return
|
||||
|
||||
proxy, interface = _get_sessionproxy()
|
||||
if proxy:
|
||||
if proxy.CanHibernate():
|
||||
proxy.Hibernate(dbus_interface=interface)
|
||||
else:
|
||||
proxy, interface, pinterface = _get_systemproxy('UPower')
|
||||
if not proxy:
|
||||
proxy, interface, pinterface = _get_systemproxy('DeviceKit')
|
||||
if proxy:
|
||||
if proxy.Get(interface, 'can-hibernate', dbus_interface=pinterface):
|
||||
try:
|
||||
proxy.Hibernate(dbus_interface=interface)
|
||||
except dbus.exceptions.DBusException, msg:
|
||||
logging.info('Received a DBus exception %s', latin1(msg))
|
||||
else:
|
||||
logging.info('DBus does not support Hibernate')
|
||||
time.sleep(10)
|
||||
|
||||
|
||||
def linux_standby():
|
||||
""" Make Linux system go into standby, returns after wakeup
|
||||
"""
|
||||
if not HAVE_DBUS: return
|
||||
|
||||
proxy, interface = _get_sessionproxy()
|
||||
if proxy:
|
||||
if proxy.CanSuspend():
|
||||
proxy.Suspend(dbus_interface=interface)
|
||||
else:
|
||||
proxy, interface, pinterface = _get_systemproxy('UPower')
|
||||
if not proxy:
|
||||
proxy, interface, pinterface = _get_systemproxy('DeviceKit')
|
||||
if proxy:
|
||||
if proxy.Get(interface, 'can-suspend', dbus_interface=pinterface):
|
||||
try:
|
||||
proxy.Suspend(dbus_interface=interface)
|
||||
except dbus.exceptions.DBusException, msg:
|
||||
logging.info('Received a DBus exception %s', latin1(msg))
|
||||
else:
|
||||
logging.info('DBus does not support Suspend (standby)')
|
||||
time.sleep(10)
|
||||
@@ -23,6 +23,8 @@ import re
|
||||
import logging
|
||||
import time
|
||||
import threading
|
||||
import urllib
|
||||
import os
|
||||
|
||||
import sabnzbd
|
||||
from sabnzbd.constants import *
|
||||
@@ -125,6 +127,23 @@ def convert_filter(text):
|
||||
logging.error(Ta('Could not compile regex: %s'), text)
|
||||
return None
|
||||
|
||||
_EXPIRE_SEC = 3*24*3600 # 3 days
|
||||
def remove_obsolete(jobs, new_jobs):
|
||||
""" Expire G/B links that are not in new_jobs (mark them 'X')
|
||||
Expired links older than 3 days are removed from 'jobs'
|
||||
"""
|
||||
now = time.time()
|
||||
limit = now - _EXPIRE_SEC
|
||||
olds = jobs.keys()
|
||||
for old in olds:
|
||||
tm = jobs[old]['time']
|
||||
if old not in new_jobs:
|
||||
if jobs[old].get('status', ' ')[0] in ('G', 'B'):
|
||||
jobs[old]['status'] = 'X'
|
||||
if jobs[old]['status'] == 'X' and tm < limit:
|
||||
logging.debug("Purging link %s", old)
|
||||
del jobs[old]
|
||||
|
||||
|
||||
LOCK = threading.RLock()
|
||||
class RSSQueue(object):
|
||||
@@ -140,9 +159,13 @@ class RSSQueue(object):
|
||||
|
||||
self.jobs = {}
|
||||
try:
|
||||
defined = config.get_rss().keys()
|
||||
feeds = sabnzbd.load_admin(RSS_FILE_NAME)
|
||||
if type(feeds) == type({}):
|
||||
for feed in feeds:
|
||||
if feed not in defined:
|
||||
logging.debug('Dropping obsolete data for feed "%s"', feed)
|
||||
continue
|
||||
self.jobs[feed] = {}
|
||||
for link in feeds[feed]:
|
||||
data = feeds[feed][link]
|
||||
@@ -168,7 +191,8 @@ class RSSQueue(object):
|
||||
item = feeds[feed][link]
|
||||
if not isinstance(item, dict) or not isinstance(item.get('title'), unicode):
|
||||
raise IndexError
|
||||
if not item.get('status', ' ')[0] not in ('D', 'G', 'B', 'X'): item['status'] = 'X'
|
||||
if item.get('status', ' ')[0] not in ('D', 'G', 'B', 'X'):
|
||||
item['status'] = 'X'
|
||||
if not isinstance(item.get('url'), unicode): item['url'] = ''
|
||||
if not check_str(item.get('cat')): item['cat'] = ''
|
||||
if not check_str(item.get('orgcat')): item['orgcat'] = ''
|
||||
@@ -182,6 +206,8 @@ class RSSQueue(object):
|
||||
except (KeyError, IndexError):
|
||||
logging.info('Incorrect entry in %s detected, discarding %s', RSS_FILE_NAME, item)
|
||||
|
||||
remove_obsolete(self.jobs[feed], self.jobs[feed].keys())
|
||||
|
||||
except IOError:
|
||||
logging.debug('Cannot read file %s', RSS_FILE_NAME)
|
||||
|
||||
@@ -298,6 +324,12 @@ class RSSQueue(object):
|
||||
logging.info(msg)
|
||||
return unicoder(msg)
|
||||
|
||||
status = d.get('status', 999)
|
||||
if status in (401, 402, 403):
|
||||
msg = Ta('Do not have valid authentication for feed %s') % feed
|
||||
logging.info(msg)
|
||||
return unicoder(msg)
|
||||
|
||||
entries = d.get('entries')
|
||||
if 'bozo_exception' in d and not entries:
|
||||
msg = Ta('Failed to retrieve RSS from %s: %s') % (uri, xml_name(str(d['bozo_exception'])))
|
||||
@@ -337,12 +369,20 @@ class RSSQueue(object):
|
||||
title = unicoder(atitle)
|
||||
|
||||
if link:
|
||||
# Make sure there are no spaces in the URL
|
||||
link = link.replace(' ','')
|
||||
# Make sure spaces are quoted in the URL
|
||||
if 'nzbclub.com' in link:
|
||||
link, path = os.path.split(link.strip())
|
||||
link = '%s/%s' % (link, urllib.quote(path))
|
||||
else:
|
||||
link = link.strip().replace(' ','%20')
|
||||
|
||||
newlinks.append(link)
|
||||
|
||||
if (link not in jobs) or (jobs[link].get('status', ' ') in ('G', 'B', 'G*', 'B*')):
|
||||
if link in jobs:
|
||||
jobstat = jobs[link].get('status', ' ')[0]
|
||||
else:
|
||||
jobstat = 'N'
|
||||
if jobstat in 'NGB' or (jobstat == 'X' and readout):
|
||||
# Match this title against all filters
|
||||
logging.debug('Trying title %s', atitle)
|
||||
result = False
|
||||
@@ -402,7 +442,7 @@ class RSSQueue(object):
|
||||
logging.info("Ignoring duplicate job %s", atitle)
|
||||
continue
|
||||
else:
|
||||
priority = DUP_PRIORITY
|
||||
myPrio = DUP_PRIORITY
|
||||
|
||||
act = download and not first
|
||||
if link in jobs:
|
||||
@@ -425,25 +465,7 @@ class RSSQueue(object):
|
||||
if new_downloads and cfg.email_rss() and not force:
|
||||
emailer.rss_mail(feed, new_downloads)
|
||||
|
||||
# If links are in table for more than 1 week, remove
|
||||
# Flag old D/B links as obsolete, so that they don't show up in Preview
|
||||
now = time.time()
|
||||
limit = now - 1*7*24*3600
|
||||
olds = jobs.keys()
|
||||
for old in olds:
|
||||
if old not in newlinks:
|
||||
if jobs[old].get('status', ' ')[0] in ('G', 'B'):
|
||||
jobs[old]['status'] = 'X'
|
||||
try:
|
||||
tm = float(jobs[old]['time'])
|
||||
except:
|
||||
# Fix missing timestamp in older RSS_DATA.SAB file
|
||||
jobs[old]['time'] = now
|
||||
tm = now
|
||||
if tm < limit:
|
||||
logging.debug("Purging link %s", old)
|
||||
del jobs[old]
|
||||
|
||||
remove_obsolete(jobs, newlinks)
|
||||
return ''
|
||||
|
||||
|
||||
|
||||
@@ -42,6 +42,7 @@ SKIN_TEXT = {
|
||||
'post-Verifying' : TT('Verifying...'), #: PP status
|
||||
'post-Downloading' : TT('Downloading'), #: Pseudo-PP status, in reality used for Queue-status
|
||||
'post-Grabbing' : TT('Get NZB'), #: Pseudo-PP status, in reality used for Grabbing status
|
||||
'post-Checking' : TT('Checking'), #: PP status
|
||||
|
||||
'sch-frequency' : TT('Frequency'), #: #: Config->Scheduler
|
||||
'sch-action' : TT('Action'), #: #: Config->Scheduler
|
||||
@@ -115,6 +116,7 @@ SKIN_TEXT = {
|
||||
'cmenu-servers' : TT('Servers'), #: Main menu item
|
||||
'cmenu-scheduling' : TT('Scheduling'), #: Main menu item
|
||||
'cmenu-rss' : TT('RSS'), #: Main menu item
|
||||
'cmenu-emailN' : TT('Notifications'), #: Main menu item
|
||||
'cmenu-email' : TT('Email'), #: Main menu item
|
||||
'cmenu-newzbin' : TT('Index Sites'), #: Main menu item
|
||||
'cmenu-cat' : TT('Categories'), #: Main menu item
|
||||
@@ -154,6 +156,7 @@ SKIN_TEXT = {
|
||||
'pp-u' : TT('U'),
|
||||
'pp-d' : TT('D'),
|
||||
'pr-force' : TT('Force'),
|
||||
'pr-repair' : TT('Repair'),
|
||||
'pr-normal' : TT('Normal'),
|
||||
'pr-high' : TT('High'),
|
||||
'pr-low' : TT('Low'),
|
||||
@@ -194,6 +197,7 @@ SKIN_TEXT = {
|
||||
'removeNZB-Files' : TT('Remove NZB & Delete Files'), #: Queue page button
|
||||
'AofB' : TT('of'), #: Queue page, as in "4G *of* 10G"
|
||||
'missingArt': TT('Missing articles'), #: Caption for missing articles in Queue
|
||||
'quotum-left' : TT('Quotum left'), #: Remaining quotum (displayed in Queue)
|
||||
|
||||
# History page
|
||||
'purgeHist' : TT('Purge History'), #: History page button
|
||||
@@ -419,6 +423,17 @@ SKIN_TEXT = {
|
||||
'swtag-queue' : TT('Queue'),
|
||||
'swtag-pp' : TT('Post processing'),
|
||||
'swtag-naming' : TT('Naming'),
|
||||
'swtag-quotum' : TT('Quotum'),
|
||||
'opt-quotum_size' : TT('Size'), #: Size of the download quotum
|
||||
'explain-quotum_size' : TT('How much can be downloaded this month (K/M/G)'),
|
||||
'opt-quotum_day' : TT('Reset day'), #: Reset day of the download quotum
|
||||
'explain-quotum_day' : TT('On which day of the month or week (1=Monday) does your ISP reset the quotum? (Optionally with hh:mm)'),
|
||||
'opt-quotum_resume' : TT('Auto resume'), #: Auto-resume download on the reset day
|
||||
'explain-quotum_resume' : TT('Should downloading resume after the quotum is reset?'),
|
||||
'opt-quotum_period' : TT('Quotum period'), #: Does the quotum get reset every day, week or month?
|
||||
'explain-quotum_period' : TT('Does the quotum get reset each day, week or month?'),
|
||||
'opt-pre_check' : TT('Check before download'),
|
||||
'explain-pre_check' : TT('Try to predict successful completion before actual download (slower!)'),
|
||||
|
||||
|
||||
# Config->Server
|
||||
@@ -485,12 +500,12 @@ SKIN_TEXT = {
|
||||
'filters' : TT('Filters'), #: Tab title for Config->Feeds
|
||||
|
||||
# Config->Email
|
||||
'configEmail' : TT('Email Notification'),
|
||||
'emailOptions' : TT('Email Options'),
|
||||
'configEmail' : TT('Email Notifications'), #: Main Config page
|
||||
'emailOptions' : TT('Email Options'), #: Section header
|
||||
'opt-email_endjob' : TT('Email Notification On Job Completion'),
|
||||
'email-never' : TT('Never'),
|
||||
'email-always' : TT('Always'),
|
||||
'email-errorOnly' : TT('Error-only'),
|
||||
'email-never' : TT('Never'), #: When to send email
|
||||
'email-always' : TT('Always'), #: When to send email
|
||||
'email-errorOnly' : TT('Error-only'), #: When to send email
|
||||
'opt-email_full' : TT('Disk Full Notifications'),
|
||||
'explain-email_full' : TT('Send email when disk is full and SABnzbd is paused.'),
|
||||
'opt-email_rss' : TT('Send RSS notifications'),
|
||||
@@ -506,6 +521,16 @@ SKIN_TEXT = {
|
||||
'explain-email_account' : TT('For authenticated email, account name.'),
|
||||
'opt-email_pwd' : TT('OPTIONAL Account Password'),
|
||||
'explain-email_pwd' : TT('For authenticated email, password.'),
|
||||
'growlSettings' : TT('Notifications'), #: Section header
|
||||
'opt-growl_enable' : TT('Enable Growl'), #: Don't translate "Growl"
|
||||
'explain-growl_enable' : TT('Send notifications to Growl'), #: Don't translate "Growl"
|
||||
'opt-growl_server' : TT('Server address'), #: Address of Growl server
|
||||
'explain-growl_server' : TT('Only use for remote Growl server (host:port)'), #: Don't translate "Growl"
|
||||
'opt-growl_password' : TT('Server password'), #: Growl server password
|
||||
'explain-growl_password' : TT('Optional password for Growl server'), #: Don't translate "Growl"
|
||||
'opt-ntfosd_enable' : TT('Enable NotifyOSD'), #: Don't translate "NotifyOSD"
|
||||
'explain-ntfosd_enable' : TT('Send notifications to NotifyOSD'), #: Don't translate "NotifyOSD"
|
||||
'testNotify' : TT('Test Notification'),
|
||||
|
||||
# Config->Newzbin
|
||||
'explain-newzbin' : TT('If you have an account at <strong>www.newzbin.com</strong>, you can enter your account info here.<br />This will unlock extra functionality.'),
|
||||
@@ -741,6 +766,7 @@ SKIN_TEXT = {
|
||||
'smpl-downloading' : TT('Downloading'),
|
||||
'smpl-idle' : TT('Idle'),
|
||||
'smpl-emailsent' : TT('Email Sent!'),
|
||||
'smpl-notesent' : TT('Notification Sent!'),
|
||||
'smpl-saving' : TT('Saving..'),
|
||||
'smpl-saved' : TT('Saved'),
|
||||
'smpl-failed' : TT('Failed'),
|
||||
|
||||
@@ -524,12 +524,13 @@ class GenericSorter(object):
|
||||
""" Collect and construct all the values needed for path replacement """
|
||||
|
||||
## - Get Year
|
||||
dirname = self.original_dirname.replace('_', ' ')
|
||||
RE_YEAR = re.compile(year_match, re.I)
|
||||
year_m = RE_YEAR.search(self.original_dirname)
|
||||
year_m = RE_YEAR.search(dirname)
|
||||
if year_m:
|
||||
# Find the last matched date
|
||||
# Keep year_m to use in getTitles
|
||||
year = RE_YEAR.findall(self.original_dirname)[-1][0]
|
||||
year = RE_YEAR.findall(dirname)[-1][0]
|
||||
self.movie_info['year'] = year
|
||||
else:
|
||||
self.movie_info['year'] = ''
|
||||
@@ -921,6 +922,10 @@ def getTitles(match, name):
|
||||
xtitled = titler(x)
|
||||
title = replace_word(title, xtitled, x)
|
||||
|
||||
# Make sure the first letter of the title is always uppercase
|
||||
if title:
|
||||
title = titler(title[0]) + title[1:]
|
||||
|
||||
# The title with spaces replaced by dots
|
||||
dots = title.replace(" - ", "-").replace(' ','.').replace('_','.')
|
||||
dots = dots.replace('(', '.').replace(')','.').replace('..','.').rstrip('.')
|
||||
|
||||
@@ -194,10 +194,12 @@ class URLGrabber(Thread):
|
||||
if res == 0:
|
||||
NzbQueue.do.remove(future_nzo.nzo_id, add_to_history=False)
|
||||
elif res == -2:
|
||||
self.add(url, future_nzo)
|
||||
elif matrix_id and length > 0:
|
||||
# Keep retrying NzbMatrix forever (if file not empty)
|
||||
self.add(url, future_nzo)
|
||||
retry_count -= 1
|
||||
if retry_count > 0:
|
||||
logging.info('Incomplete NZB, retry %s', url)
|
||||
self.queue.put((url, future_nzo, retry_count))
|
||||
else:
|
||||
misc.bad_fetch(future_nzo, url, retry=True, content=True)
|
||||
else:
|
||||
misc.bad_fetch(future_nzo, url, retry=True, content=True)
|
||||
# Check if a supported archive
|
||||
|
||||
@@ -261,13 +261,19 @@ class Scheduler:
|
||||
if sys.version_info>=(2,6):
|
||||
# code for sched module of python 2.6+
|
||||
def _getqueuetoptime(self):
|
||||
return self.sched._queue[0].time
|
||||
try:
|
||||
return self.sched._queue[0].time
|
||||
except IndexError:
|
||||
return 0.0
|
||||
def _clearschedqueue(self):
|
||||
self.sched._queue[:] = []
|
||||
else:
|
||||
# code for sched module of python 2.5 and older
|
||||
def _getqueuetoptime(self):
|
||||
return self.sched.queue[0][0]
|
||||
try:
|
||||
return self.sched.queue[0][0]
|
||||
except IndexError:
|
||||
return 0.0
|
||||
def _clearschedqueue(self):
|
||||
self.sched.queue[:] = []
|
||||
|
||||
|
||||
@@ -22,6 +22,19 @@
|
||||
#NOTIFICATION = {'startup':'grwl-notif-startup','download':'grwl-notif-dl','pp':'grwl-notif-pp','other':'grwl-notif-other'}
|
||||
NOTIFICATION = {'startup':'1. On Startup/Shutdown','download':'2. On adding NZB','pp':'3. On post-processing','complete':'4. On download terminated','other':'5. Other Messages'}
|
||||
|
||||
# For a future release, make texts translatable.
|
||||
if 0:
|
||||
#------------------------------------------------------------------------------
|
||||
# Define translatable message table
|
||||
TT = lambda x:x
|
||||
_NOTIFICATION = {
|
||||
'startup' : TT('Startup/Shutdown'), #: Message class for Growl server
|
||||
'download' : TT('Added NZB'), #: Message class for Growl server
|
||||
'pp' : TT('Post-processing started'), #: Message class for Growl server
|
||||
'complete' : TT('Job finished'), #: Message class for Growl server
|
||||
'other' : TT('Other Messages') #: Message class for Growl server
|
||||
}
|
||||
|
||||
try:
|
||||
import Growl
|
||||
import os.path
|
||||
|
||||
@@ -109,7 +109,11 @@ def test_nntp_server(host, port, server=None, username=None, password=None, ssl=
|
||||
return False, xml_name(str(sys.exc_info()[1]))
|
||||
|
||||
# Could do with making a function for return codes to be used by downloader
|
||||
code = nw.lines[0][:3]
|
||||
try:
|
||||
code = nw.lines[0][:3]
|
||||
except IndexError:
|
||||
code = ''
|
||||
nw.lines.append('')
|
||||
|
||||
if code == '480':
|
||||
return False, T('Server requires username and password.')
|
||||
|
||||
@@ -181,7 +181,7 @@ print 'Creating the NSIS POT file'
|
||||
if not os.path.exists(PON_DIR):
|
||||
os.makedirs(PON_DIR)
|
||||
src = open(NSIS, 'r')
|
||||
dst = open(os.path.join(PON_DIR, DOMAIN_NSIS+'.pot'), 'w')
|
||||
dst = open(os.path.join(PON_DIR, DOMAIN_NSIS+'.pot'), 'wb')
|
||||
dst.write(HEADER.replace('__TYPE__', 'NSIS'))
|
||||
dst.write('\n')
|
||||
count = 0
|
||||
|
||||
@@ -49,7 +49,12 @@ def add(id, str, fuzzy):
|
||||
"Add a non-fuzzy translation to the dictionary."
|
||||
global MESSAGES
|
||||
if not fuzzy and str:
|
||||
MESSAGES[id] = str
|
||||
if id.count('%s') == str.count('%s'):
|
||||
MESSAGES[id] = str
|
||||
else:
|
||||
print 'WARNING: %s mismatch, skipping!'
|
||||
print ' %s' % id
|
||||
print ' %s' % str
|
||||
|
||||
|
||||
|
||||
|
||||