Example #1
0
 def count_subfolders_and_files(self):
     if self.dir:
         self.subdircount = 0
         self.subfilescount = 0
         fullpath = CherryModel.abspath(self.path)
         if not os.path.isdir(fullpath):
             # not a dir, or not even there: fail gracefully.
             # There are 0 subfolders and 0 files by default.
             log.error(
                 "MusicEntry does not exist: %r", self.path)
             return
         try:
             directory_listing = os.listdir(fullpath)
         except OSError as e:
             log.e(_('Error listing directory %s: %s') % (fullpath, str(e)))
             directory_listing = []
         for idx, filename in enumerate(directory_listing):
             if idx > MusicEntry.MAX_SUB_FILES_ITER_COUNT:
                 # estimate remaining file count
                 self.subfilescount *= len(directory_listing)/float(idx+1)
                 self.subfilescount = int(self.subfilescount)
                 self.subdircount *= len(directory_listing)/float(idx+1)
                 self.subdircount = int(self.subdircount)
                 self.subfilesestimate = True
                 return
             subfilefullpath = os.path.join(fullpath, filename)
             if os.path.isfile(subfilefullpath):
                 if CherryModel.isplayable(subfilefullpath):
                     self.subfilescount += 1
             else:
                 self.subdircount += 1
Example #2
0
def delete_user(username):
    userservice = service.get('users')
    userid = userservice.getIdByName(username)
    if userid is None:
        log.e(_('user with the name "%s" does not exist!'), username)
        return False
    return userservice.deleteUser(userid)
Example #3
0
 def addUser(self, username, password, admin):
     if not (username.strip() or password.strip()):
         log.d(_('empty username or password!'))
         return False
     user = User.create(username, password, admin)
     try:
         exists = self.conn.execute(
             'SELECT username'
             ' FROM users WHERE lower(username) = lower(?)',
             (username, )).fetchone()
         if (not exists):
             self.conn.execute(
                 '''
             INSERT INTO users
             (username, admin, password, salt)
             VALUES (?,?,?,?)''', (user.name, 1 if user.isadmin else 0,
                                   user.password, user.salt))
         else:
             raise sqlite3.IntegrityError
     except sqlite3.IntegrityError:
         log.e('cannot create user "%s", already exists!' % user.name)
         return False
     self.conn.commit()
     log.i('added user: ' + user.name)
     return True
Example #4
0
 def __init__(self, method="amazon", timeout=10):
     """define the urls of the services and a regex to fetch images
     """
     self.MAX_IMAGE_SIZE_BYTES = 100 * 1024
     self.IMAGE_SIZE = 80
     # the GET parameter value of the searchterm must be appendable
     # to the urls defined in "methods".
     self.methods = {
         "amazon": {
             "url": "http://www.amazon.com/s/ref=sr_nr_i_0?rh=k:",
             "regexes": ['<img  src="([^"]*)" class="productImage"', '<img.+?src="([^"]*)" class="productImage"'],
         },
         "bestbuy.com": {
             "url": "http://www.bestbuy.com/site/searchpage.jsp?_dyncharset=ISO-8859-1&id=pcat17071&type=page&ks=960&sc=Global&cp=1&sp=&qp=crootcategoryid%23%23-1%23%23-1~~q6a616d657320626c616b65206a616d657320626c616b65~~nccat02001%23%230%23%23e&list=y&usc=All+Categories&nrp=15&iht=n&st=",
             "regexes": ['<img itemprop="image" class="thumb" src="([^"]*)"'],
         },
         "buy.com": {
             "url": "http://www.buy.com/sr/srajax.aspx?from=2&qu=",
             "regexes": [' class="productImageLink"><img src="([^"]*)"'],
         },
     }
     if not method in self.methods:
         log.e("unknown album art fetch method: %s, using default." % self.method)
         method = "amazon"
     self.method = method
     self.timeout = timeout
     self.imageMagickAvailable = self.programAvailable("convert")
Example #5
0
def create_user(username, password):
    """ Creates a non-admin user with given username and password """
    non_alnum = re.compile('[^a-z0-9]', re.IGNORECASE)
    if non_alnum.findall(username):
        log.e(_('usernames may only contain letters and digits'))
        return False
    return service.get('users').addUser(username, password, admin=False)
 def __init__(self, method='amazon', timeout=10):
     self.MAX_IMAGE_SIZE_BYTES = 100 * 1024
     self.IMAGE_SIZE = 80
     self.methods = {
         'amazon': {
             'url': "http://www.amazon.com/s/ref=sr_nr_i_0?rh=k:",
             'regex': '<img  src="([^"]*)" class="productImage"'
         },
         'music.ovi.com': {
             'url':
             'http://music.ovi.com/gb/en/pc/Search/?display=detail&text=',
             'regex': 'class="prod-sm"><img src="([^"]*)"',
             #improve image quality:
             'urltransformer':
             lambda x: x[:x.rindex('/')] + '/?w=200&q=100',
         },
         'bestbuy.com': {
             'url':
             'http://www.bestbuy.com/site/searchpage.jsp?_dyncharset=ISO-8859-1&id=pcat17071&type=page&ks=960&sc=Global&cp=1&sp=&qp=crootcategoryid%23%23-1%23%23-1~~q6a616d657320626c616b65206a616d657320626c616b65~~nccat02001%23%230%23%23e&list=y&usc=All+Categories&nrp=15&iht=n&st=',
             'regex': '<img itemprop="image" class="thumb" src="([^"]*)"'
         },
         'buy.com': {
             'url': "http://www.buy.com/sr/srajax.aspx?from=2&qu=",
             'regex': ' class="productImageLink"><img src="([^"]*)"'
         },
     }
     if not method in self.methods:
         log.e('unknown album art fetch method: %s, using default.' %
               self.method)
         method = 'amazon'
     self.method = method
     self.timeout = timeout
     self.imageMagickAvailable = self.programAvailable('convert')
Example #7
0
    def remove_recursive(self, fileobj, progress=None):
        '''recursively remove fileobj and all its children from the media db.'''


        if progress is None:
            log.i(
                  _('removing dead reference(s): %s "%s"'),
                  'directory' if fileobj.isdir else 'file',
                  fileobj.relpath,
                  )
            factory = None
            remove = lambda item: self.remove_file(item)
        else:
            def factory(new, pnt):
                if pnt is None:
                    return (new, None, progress)
                return (new, pnt, pnt[2].spawnchild('[-] ' + new.relpath))
            remove = lambda item: (self.remove_file(item[0]), item[2].tick())

        deld = 0
        try:
            with self.conn:
                for item in self.db_recursive_filelister(fileobj, factory):
                    remove(item)
                    deld += 1
        except Exception as e:
            log.e(_('error while removing dead reference(s): %s'), e)
            log.e(_('rolled back to safe state.'))
            return 0
        else:
            return deld
Example #8
0
def create_user(username, password):
    """ Creates a non-admin user with given username and password """
    non_alnum = re.compile('[^a-z0-9]', re.IGNORECASE)
    if non_alnum.findall(username):
        log.e(_('usernames may only contain letters and digits'))
        return False
    return service.get('users').addUser(username, password, admin=False)
Example #9
0
    def listdir(self, dirpath, filterstr=''):
        absdirpath = CherryModel.abspath(dirpath)
        if cherry.config['browser.pure_database_lookup']:
            allfilesindir = self.cache.listdir(dirpath)     # NOT absdirpath!
        else:
            in_basedir = (os.path.normpath(absdirpath)+'/').startswith(
                cherry.config['media.basedir'])
            if not in_basedir:
                raise ValueError('dirpath not in basedir: %r' % dirpath)
            try:
                allfilesindir = os.listdir(absdirpath)
            except OSError as e:
                log.e(_('Error listing directory %s: %s') % (absdirpath, str(e)))
                allfilesindir = []

        #remove all files not inside the filter
        if filterstr:
            filterstr = filterstr.lower()
            allfilesindir = [f for f in allfilesindir
                             if f.lower().startswith(filterstr)]
        else:
            allfilesindir = [f for f in allfilesindir if not f.startswith('.')]

        musicentries = []

        maximum_shown_files = cherry.config['browser.maxshowfiles']
        compactlisting = len(allfilesindir) > maximum_shown_files
        if compactlisting:
            upper_case_files = [x.upper() for x in allfilesindir]
            filterstr = os.path.commonprefix(upper_case_files)
            filterlength = len(filterstr)+1
            currentletter = '/'  # impossible first character
            # don't care about natural number order in compact listing
            sortedfiles = self.sortFiles(allfilesindir, number_ordering=False)
            for dir in sortedfiles:
                filter_match = dir.upper().startswith(currentletter.upper())
                if filter_match and not len(currentletter) < filterlength:
                    continue
                else:
                    currentletter = dir[:filterlength]
                    #if the filter equals the foldername
                    if len(currentletter) == len(filterstr):
                        subpath = os.path.join(absdirpath, dir)
                        CherryModel.addMusicEntry(subpath, musicentries)
                    else:
                        musicentries.append(
                            MusicEntry(strippath(absdirpath),
                                       repr=currentletter,
                                       compact=True))
        else:
            # enable natural number ordering for real directories and files
            sortedfiles = self.sortFiles(allfilesindir, absdirpath,
                                         number_ordering=True)
            for dir in sortedfiles:
                subpath = os.path.join(absdirpath, dir)
                CherryModel.addMusicEntry(subpath, musicentries)
        if cherry.config['media.show_subfolder_count']:
            for musicentry in musicentries:
                musicentry.count_subfolders_and_files()
        return musicentries
Example #10
0
    def remove_recursive(self, fileobj, progress=None):
        '''recursively remove fileobj and all its children from the media db.'''


        if progress is None:
            log.i(
                  _('removing dead reference(s): %s "%s"'),
                  'directory' if fileobj.isdir else 'file',
                  fileobj.relpath,
                  )
            factory = None
            remove = lambda item: self.remove_file(item)
        else:
            def factory(new, pnt):
                if pnt is None:
                    return (new, None, progress)
                return (new, pnt, pnt[2].spawnchild('[-] ' + new.relpath))
            remove = lambda item: (self.remove_file(item[0]), item[2].tick())

        deld = 0
        try:
            with self.conn:
                for item in self.db_recursive_filelister(fileobj, factory):
                    remove(item)
                    deld += 1
        except Exception as e:
            log.e(_('error while removing dead reference(s): %s'), e)
            log.e(_('rolled back to safe state.'))
            return 0
        else:
            return deld
Example #11
0
    def update_db_recursive(self, fullpath, skipfirst=False):
        '''recursively update the media database for a path in basedir'''

        from collections import namedtuple
        Item = namedtuple('Item', 'infs indb parent progress')
        def factory(fs, db, parent):
            fileobj = fs if fs is not None else db
            name = fileobj.relpath or fileobj.fullpath if fileobj else '<path not found in filesystem or database>'
            if parent is None:
                progress = ProgressTree(name=name)
                maxlen = lambda s: util.trim_to_maxlen(50, s)
                progress.reporter = ProgressReporter(lvl=1, namefmt=maxlen)
            else:
                progress = parent.progress.spawnchild(name)
            return Item(fs, db, parent, progress)

        log.d(_('recursive update for %s'), fullpath)
        generator = self.enumerate_fs_with_db(fullpath, itemfactory=factory)
        skipfirst and generator.send(None)
        adds_without_commit = 0
        add = 0
        deld = 0
        try:
            with self.conn:
                for item in generator:
                    infs, indb, progress = (item.infs, item.indb, item.progress)
                    if infs and indb:
                        if infs.isdir != indb.isdir:
                            progress.name = '[±] ' + progress.name
                            deld += self.remove_recursive(indb, progress)
                            self.register_file_with_db(infs)
                            adds_without_commit = 1
                        else:
                            infs.uid = indb.uid
                            progress.name = '[=] ' + progress.name
                    elif indb:
                        progress.name = '[-] ' + progress.name
                        deld += self.remove_recursive(indb, progress)
                        adds_without_commit = 0
                        continue    # progress ticked by remove; don't tick again
                    elif infs:
                        self.register_file_with_db(item.infs)
                        adds_without_commit += 1
                        progress.name = '[+] ' + progress.name
                    else:
                        progress.name = '[?] ' + progress.name
                    if adds_without_commit == AUTOSAVEINTERVAL:
                        self.conn.commit()
                        add += adds_without_commit
                        adds_without_commit = 0
                    progress.tick()
        except Exception as exc:
            log.e(_("error while updating media: %s %s"), exc.__class__.__name__, exc)
            log.e(_("rollback to previous commit."))
            traceback.print_exc()
            raise exc
        finally:
            add += adds_without_commit
            log.i(_('items added %d, removed %d'), add, deld)
            self.load_db_to_memory()
Example #12
0
 def count_subfolders_and_files(self):
     if self.dir:
         self.subdircount = 0
         self.subfilescount = 0
         fullpath = CherryModel.abspath(self.path)
         if not os.path.isdir(fullpath):
             # not a dir, or not even there: fail gracefully.
             # There are 0 subfolders and 0 files by default.
             log.error("MusicEntry does not exist: %r", self.path)
             return
         try:
             directory_listing = os.listdir(fullpath)
         except OSError as e:
             log.e(_('Error listing directory %s: %s') % (fullpath, str(e)))
             directory_listing = []
         for idx, filename in enumerate(directory_listing):
             if idx > MusicEntry.MAX_SUB_FILES_ITER_COUNT:
                 # estimate remaining file count
                 self.subfilescount *= len(directory_listing) / float(idx +
                                                                      1)
                 self.subfilescount = int(self.subfilescount)
                 self.subdircount *= len(directory_listing) / float(idx + 1)
                 self.subdircount = int(self.subdircount)
                 self.subfilesestimate = True
                 return
             subfilefullpath = os.path.join(fullpath, filename)
             if os.path.isfile(subfilefullpath):
                 if CherryModel.isplayable(subfilefullpath):
                     self.subfilescount += 1
             else:
                 self.subdircount += 1
Example #13
0
 def __init__(self,method='amazon', timeout=10):
     self.methods = {
         'amazon' : {
             'url' : "http://www.amazon.com/s/ref=sr_nr_i_0?rh=k:",
             'regex' : '<img  src="([^"]*)" class="productImage"'
         },
         'music.ovi.com' : {
             'url' : 'http://music.ovi.com/gb/en/pc/Search/?display=detail&text=',
             'regex': 'class="prod-sm"><img src="([^"]*)"',
             #improve image quality:
             'urltransformer' : lambda x : x[:x.rindex('/')]+'/?w=200&q=100',
         },
         'bestbuy.com':{
             'url' : 'http://www.bestbuy.com/site/searchpage.jsp?_dyncharset=ISO-8859-1&id=pcat17071&type=page&ks=960&sc=Global&cp=1&sp=&qp=crootcategoryid%23%23-1%23%23-1~~q6a616d657320626c616b65206a616d657320626c616b65~~nccat02001%23%230%23%23e&list=y&usc=All+Categories&nrp=15&iht=n&st=',
             'regex' : '<img itemprop="image" class="thumb" src="([^"]*)"'
         },
         'buy.com' : {
             'url' : "http://www.buy.com/sr/srajax.aspx?from=2&qu=",
             'regex' : ' class="productImageLink"><img src="([^"]*)"'
         },
     }
     if not method in self.methods:
         log.e('unknown album art fetch method: %s, using default.'%self.method)
         method = 'amazon'
     self.method = method
     self.timeout = timeout
Example #14
0
 def _unicode_listdir(dirname):
     for name in os.listdir(dirname):
         try:
             yield (name if is_unicode(name) else decode(name, encoding))
         except UnicodeError:
             log.e(_('unable to decode filename %r in %r; skipping.'),
                 name, dirname)
Example #15
0
 def _unicode_listdir(dirname):
     for name in os.listdir(dirname):
         try:
             yield (name if is_unicode(name) else decode(name, encoding))
         except UnicodeError:
             log.e(_('unable to decode filename %r in %r; skipping.'),
                 name, dirname)
Example #16
0
def delete_user(username):
    userservice = service.get('users')
    userid = userservice.getIdByName(username)
    if userid is None:
        log.e(_('user with the name "%s" does not exist!'), username)
        return False
    return userservice.deleteUser(userid)
Example #17
0
    def update_db_recursive(self, fullpath, skipfirst=False):
        '''recursively update the media database for a path in basedir'''

        from collections import namedtuple
        Item = namedtuple('Item', 'infs indb parent progress')
        def factory(fs, db, parent):
            fileobj = fs if fs is not None else db
            name = fileobj.relpath or fileobj.fullpath if fileobj else '<path not found in filesystem or database>'
            if parent is None:
                progress = ProgressTree(name=name)
                maxlen = lambda s: util.trim_to_maxlen(50, s)
                progress.reporter = ProgressReporter(lvl=1, namefmt=maxlen)
            else:
                progress = parent.progress.spawnchild(name)
            return Item(fs, db, parent, progress)

        log.d(_('recursive update for %s'), fullpath)
        generator = self.enumerate_fs_with_db(fullpath, itemfactory=factory)
        skipfirst and generator.send(None)
        adds_without_commit = 0
        add = 0
        deld = 0
        try:
            with self.conn:
                for item in generator:
                    infs, indb, progress = (item.infs, item.indb, item.progress)
                    if infs and indb:
                        if infs.isdir != indb.isdir:
                            progress.name = '[±] ' + progress.name
                            deld += self.remove_recursive(indb, progress)
                            self.register_file_with_db(infs)
                            adds_without_commit = 1
                        else:
                            infs.uid = indb.uid
                            progress.name = '[=] ' + progress.name
                    elif indb:
                        progress.name = '[-] ' + progress.name
                        deld += self.remove_recursive(indb, progress)
                        adds_without_commit = 0
                        continue    # progress ticked by remove; don't tick again
                    elif infs:
                        self.register_file_with_db(item.infs)
                        adds_without_commit += 1
                        progress.name = '[+] ' + progress.name
                    else:
                        progress.name = '[?] ' + progress.name
                    if adds_without_commit == AUTOSAVEINTERVAL:
                        self.conn.commit()
                        add += adds_without_commit
                        adds_without_commit = 0
                    progress.tick()
        except Exception as exc:
            log.e(_("error while updating media: %s %s"), exc.__class__.__name__, exc)
            log.e(_("rollback to previous commit."))
            traceback.print_exc()
            raise exc
        finally:
            add += adds_without_commit
            log.i(_('items added %d, removed %d'), add, deld)
            self.load_db_to_memory()
Example #18
0
 def listdir(self, path):
     basedir = cherry.config['media.basedir']
     targetpath = os.path.join(basedir, path)
     targetdir = self.db_find_file_by_path(targetpath)
     if targetdir is None:
         log.e(_('media cache cannot listdir %r: path not in database'), path)
         return []
     return [f.basename for f in self.fetch_child_files(targetdir)]
Example #19
0
 def register_file_with_db(self, fileobj):
     """add data in File object to relevant tables in media database"""
     try:
         self.add_to_file_table(fileobj)
         word_ids = self.add_to_dictionary_table(fileobj.name)
         self.add_to_search_table(fileobj.uid, word_ids)
     except UnicodeEncodeError as e:
         log.e("wrong encoding for filename '%s' (%s)", fileobj.relpath, e.__class__.__name__)
Example #20
0
 def listdir(self, path):
     basedir = cherry.config['media.basedir']
     targetpath = os.path.join(basedir, path)
     targetdir = self.db_find_file_by_path(targetpath)
     if targetdir is None:
         log.e(_('media cache cannot listdir %r: path not in database'), path)
         return []
     return list(map(lambda f: f.basename, self.fetch_child_files(targetdir)))
Example #21
0
 def register_file_with_db(self, fileobj):
     """add data in File object to relevant tables in media database"""
     try:
         self.add_to_file_table(fileobj)
         word_ids = self.add_to_dictionary_table(fileobj.name)
         self.add_to_search_table(fileobj.uid, word_ids)
         return fileobj
     except UnicodeEncodeError as e:
         log.e(_("wrong encoding for filename '%s' (%s)"), fileobj.relpath, e.__class__.__name__)
Example #22
0
 def check_for_updates(self):
     try:
         url = 'http://fomori.org/cherrymusic/update_check.php?version='
         url += cherry.__version__
         urlhandler = urllib.request.urlopen(url, timeout=5)
         jsondata = codecs.decode(urlhandler.read(), 'UTF-8')
         versioninfo = json.loads(jsondata)
         return versioninfo
     except Exception as e:
         log.e(_('Error fetching version info: %s') % str(e))
         return []
Example #23
0
 def check_for_updates(self):
     try:
         url = 'http://fomori.org/cherrymusic/update_check.php?version='
         url += cherry.__version__
         urlhandler = urllib.request.urlopen(url, timeout=5)
         jsondata = codecs.decode(urlhandler.read(), 'UTF-8')
         versioninfo = json.loads(jsondata)
         return versioninfo
     except Exception as e:
         log.e(_('Error fetching version info: %s') % str(e))
         return []
Example #24
0
 def __init__(self, method="amazon", timeout=10):
     """define the urls of the services and a regex to fetch images
     """
     self.MAX_IMAGE_SIZE_BYTES = 100 * 1024
     self.IMAGE_SIZE = 80
     # the GET parameter value of the searchterm must be appendable
     # to the urls defined in "methods".
     if not method in self.methods:
         log.e(_(("""unknown album art fetch method: '%(method)s', """ """using default.""")), {"method": method})
         method = "google"
     self.method = method
     self.timeout = timeout
Example #25
0
    def full_update(self):
        '''verify complete media database against the filesystem and make
        necesary changes.'''

        log.i(_('running full update...'))
        try:
            self.update_db_recursive(cherry.config['media.basedir'], skipfirst=True)
        except:
            log.e(_('error during media update. database update incomplete.'))
        finally:
            self.update_word_occurrences()
            log.i(_('media database update complete.'))
Example #26
0
    def full_update(self):
        """verify complete media database against the filesystem and make
        necesary changes."""

        log.i("running full update...")
        try:
            self.update_db_recursive(cherry.config["media.basedir"], skipfirst=True)
        except:
            log.e("error during media update. database update incomplete.")
        finally:
            self.update_word_occurrences()
            log.i("media database update complete.")
Example #27
0
    def full_update(self):
        '''verify complete media database against the filesystem and make
        necesary changes.'''

        log.i(_('running full update...'))
        try:
            self.update_db_recursive(cherry.config['media.basedir'], skipfirst=True)
        except:
            log.e(_('error during media update. database update incomplete.'))
        finally:
            self.update_word_occurrences()
            log.i(_('media database update complete.'))
Example #28
0
 def children(self, sort=True, reverse=True):
     '''If self.isdir and self.exists, return an iterable of fileobjects
     corresponding to its direct content (non-recursive).
     Otherwise, log an error and return ().
     '''
     try:
         content = _unicode_listdir(self.fullpath)
         if sort:
             content = sorted(content, reverse=reverse)
         return (File(name, parent=self) for name in content)
     except OSError as error:
         log.e(_('cannot list directory: %s'), error)
         return ()
Example #29
0
 def remove_file(self, fileobj):
     '''removes a file entry from the db, which means removing:
         - all search references,
         - all dictionary words which were orphaned by this,
         - the reference in the files table.'''
     try:
         dead_wordids = self.remove_from_search(fileobj.uid)
         self.remove_all_from_dictionary(dead_wordids)
         self.remove_from_files(fileobj.uid)
     except Exception as exception:
         log.ex(exception)
         log.e(_('error removing entry for %s'), fileobj.relpath)
         raise exception
Example #30
0
 def children(self, sort=True, reverse=True):
     '''If self.isdir and self.exists, return an iterable of fileobjects
     corresponding to its direct content (non-recursive).
     Otherwise, log an error and return ().
     '''
     try:
         content = _unicode_listdir(self.fullpath)
         if sort:
             content = sorted(content, reverse=reverse)
         return (File(name, parent=self) for name in content)
     except OSError as error:
         log.e(_('cannot list directory: %s'), error)
         return ()
Example #31
0
 def _runscript(self, version, name, cxn):
     try:
         cxn.executescript(self.desc[version][name])
     except sqlite3.OperationalError:
         # update scripts are tested, so the problem's seems to be sqlite
         # itself
         log.x(_('Exception while updating database schema.'))
         log.e(_('Database error. This is probably due to your version of'
                 ' sqlite being too old. Try updating sqlite3 and'
                 ' updating python. If the problem persists, you will need'
                 ' to delete the database at ' + self.db.dblocation))
         import sys
         sys.exit(1)
Example #32
0
 def remove_file(self, fileobj):
     '''removes a file entry from the db, which means removing:
         - all search references,
         - all dictionary words which were orphaned by this,
         - the reference in the files table.'''
     try:
         dead_wordids = self.remove_from_search(fileobj.uid)
         self.remove_all_from_dictionary(dead_wordids)
         self.remove_from_files(fileobj.uid)
     except Exception as exception:
         log.ex(exception)
         log.e(_('error removing entry for %s'), fileobj.relpath)
         raise exception
Example #33
0
 def inputfilter(cls, files_iter):
     basedir = cherry.config['media.basedir']
     for f in files_iter:
         if not f.exists:
             log.e(_('file not found: %s. skipping.' % f.fullpath))
             continue
         if not f.fullpath.startswith(basedir):
             log.e(_('file not in basedir: %s. skipping.') % f.fullpath)
             continue
         if f.islink:
             rp = os.path.realpath(f.fullpath)
             if os.path.abspath(basedir).startswith(rp) \
                 or (os.path.islink(basedir)
                     and
                     os.path.realpath(basedir).startswith(rp)):
                 log.e(_(("Cyclic symlink found: %s creates a circle "
                          "if followed. Skipping.")) % f.relpath)
                 continue
             if not (f.parent is None or f.parent.parent is None):
                 log.e(_(("Deeply nested symlink found: %s . All links "
                       "must be directly in your basedir (%s). The "
                       "program cannot safely handle them otherwise."
                       " Skipping.")) % (f.relpath, os.path.abspath(basedir)))
                 continue
         yield f
 def __init__(self, method='amazon', timeout=10):
     """define the urls of the services and a regex to fetch images
     """
     self.MAX_IMAGE_SIZE_BYTES = 100*1024
     self.IMAGE_SIZE = 80
     # the GET parameter value of the searchterm must be appendable
     # to the urls defined in "methods".
     if not method in self.methods:
         log.e(_('''unknown album art fetch method: '%(method)s', using default.'''),
               {'method': method})
         method = 'amazon'
     self.method = method
     self.timeout = timeout
     self.imageMagickAvailable = self.programAvailable('convert')
Example #35
0
    def full_update(self):
        '''verify complete media database against the filesystem and make
        necesary changes.'''

        log.i('running full update...')

        try:
            self.update_db_recursive(cherry.config.media.basedir.str, skipfirst=True)
        except:
            log.e('error during media update. database update incomplete.')
        finally:
            self.__create_index_if_non_exist()
            self.update_word_occurences()
            log.i('media database update complete.')
Example #36
0
 def inputfilter(cls, files_iter):
     basedir = cherry.config['media.basedir']
     for f in files_iter:
         if not f.exists:
             log.e('file not found: ' + f.fullpath + ' . skipping.')
             continue
         if not f.fullpath.startswith(basedir):
             log.e('file not in basedir: ' + f.fullpath + ' . skipping.')
             continue
         if f.islink:
             rp = os.path.realpath(f.fullpath)
             if os.path.abspath(basedir).startswith(rp) \
                 or (os.path.islink(basedir)
                     and
                     os.path.realpath(basedir).startswith(rp)):
                 log.e("Cyclic symlink found: " + f.relpath +
                       " creates a circle if followed. Skipping.")
                 continue
             if not (f.parent is None or f.parent.parent is None):
                 log.e("Deeply nested symlink found: " + f.relpath +
                       " All links must be directly in your basedir (" +
                       os.path.abspath(basedir) + "). The program cannot"
                       " safely handle them otherwise. Skipping.")
                 continue
         yield f
Example #37
0
 def inputfilter(cls, files_iter):
     basedir = cherry.config['media.basedir']
     for f in files_iter:
         if not f.exists:
             log.e('file not found: ' + f.fullpath + ' . skipping.')
             continue
         if not f.fullpath.startswith(basedir):
             log.e('file not in basedir: ' + f.fullpath + ' . skipping.')
             continue
         if f.islink:
             rp = os.path.realpath(f.fullpath)
             if os.path.abspath(basedir).startswith(rp) \
                 or (os.path.islink(basedir)
                     and
                     os.path.realpath(basedir).startswith(rp)):
                 log.e("Cyclic symlink found: " + f.relpath +
                       " creates a circle if followed. Skipping.")
                 continue
             if not (f.parent is None or f.parent.parent is None):
                 log.e("Deeply nested symlink found: " + f.relpath +
                       " All links must be directly in your basedir (" +
                       os.path.abspath(basedir) + "). The program cannot"
                       " safely handle them otherwise. Skipping.")
                 continue
         yield f
Example #38
0
    def changePassword(self, username, newpassword):
        if not newpassword.strip():
            return _("not a valid password")
        if self.getIdByName(username) is None:
            msg = 'cannot change password: "******" does not exist!' % username
            log.e(msg)
            return msg

        newuser = User.create(username, newpassword, False) #dummy user for salt
        self.conn.execute('''
        UPDATE users SET password = ?, salt = ? WHERE username = ?
        ''', (newuser.password, newuser.salt, newuser.name) )
        self.conn.commit()
        return "success"
Example #39
0
 def inputfilter(cls, files_iter):
     basedir = cherry.config['media.basedir']
     for f in files_iter:
         if not f.exists:
             log.e(_('file not found: %s. skipping.' % f.fullpath))
             continue
         if not f.fullpath.startswith(basedir):
             log.e(_('file not in basedir: %s. skipping.') % f.fullpath)
             continue
         if f.islink and not os.path.isfile(f.fullpath):
             rp = os.path.realpath(f.fullpath)
             if os.path.abspath(basedir).startswith(rp) \
                 or (os.path.islink(basedir)
                     and
                     os.path.realpath(basedir).startswith(rp)):
                 log.e(_(("Cyclic symlink found: %s creates a circle "
                          "if followed. Skipping.")) % f.relpath)
                 continue
             if not (f.parent is None or f.parent.parent is None):
                 log.e(_(("Deeply nested directory symlink found: %s . "
                       "All symlinks to directories "
                       "must be directly in your basedir (%s). The "
                       "program cannot safely handle them otherwise."
                       " Skipping.")) % (f.relpath, os.path.abspath(basedir)))
                 continue
         yield f
Example #40
0
 def __init__(self, method='amazon', timeout=10):
     """define the urls of the services and a regex to fetch images
     """
     self.MAX_IMAGE_SIZE_BYTES = 100 * 1024
     self.IMAGE_SIZE = 80
     # the GET parameter value of the searchterm must be appendable
     # to the urls defined in "methods".
     if not method in self.methods:
         log.e(
             _(('''unknown album art fetch method: '%(method)s', '''
                '''using default.''')), {'method': method})
         method = 'google'
     self.method = method
     self.timeout = timeout
Example #41
0
    def changePassword(self, username, newpassword):
        if not newpassword.strip():
            return _("not a valid password")
        if self.getIdByName(username) is None:
            msg = 'cannot change password: "******" does not exist!' % username
            log.e(msg)
            return msg

        newuser = User.create(username, newpassword,
                              False)  #dummy user for salt
        self.conn.execute(
            '''
        UPDATE users SET password = ?, salt = ? WHERE lower(username) = lower(?)
        ''', (newuser.password, newuser.salt, newuser.name))
        self.conn.commit()
        return "success"
Example #42
0
 def addUser(self, username, password, admin):
     if not (username.strip() or password.strip()):
         log.d(_('empty username or password!'))
         return False
     user = User.create(username, password, admin)
     try:
         self.conn.execute('''
         INSERT INTO users
         (username, admin, password, salt)
         VALUES (?,?,?,?)''',
         (user.name, 1 if user.isadmin else 0, user.password, user.salt))
     except sqlite3.IntegrityError:
         log.e('cannot create user "%s", already exists!' % user.name)
         return False
     self.conn.commit()
     log.i('added user: ' + user.name)
     return True
Example #43
0
 def api_downloadcheck(self, filelist):
     status = self.download_check_files(filelist)
     if status == 'not_permitted':
         return """You are not allowed to download files."""
     elif status == 'invalid_file':
         return """Error: File has invalid filename""" % f
     elif status == 'too_big':
         size_limit = cherry.config['media.maximum_download_size']
         return """Can't download: Playlist is bigger than %s mB.
         The server administrator can change this configuration.
         """ % (size_limit/1024/1024)
     elif status == 'ok':
         return status
     else:
         message = "Error status check for download: '%s'" % status
         log.e(message)
         return message
Example #44
0
 def api_downloadcheck(self, filelist):
     status = self.download_check_files(filelist)
     if status == 'not_permitted':
         return """You are not allowed to download files."""
     elif status == 'invalid_file':
         return "Error: invalid filename found in {list}".format(list=filelist)
     elif status == 'too_big':
         size_limit = cherry.config['media.maximum_download_size']
         return """Can't download: Playlist is bigger than {maxsize} mB.
                     The server administrator can change this configuration.
                     """.format(maxsize=size_limit/1024/1024)
     elif status == 'ok':
         return status
     else:
         message = "Error status check for download: {status!r}".format(status=status)
         log.e(message)
         return message
Example #45
0
 def api_downloadcheck(self, filelist):
     status = self.download_check_files(filelist)
     if status == 'not_permitted':
         return """You are not allowed to download files."""
     elif status == 'invalid_file':
         return "Error: invalid filename found in {list}".format(list=filelist)
     elif status == 'too_big':
         size_limit = cherry.config['media.maximum_download_size']
         return """Can't download: Playlist is bigger than {maxsize} mB.
                     The server administrator can change this configuration.
                     """.format(maxsize=size_limit/1024/1024)
     elif status == 'ok':
         return status
     else:
         message = "Error status check for download: {status!r}".format(status=status)
         log.e(message)
         return message
Example #46
0
 def partial_update(self, path, *paths):
     basedir = cherry.config['media.basedir']
     paths = (path,) + paths
     log.i(_('updating paths: %s') % (paths,))
     for path in paths:
         path = os.path.normcase(path)
         abspath = path if os.path.isabs(path) else os.path.join(basedir, path)
         normpath = os.path.normpath(abspath)
         if not normpath.startswith(basedir):
             log.e(_('path is not in basedir. skipping %r') % abspath)
             continue
         log.i(_('updating %r...') % path)
         try:
             self.update_db_recursive(normpath, skipfirst=False)
         except Exception as exception:
             log.e(_('update incomplete: %r'), exception)
     self.update_word_occurrences()
     log.i(_('done updating paths.'))
Example #47
0
 def addUser(self, username, password, admin):
     if not (username.strip() or password.strip()):
         log.d(_('empty username or password!'))
         return False
     user = User.create(username, password, admin)
     try:
         self.conn.execute(
             '''
         INSERT INTO users
         (username, admin, password, salt)
         VALUES (?,?,?,?)''', (user.name, 1 if user.isadmin else 0,
                               user.password, user.salt))
     except sqlite3.IntegrityError:
         log.e('cannot create user "%s", already exists!' % user.name)
         return False
     self.conn.commit()
     log.d('added user: ' + user.name)
     return True
Example #48
0
 def partial_update(self, path, *paths):
     basedir = cherry.config['media.basedir']
     paths = (path,) + paths
     log.i(_('updating paths: %s') % (paths,))
     for path in paths:
         path = os.path.normcase(path)
         abspath = path if os.path.isabs(path) else os.path.join(basedir, path)
         normpath = os.path.normpath(abspath)
         if not normpath.startswith(basedir):
             log.e(_('path is not in basedir. skipping %r') % abspath)
             continue
         log.i(_('updating %r...') % path)
         try:
             self.update_db_recursive(normpath, skipfirst=False)
         except Exception as exception:
             log.e(_('update incomplete: %r'), exception)
     self.update_word_occurrences()
     log.i(_('done updating paths.'))
Example #49
0
def getSongInfo(filepath):
    if has_stagger:
        try:
            tag = stagger.read_tag(filepath)
        except Exception:
            tag = MockTag()
    else:
        tag = MockTag()
            
    if has_audioread:
        try:
            with audioread.audio_open(filepath) as f:
                audiolength = f.duration
        except Exception:
            log.e('audioread failed! (%s)', filepath)
            audiolength = 0
    else:
        audiolength = 0
    return Metainfo(tag.artist, tag.album, tag.title, tag.track, audiolength)
Example #50
0
def getSongInfo(filepath):
    if has_stagger:
        try:
            tag = stagger.read_tag(filepath)
        except Exception:
            tag = MockTag()
    else:
        tag = MockTag()

    if has_audioread:
        try:
            with audioread.audio_open(filepath) as f:
                audiolength = f.duration
        except Exception:
            log.e('audioread failed! (%s)', filepath)
            audiolength = 0
    else:
        audiolength = 0
    return Metainfo(tag.artist, tag.album, tag.title, tag.track, audiolength)
Example #51
0
    def listdir(self, dirpath, filterstr=''):
        if dirpath is None:
            absdirpath = cherry.config['media.basedir']
        else:
            absdirpath = CherryModel.abspath(dirpath)

        if cherry.config['browser.pure_database_lookup']:
            allfilesindir = self.cache.listdir(dirpath)  # NOT absdirpath!
        else:
            in_basedir = (os.path.normpath(absdirpath) + '/').startswith(
                cherry.config['media.basedir'])
            if not in_basedir:
                raise ValueError('dirpath not in basedir: %r' % dirpath)
            try:
                allfilesindir = os.listdir(absdirpath)
            except OSError as e:
                log.e(
                    _('Error listing directory %s: %s') % (absdirpath, str(e)))
                allfilesindir = []

        #remove all files not inside the filter
        if filterstr:
            filterstr = filterstr.lower()
            allfilesindir = [
                f for f in allfilesindir if f.lower().startswith(filterstr)
            ]
        else:
            allfilesindir = [f for f in allfilesindir if not f.startswith('.')]

        musicentries = []

        maximum_shown_files = cherry.config['browser.maxshowfiles']
        compactlisting = len(allfilesindir) > maximum_shown_files
        if compactlisting:
            upper_case_files = [x.upper() for x in allfilesindir]
            filterstr = os.path.commonprefix(upper_case_files)
            filterlength = len(filterstr) + 1
            currentletter = '/'  # impossible first character
            # don't care about natural number order in compact listing
            sortedfiles = self.sortFiles(allfilesindir, number_ordering=False)
            for dir in sortedfiles:
                filter_match = dir.upper().startswith(currentletter.upper())
                if filter_match and not len(currentletter) < filterlength:
                    continue
                else:
                    currentletter = dir[:filterlength]
                    #if the filter equals the foldername
                    if len(currentletter) == len(filterstr):
                        subpath = os.path.join(absdirpath, dir)
                        CherryModel.addMusicEntry(subpath, musicentries)
                    else:
                        musicentries.append(
                            MusicEntry(strippath(absdirpath),
                                       repr=currentletter,
                                       compact=True))
        else:
            # enable natural number ordering for real directories and files
            sortedfiles = self.sortFiles(allfilesindir,
                                         absdirpath,
                                         number_ordering=True)
            for dir in sortedfiles:
                subpath = os.path.join(absdirpath, dir)
                CherryModel.addMusicEntry(subpath, musicentries)
        if cherry.config['media.show_subfolder_count']:
            for musicentry in musicentries:
                musicentry.count_subfolders_and_files()
        return musicentries