Beispiel #1
0
    def get_files(self, ids, servers_known = False, bl = 0):
        '''
        Devuelve los datos de los ficheros correspondientes a los ids
        dados en formato hexadecimal.

        @param ids: Lista de identificadores de los ficheros a recuperar. Si server_known es False, es una lista de cadenas. Si server_known es True, es una lista de tuplas, que incluyen el identificador del fichero y el número de servidor.
        @param servers_known: Indica si la lista de identificadores incluye el servidor donde se encuentra el fichero.


        @type bl: int o None
        @param bl: valor de bl para buscar, None para no restringir

        @rtype generator
        @return Generador con los documentos de ficheros
        '''

        if len(ids) == 0: return ()

        sids = defaultdict(list)
        # si conoce los servidores en los que están los ficheros,
        # se analiza ids como un iterable (id, servidor, ...)
        # y evitamos buscar los servidores
        if servers_known:
            for x in ids:
                sids[x[1]].append(hex2mid(x[0]))
        else:
            # averigua en qué servidor está cada fichero
            nindir = self.server_conn.foofind.indir.find({"_id": {"$in": [hex2mid(fid) for fid in ids]}})
            for ind in nindir:
                if "t" in ind: # si apunta a otro id, lo busca en vez del id dado
                    sids[ind["s"]].append(ind["t"])
                else:
                    sids[ind["s"]].append(ind["_id"])
            self.server_conn.end_request()

        if len(sids) == 0: # Si no hay servidores, no hay ficheros
            return tuple()
        elif len(sids) == 1: # Si todos los ficheros pertenecen al mismo servidor, evita MultiAsync
            sid = sids.keys()[0]
            if not "conn" in self.servers_conn[sid]: return ()
            conn = self.servers_conn[sid]["conn"]
            return end_request(
                conn.foofind.foo.find(
                    {"_id":{"$in": sids[sid]}} if bl is None else
                    {"_id":{"$in": sids[sid]},"bl":bl}))

        # función que recupera ficheros
        def get_server_files(async, sid, ids):
            '''
                Recupera los datos de los ficheros con los ids dados del
                servidor mongo indicado por sid y los devuelve a través
                del objeto async.
            '''
            if not "conn" in self.servers_conn[sid]: return
            conn = self.servers_conn[sid]["conn"]

            async.return_value(end_request(conn.foofind.foo.find(
                {"_id": {"$in": ids}}
                if bl is None else
                {"_id": {"$in": ids},"bl":bl})))
Beispiel #2
0
    def update_file(self, data, remove=None, direct_connection=False, update_sphinx=True):
        '''
        Actualiza los datos del fichero dado.

        @type data: dict
        @param data: Diccionario con los datos del fichero a guardar. Se debe incluir '_id', y es recomendable incluir 's' por motivos de rendimiento.
        @type remove: iterable
        @param remove: Lista de campos a quitar del registro.
        @type direct_connection: bool
        @param direct_connection: Especifica si se crea una conexión directa, ineficiente e independiente al foo primario.
        @type update_sphinx: bool
        @param update_sphinx: si se especifica bl, de este parámetro depende el si se conecta al sphinx para actualizarlo
        '''
        update = {"$set":data.copy()}
        if remove is not None:
            update["$unset"] = {}
            for rem in remove:
                if rem in update["$set"]:
                    del update["$set"][rem]
                update["$unset"][rem] = 1

        fid = hex2mid(data["_id"])
        _indir = self.server_conn.foofind.indir.find_one({"_id": fid})
        if _indir and "t" in _indir:
            fid = hex2mid(_indir['t'])

        if "s" in data:
            server = str(data["s"])
        else:
            try:
                server = str(self.get_file(fid, bl=None)["s"])
            except (TypeError, KeyError) as e:
                logging.error("Se ha intentado actualizar un fichero que no se encuentra en la base de datos", extra=data)
                raise

        if update_sphinx and "bl" in data:
            try:
                file_name = i["fn"].itervalues().next()["n"]
            except:
                file_name = None
            block_files(mongo_ids=((i["_id"],file_name),), block=data["bl"])

        for i in ("_id", "s"):
            if i in update["$set"]:
                del update["$set"][i]

        # TODO: update cache
        self.servers_conn[server].foofind.foo.update({"_id":fid}, update)
Beispiel #3
0
    def get_file(self, fid, sid=None, bl=0):
        '''
        Obtiene un fichero del servidor

        @type fid: str
        @param fid: id de fichero en hexadecimal

        @type sid: str
        @param sid: id del servidor

        @type bl: int o None
        @param bl: valor de bl para buscar, None para no restringir

        @rtype mongodb document
        @return Documento del fichero
        '''
        mfid = hex2mid(fid)
        if sid is None:
            # averigua en qué servidor está el fichero
            ind = self.server_conn.foofind.indir.find_one({"_id":mfid})
            if ind is None: return None
            if "t" in ind: mfid = ind["t"]
            sid = ind["s"]
            self.server_conn.end_request()

        if not "conn" in self.servers_conn[sid]: return None
        conn = self.servers_conn[sid]["conn"]
        return end_request(conn.foofind.foo.find_one(
            {"_id":mfid} if bl is None else
            {"_id":mfid,"bl":bl}), conn)
Beispiel #4
0
def getserver(fileid, filename=None):
    '''
    Apaño porque Fer tarda mucho en arreglar indir
    '''
    # TODO(felipe): posibilidad de bloquear

    form = GetServerForm(request.form)

    data = None
    if request.method == 'POST':
        fname = form.filename.data
        sid = get_id_server_from_search(hex2mid(fileid), fname)
        if sid:
            try:
                data = filesdb.get_file(fileid, sid = sid, bl = None)

            except filesdb.BogusMongoException as e:
                logging.exception(e)
                flash(e, "error")
        else:
            flash("admin_file_search_server_not_found", "error")
    elif filename:
        form.filename.data = filename

    return render_template('admin/getserver.html',
        fileid = fileid,
        searchform = form,
        file_data = data
        )
Beispiel #5
0
    def update_user(self, data, remove=None):
        '''
        Actualiza los datos del usuario

        @param data: Diccionario con los datos del usuario a guardar.
        @param remove: Lista de campos a quitar del registro.
        '''
        update = {"$set":data.copy()}
        if "password" in data:
            update["$set"]["password"] = sha256(data["password"]).hexdigest()

        if remove is not None:
            update["$unset"]={}
            for rem in remove:
                del update["$set"][rem]
                update["$unset"][rem]=1

        del update["$set"]["_id"]

        parser = self._userParse
        update["$set"].update(
            (key, parser[key](value) if key in parser else parser["*"](value))
            for key, value in update["$set"].iteritems())

        self.user_conn.foofind.users.update({"_id":hex2mid(data["_id"])}, update)
        self.user_conn.end_request()
Beispiel #6
0
 def set_file_vote(self,file_id,user,lang,vote):
     '''
     Guarda el voto en la colección y actualiza el archivo correspondiente con los nuevos datos
     '''
     self.user_conn.foofind.vote.save({"_id":"%s_%s"%(file_id,user.id),"u":hex2mid(user.id),"k":user.karma if vote==1 else -user.karma,"d":datetime.utcnow(),"l":lang})
     #para cada idioma guarda el karma, la cuenta total y la suma
     map_function=Code('''
         function()
         {
             emit(this.l,{
                 k:this.k,
                 c:new Array((this.k>0)?1:0,(this.k<0)?1:0),
                 s:new Array((this.k>0)?this.k:0,(this.k<0)?this.k:0)
             })
         }''')
     #suma todo y aplica la funcion 1/1+E^(-X) para que el valor este entre 0 y 1
     reduce_function=Code('''
         function(lang, vals)
         {
             c=new Array(0,0);
             s=new Array(0,0);
             for (var i in vals)
             {
                 c[0]+=vals[i].c[0];
                 c[1]+=vals[i].c[1];
                 s[0]+=vals[i].s[0];
                 s[1]+=vals[i].s[1];
             }
             return {t:1/(1+Math.exp(-((s[0]*c[0]+s[1]*c[1])/(c[0]+c[1])))), c:c, s:s};
         }''')
     #tercer parametro para devolverlo en vez de generar una coleccion nueva
     votes=self.user_conn.foofind.vote.map_reduce(map_function,reduce_function,{"inline":1},query={'_id':{'$regex':"^%s"%file_id}})
     #devolver un diccionario de la forma idioma:valores
     return end_request({values["_id"]:values["value"] for values in votes["results"]}, self.user_conn)
Beispiel #7
0
 def get_file_comment_votes(self,file_id):
     '''
     Recuper los votos de los comentarios de un archivo
     '''
     cursor = self.user_conn.users.comment_vote.find({"f":hex2mid(file_id)})
     for document in cursor:
         yield cursor
     self.user_conn.end_request()
Beispiel #8
0
 def get_file_comments(self,file_id,lang):
     '''
     Recupera los comentarios de un archivo
     '''
     cursor = self.user_conn.users.comment.find({"f": hex2mid(file_id),"l": lang})
     for document in cursor:
         yield document
     self.user_conn.end_request()
Beispiel #9
0
    def remove_userid(self, userid):
        '''
        Borra un usuario con el userid dado

        @type userid: hex u ObjectID
        @param userid: identificador del usuario
        '''
        self.user_conn.foofind.users.remove({"_id":hex2mid(userid)})
Beispiel #10
0
    def get_complaint(self, hexid):
        '''
        Obtiene la información de un enlace reportado

        @type hexid: str
        @param hexid: cadena id de MongoDB en hexadecimal

        @rtype: MongoDB document or None
        @return: resultado
        '''
        return end_request(self.pages_conn.foofind.complaint.find_one({"_id":hex2mid(hexid)}), self.pages_conn)
Beispiel #11
0
 def get_file_comments_sum(self, file_id):
     '''
     Cuenta los comentarios que hay para cada idioma
     '''
     data = {
         lang["l"]: lang["c"]
         for lang in self.user_conn.users.comment.group(
             {"l": 1}, {'f': hex2mid(file_id)}, {"c": 0},
             Code("function(o,p){p.c++}"))
         }
     self.user_conn.end_request()
     return data
Beispiel #12
0
    def get_translation(self, hexid):
        '''
        Obtiene la información de una traducción

        @type hexid: str
        @param hexid: cadena id de MongoDB en hexadecimal

        @rtype: MongoDB document or None
        @return: resultado
        '''
        return end_request(
            self.pages_conn.foofind.translation.find_one({"_id":hex2mid(hexid)}),
            self.pages_conn)
Beispiel #13
0
    def update_translation(self, data, remove=None):
        '''
        Actualiza una traducción.

        @type data: dict
        @param data: datos
        '''
        update = {"$set":data.copy()}
        if remove is not None:
            update["$unset"]=dict()
            for rem in remove:
                del update["$set"][rem]
                update["$unset"][rem]=1

        del update["$set"]["_id"]
        self.pages_conn.users.translation.update({"_id":hex2mid(data["_id"])}, update)
        self.pages_conn.end_request()
Beispiel #14
0
    def update_complaint(self, data, remove=None):
        '''
        Actualiza una queja.

        @type data: dict
        @param data: datos
        '''
        update = {"$set":data.copy()}
        if remove is not None:
            update["$unset"]=dict()
            for rem in remove:
                del update["$set"][rem]
                update["$unset"][rem]=1

        del update["$set"]["_id"]
        self.pages_conn.foofind.complaint.update({"_id":hex2mid(data["_id"])}, update)
        self.pages_conn.end_request()
Beispiel #15
0
    def update_file(self, data, remove=None, direct_connection=False, update_sphinx=True):
        '''
        Actualiza los datos del fichero dado.

        @type data: dict
        @param data: Diccionario con los datos del fichero a guardar. Se debe incluir '_id', y es recomendable incluir 's' por motivos de rendimiento.
        @type remove: iterable
        @param remove: Lista de campos a quitar del registro.
        @type direct_connection: bool
        @param direct_connection: Especifica si se crea una conexión directa, ineficiente e independiente al foo primario.
        @type update_sphinx: bool
        @param update_sphinx: si se especifica bl, de este parámetro depende el si se conecta al sphinx para actualizarlo
        '''
        update = {"$set":data.copy()}
        if remove is not None:
            update["$unset"]=dict()
            for rem in remove:
                del update["$set"][rem]
                update["$unset"][rem]=1

        fid = hex2mid(data["_id"])

        if "s" in data:
            server = data["s"]
        else:
            try:
                server = self.get_file(fid, bl=None)["s"]
            except (TypeError, KeyError) as e:
                logging.error("Se ha intentado actualizar un fichero que no se encuentra en la base de datos", extra=data)
                raise

        if update_sphinx and "bl" in data:
            block_files(mongo_ids=(i["_id"],), block=data["bl"])

        for i in ("_id", "s"):
            if i in update["$set"]:
                del update["$set"][i]

        if direct_connection:
            # TODO: update cache
            with self.servers_conn[server].contextmaster as context:
                context.conn.foofind.foo.update({"_id":fid}, update)
                context.conn.end_request()
        else:
            #TODO(felipe): implementar usando el EventManager
            raise NotImplemented("No se ha implementado una forma eficiente de actualizar un foo")
Beispiel #16
0
    def update_file(self, data, remove=None, direct_connection=False, update_sphinx=True):
        '''
        Actualiza los datos del fichero dado.

        @type data: dict
        @param data: Diccionario con los datos del fichero a guardar. Se debe incluir '_id', y es recomendable incluir 's' por motivos de rendimiento.
        @type remove: iterable
        @param remove: Lista de campos a quitar del registro.
        @type direct_connection: bool
        @param direct_connection: Especifica si se crea una conexión directa, ineficiente e independiente al foo primario.
        @type update_sphinx: bool
        @param update_sphinx: si se especifica bl, de este parámetro depende el si se conecta al sphinx para actualizarlo
        '''

        update = {"$set":data.copy()}
        if remove is not None:
            update["$unset"]=dict()
            for rem in remove:
                del update["$set"][rem]
                update["$unset"][rem]=1

        fid = hex2mid(data["_id"])

        if "s" in data:
            server = data["s"]
        else:
            server = self.get_file(fid, bl=None)["s"]

        if update_sphinx and "bl" in data:
            block_files(mongo_ids=(i["_id"],), block=data["bl"])

        for i in ("_id", "s"):
            if i in update["$set"]:
                del update["$set"][i]

        if direct_connection:
            # TODO: update cache
            foocon = self.connect_foo(server,1)
            foocon.foofind.foo.update({"_id":fid}, update)
            foocon.end_request()
        else:
            raise NotImplemented("No se ha implementado una forma eficiente de actualizar un foo")
Beispiel #17
0
def lock_file(complaint_id=None):
    '''
    Información y bloqueo de ficheros, puede recibir un id de queja, o una lista de ids (en hex) de ficheros separados por la letra "g"
    '''
    page = request.args.get("page", 0, int)
    mode = request.args.get("show", "old", str)
    size = request.args.get("size", 15, int)

    filenames = {}
    bugged = []
    fileids = ()
    if request.method == 'POST':
        if not "fileids" in request.form:
            searchform = BlockFileSearchForm(request.form)
            identifiers = searchform.identifier.data.split()
            if searchform.mode.data == "hexid":
                fileids = [ mid2hex(hex2mid(i))
                    for i in identifiers
                    if all(x in "0123456789abcdef" for x in i)
                    ]
            elif searchform.mode.data == "b64id":
                fileids = [
                    mid2hex(url2mid(i))
                    for i in identifiers
                    if all(x in "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!-" for x in i)
                        and (len(i)*8)%6 == 0
                    ]
            elif searchform.mode.data == "url":
                filenames.update(
                    (
                        mid2hex(fileurl2mid(i)),
                        u".".join(urllib2.unquote(i.split("/")[-1]).split(".")[:-1])
                        )
                    for i in identifiers
                    if i.startswith("http") and len(i.split("//")[1].split("/")) > 3
                    )
                fileids = filenames.keys()
            if not fileids:
                return redirect(url_for('admin.locks', page=page, mode=mode, size=size))
        else:
            block = request.form.get("block", False, bool)
            unblock = request.form.get("unblock", False, bool)
            if block or unblock: # submit confirmar
                if complaint_id: pagesdb.update_complaint({"_id":complaint_id,"processed":True})
                fileids = dict(i.split(":") for i in request.form["fileids"].split(","))
                sphinx_block = []
                sphinx_unblock = []
                for fileid, server in fileids.iteritems():
                    (sphinx_block if block and not unblock else sphinx_unblock).append(fileid)
                    req = {"_id":fileid, "bl": int(block and not unblock)}
                    if server: req["s"] = int(server) # si recibo el servidor, lo uso por eficiencia
                    try:
                        # TODO(felipe): comprobar en qué casos se puede llegar aquí sin "s"
                        filesdb.update_file(req, direct_connection=True, update_sphinx=False)
                    except:
                        flash("No se ha podido actualizar el fichero con id %s" % fileid, "error")
                if sphinx_block:
                    block_files_in_sphinx(mongo_ids=sphinx_block, block=True)
                if sphinx_unblock:
                    block_files_in_sphinx(mongo_ids=sphinx_unblock, block=False)
                flash("admin_locks_locked" if block else "admin_locks_unlocked", "success")
            elif request.form.get("cancel", False, bool): # submit cancelar
                if complaint_id:
                    pagesdb.update_complaint({"_id":complaint_id,"processed":True})
                flash("admin_locks_not_locked", "success")
            return redirect(url_for('admin.locks', page=page, mode=mode, size=size))

    complaint_data = None # Hay un único o ningún registro de queja por formulario
    files_data = OrderedDict() # Pueden haber varios ficheros por formulario
    if complaint_id: # Si hay queja, sólo hay una url, la de la queja
        complaint_data = pagesdb.get_complaint(complaint_id)
        if complaint_data and "urlreported" in complaint_data:
            # extracción el id de complaint["urlreported"] de base64 a hexadecimal
            files_data[mid2hex(fileurl2mid(complaint_data["urlreported"]))] = None
    elif fileids: # Si no hay queja, los ficheros se sacan de la url
        files_data.update((i,None) for i in fileids)

    # Suponemos si queremos bloquear, desbloquear, o mostrar las dos opciones
    # dependiendo de sí de los ficheros están bloqueados o no
    # además rellenamos la información de los ficheros
    blocked = 0
    unblocked = 0
    for fileid in files_data.iterkeys():
        data = filesdb.get_file(fileid, bl=None)
        if data is None and fileid in filenames:
            bugged.append(fileid)
            sid = get_id_server_from_search(fileid, filenames[fileid])
            if sid:
                data = filesdb.get_file(fileid, sid = sid, bl = None)
        files_data[fileid] = data or {}
        if not "bl" in files_data[fileid] or files_data[fileid]["bl"] == 0: unblocked += 1
        else: blocked += 1

    return render_template('admin/lock_file.html',
        page_title=_('admin_locks_fileinfo'),
        complaint_data=complaint_data,
        files_data=files_data,
        filenames = filenames,
        bugged = bugged,
        fileids=",".join(
            "%s:%s" % (fileid, prop["s"] if "s" in prop else "")
            for fileid, prop in files_data.iteritems()),
        blocked=None if blocked and unblocked else blocked > 0,
        list_mode=mode,
        page=page,
        title=admin_title('admin_losfdcks_fileinfo'))
Beispiel #18
0
def choose_filename(f,text=False):
    '''
    Elige el archivo correcto
    '''
    text=slugify(text) if text else text
    srcs = f['file']['src']
    fns = f['file']['fn']
    chosen = None
    max_count = -1
    has_text = 0
    try:
        for hexuri,src in srcs.items():
            if 'bl' in src and src['bl']!=0:
                continue

            this_has_text=0
            for crc,srcfn in src['fn'].items():
                #si no tiene nombre no se tiene en cuenta
                m = srcfn['m'] if len(fns[crc]['n'])>0 else 0
                if 'c' in fns[crc]:
                    fns[crc]['c']+=m
                else:
                    fns[crc]['c']=m

                if text:
                    slugified_fn = slugify(fns[crc]['n']).strip()
                    if len(slugified_fn)>0:
                        #TODO hace lo mismo que para poner el nombre en negrita y sacar el mejor texto aunque no tenga tildes o no venga unido por espacios
                        if slugified_fn.upper().find(text.upper())!=-1:
                            this_has_text = 2000
                        else:
                            matches = 0
                            for word in [re.escape(w) for w in text.split(" ")]:
                                matches += len(re.findall(r"/((?:\b|_)%s(?:\b|_))/i"%word, slugified_fn))

                            if matches>0:
                                this_has_text = 1000 + matches

                f['file']['fn'][crc]['tht'] = this_has_text
                better = fns[crc]['c']>max_count
                if this_has_text > has_text or (better and this_has_text==has_text):
                    has_text = this_has_text
                    chosen = crc
                    max_count = fns[crc]['c']

    except KeyError as e: #para los sources que tienen nombre pero no estan en el archivo
        logging.exception(e)

    f['view']['url'] = mid2url(hex2mid(f['file']['_id']))
    if chosen:
        filename = fns[chosen]['n']
        ext = fns[chosen]['x']
    else: #uses filename from src
        srcurl = ""
        for hexuri,src in srcs.items():
            if src['url'].find("/")!=-1:
                srcurl = src['url']

        if srcurl=="":
            return

        srcurl = srcurl[srcurl.rfind("/")+1:]
        ext = srcurl[srcurl.rfind(".")+1:]
        filename = srcurl[0:srcurl.rfind(".")]

    filename = Markup(filename).striptags()[:512]
    if not ext in EXTENSIONS:
        filename += ext
        ext=""
        nfilename = filename
    else:
        #clean filename
        end = filename.upper().rfind("."+ext.upper())
        if end == -1:
            nfilename = filename
        else:
            nfilename = filename.strip()[0:end]

    f['view']['fn'] = filename #TODO para los tipo archive buscar el tipo real en el nombre (mp3,avi...)
    f['view']['fnx'] = ext
    f['view']['efn'] = filename.replace(" ", "%20")

    #poner bonito nombre del archivo
    if nfilename.find(" ")==-1:
        nfilename = nfilename.replace(".", " ")

    f['view']['nfn'] = nfilename.replace("_", " ")

    #nombre del archivo escapado para generar las url de descarga
    f['view']['qfn'] = u(filename).encode("UTF-8")

    #nombre del archivo con las palabras que coinciden con la busqueda resaltadas
    if not text:# or not has_text:
        f['view']['fnh'] = f['view']['fnhs'] = filename
    else:
        f['view']['fnh'], f['view']['fnhs'] = highlight(text,filename,True)

    return has_text>0
Beispiel #19
0
def choose_filename(f,text_cache=None):
    '''
    Elige el archivo correcto
    '''
    srcs = f['file']['src']
    fns = f['file']['fn']
    chosen = None
    max_count = -1
    current_weight = -1
    if text_cache and text_cache[0] in fns: # Si text es en realidad un ID de fn
        chosen = text_cache[0]
    else:
        for hexuri,src in srcs.items():
            if 'bl' in src and src['bl']!=0:
                continue

            for crc,srcfn in src['fn'].items():
                if crc not in fns: #para los sources que tienen nombre pero no estan en el archivo
                    continue

                #si no tiene nombre no se tiene en cuenta
                m = srcfn['m'] if len(fns[crc]['n'])>0 else 0
                if 'c' in fns[crc]:
                    fns[crc]['c']+=m
                else:
                    fns[crc]['c']=m

                text_weight = 0
                if text_cache:
                    fn_parts = slugify(fns[crc]['n']).strip().split(" ")

                    if len(fn_parts)>0:
                        text_words =  slugify(text_cache[0]).split(" ")

                        # valora numero y orden coincidencias
                        last_pos = -1
                        max_length = length = 0
                        occurrences = [0]*len(text_words)
                        for part in fn_parts:
                            pos = text_words.index(part) if part in text_words else -1
                            if pos != -1 and (last_pos==-1 or pos==last_pos+1):
                                length += 1
                            else:
                                if length > max_length: max_length = length
                                length = 0
                            if pos != -1:
                                occurrences[pos]=1
                            last_pos = pos
                        if length > max_length: max_length = length
                        text_weight = sum(occurrences)*100 + max_length

                f['file']['fn'][crc]['tht'] = text_weight
                better = fns[crc]['c']>max_count

                if text_weight > current_weight or (better and text_weight==current_weight):
                    current_weight = text_weight
                    chosen = crc
                    max_count = fns[crc]['c']

    f['view']['url'] = mid2url(hex2mid(f['file']['_id']))
    f['view']['fnid'] = chosen
    if chosen:
        filename = fns[chosen]['n']
        ext = fns[chosen]['x']
    else: #uses filename from src
        filename = ""
        for hexuri,src in srcs.items():
            if src['url'].find("/")!=-1:
                filename = src['url']

        if filename=="":
            return

        filename = filename[filename.rfind("/")+1:]
        ext = filename[filename.rfind(".")+1:]
        filename = filename[0:filename.rfind(".")]
        #TODO si no viene nombre de archivo buscar en los metadatos para formar uno (por ejemplo serie - titulo capitulo)

    filename = extension_filename(filename,ext)
    f['view']['fn'] = filename.replace("?", "")
    f['view']['qfn'] = qfn = u(filename).encode("UTF-8")  #nombre del archivo escapado para generar las url de descarga
    f['view']['pfn'] = urllib.quote(qfn).replace(" ", "%20")  # P2P filename

    nfilename = seoize_text(filename, " ",True, 0)
    f['view']['nfn'] = nfilename
    # añade el nombre del fichero como palabra clave
    g.keywords.update(set(keyword for keyword in nfilename.split(" ") if len(keyword)>1))

    #nombre del archivo con las palabras que coinciden con la busqueda resaltadas
    if text_cache:
        f['view']['fnh'], f['view']['fnhs'] = highlight(text_cache[2],filename,True)
    else:
        f['view']['fnh'] = filename #esto es solo para download que nunca tiene text

    return current_weight>0 # indica si ha encontrado el texto buscado
Beispiel #20
0
def choose_filename(f,text=False):
    '''
    Elige el archivo correcto
    '''
    srcs = f['file']['src']
    fns = f['file']['fn']
    hist= ""
    chosen=""
    maxCount = 0
    hasText = 0
    for hexuri,src in srcs.items():
        if 'bl' in src and src['bl']!=0:
            continue

        srcfns = src['fn']
        for crc,srcfn in srcfns.items():
            fnn = fns[crc]['n']
            if len(fnn.strip())==0:
                continue

            thisHasText=0
            if 'c' in fns[crc]:
                fns[crc]['c']+=srcfn['m']
            else:
                fns[crc]['c']=srcfn['m']

            if text:
                if fnn.upper().find(text.upper())!=-1:
                    thisHasText = 2000
                else:
                    matches = 0
                    for word in [re.escape(w) for w in text.split(" ")]:
                        matches += len(re.findall(r"/((?:\b|_)%s(?:\b|_))/i"%word, fnn))

                    if matches>0:
                        thisHasText = 1000 + matches

            f['file']['fn'][crc]['tht'] = thisHasText
            better = fns[crc]['c']>maxCount
            if thisHasText > hasText or (better and thisHasText==hasText):
                hasText = thisHasText
                chosen = crc
                maxCount = fns[crc]['c']

    f['view']['url'] = mid2url(hex2mid(f['file']['_id']))
    if chosen!="":
        filename = fns[chosen]['n']
        ext = fns[chosen]['x']
    else:
        #uses filename from src
        srcurl = ""
        for crc,srcfn in srcfns.items():
            if src['url'].find("/")!=-1:
                srcurl = src['url']

        if srcurl=="":
            return

        srcurl = srcurl[srcurl.rfind("/")+1:]
        ext = srcurl[srcurl.rfind(".")+1:]
        filename = srcurl[0:srcurl.rfind(".")]

    if not ext in current_app.config["EXTENSIONS"].keys():
        filename += ext
        ext=""
        nfilename = filename
    else:
        #clean filename
        end = filename.upper().rfind("."+ext.upper())
        if end == -1:
            nfilename = filename
        else:
            nfilename = filename.strip()[0:end]

    f['view']['fn'] = filename
    f['view']['efn'] = filename.replace(" ", "%20")
    f['view']['fnx'] = ext

    #nombre del archivo con las palabras que coinciden con la busqueda resaltadas
    if not text:
        f['view']['fnh']=filename
    else:
        separators = u"".join({i for i in filename if not unicodedata.category(i)[0] in ("N","L")})
        separated_text = tuple(multipartition(text.lower(), separators))
        f['view']['fnh'] = u"".join(
            (u"<strong>%s</strong>" % filename_part)
            if filename_part.lower() in separated_text and not filename_part in separators
            else filename_part
            for filename_part in multipartition(filename, separators)
            )

    if nfilename.find(" ")==-1:
        nfilename = nfilename.replace(".", " ")

    nfilename = nfilename.replace("_", " ")
    f['view']['nfn'] = nfilename
Beispiel #21
0
def main(processes, part, server, xml_file, fileid, favs, stats_update):
    global sources, sources_innergroups, sources_domains, counters

    batch_size = 1024*10

    setup_logging(SentryHandler(Client(config["SENTRY_SPHINX_DNS"])))
    fields, attrs = get_definitions()

    if favs:
        attrs.append(
            {"name":"list", "type":"str", "bits":64,              # Group
                "field": "_g"
            })

    sources = {int(float(s["_id"])):s for s in server_conn.foofind.source.find({"$or": [{"crbl": { "$exists" : False } }, {"crbl":0}]})}
    sources_domains = {source_id:"%s%s"%(FILTER_PREFIX_SOURCE, source["d"].lower().replace(".","")) for source_id, source in sources.iteritems()}

    g = globals()
    def get_function(i):
        if not (i in sources and "ig" in sources[i]): return None
        try:
            ig = sources[i]["ig"]
            return partial(g["innergroup_%s"%ig[0]], *ig[1:])
        except:
            return None
    sources_innergroups = [None]+[get_function(i+1) for i in xrange(0,max(sources.iterkeys()))]

    if not server:
        servers = server_conn.foofind.server.find_one({"_id":part})
        server = "mongodb://%s:%d"%(servers["ip"],servers["p"])
    ntts_server = config["DATA_SOURCE_ENTITIES"]

    xmlpipe2.set_globals(fields, attrs, init_file, fav_stats if favs else file_stats)

    incremental_index = False
    if favs:
        counters.append(0)
        user_conn = pymongo.Connection(config["DATA_SOURCE_USER"]) # TO-DO: maybe won't work with shared connections settings
        xml = xmlpipe2.XmlPipe2(processes, fields, attrs, None, generate_fav_id)
        xml.generate_header()
        for doc in user_conn.foofind.favfile.find({"files.server":part}):
            if not doc.get("files", None): continue
            counters[0] = 0
            files_filter = {"_id":{"$in":[f["id"] for f in doc["files"]]}}
            xml.generate(server, ntts_server, (doc["name"], doc["user_id"] << 24, part << 16), files_filter, batch_size, headers=False)
        xml.generate_footer()
        user_conn.end_request()
    else:
        counters.extend((0,)*2**16) # 16 bits del hash hacen el contador
        files_filter = {'bl': 0}
        if fileid: files_filter["_id"] = hex2mid(fileid)

        stats = {"_id": part, "sg":defaultdict(int), "z":defaultdict(int), "l":defaultdict(int), "lc":defaultdict(int), "la":defaultdict(float), "lpa":defaultdict(float), "zc":defaultdict(int), "za":defaultdict(float), "zpa":defaultdict(float), "ra":defaultdict(float), "rpa":defaultdict(float), "rM":defaultdict(float), "rc":defaultdict(int), "__dtags":{tag:{subcat:0 for word, subcat in DYNAMIC_TAGS[tag].iteritems() if word==subcat} for tag in DYNAMIC_TAGS.iterkeys()}}

        if xml_file:
            if exists(xml_file):
                incremental_index = True
                line = last_line(xml_file)
                counters, stop_set, saved_stats, last_count = json.loads(line[4:-3])
                stop_set = set(stop_set)
                stop_set_len = len(stop_set)

                for key, value in saved_stats.iteritems():
                    if isinstance(value, defaultdict):
                        stats[key].update(value)
            else:
                # primer fichero
                stop_set = set()
                stop_set_len = 10
                last_count = 0

            xml = xmlpipe2.XmlPipe2(processes, fields, attrs, stats, generate_id)

            # genera cabeceras para el primer fichero
            if not incremental_index:
                xml.generate_header()
            new_stop_set = xml.generate(server, ntts_server, part<<16, files_filter, batch_size, stop_set=stop_set, stop_set_len=stop_set_len, last_count=last_count, headers=False)

            # solo imprime estado si ha añadido algun fichero
            if xml.count:
                print "\n<!--%s-->"%json.dumps((counters, list(new_stop_set), stats, xml.total_count)),

        else:
            xml = xmlpipe2.XmlPipe2(processes, fields, attrs, stats, generate_id)
            xml.generate(server, ntts_server, part<<16, files_filter, batch_size)

        dtags_stats = stats["__dtags"]
        del stats["__dtags"]


        if stats_update and not incremental_index:
            for tag, dtags in dtags_stats.iteritems():
                server_conn.torrents.subcategory.update({"_id":tag}, {"$set":{"sc.%s.c"%dtag:count for dtag, count in dtags.iteritems()}})

            server_conn.foofind.search_stats.insert({"_id":part, "d0":time(), "d1":time()})
            server_conn.foofind.search_stats.update({"_id":part}, {"$set":stats})
            server_conn.foofind.server.update({"_id":part},{"$set":{"ss":0}})
Beispiel #22
0
 def find_userid(self,userid):
     '''
     Busca los datos del usuario a partir del id
     '''
     return self.__search({"_id":hex2mid(userid)})
Beispiel #23
0
    def get_files(self, ids, servers_known = False, bl = 0):
        '''
        Devuelve los datos de los ficheros correspondientes a los ids
        dados en formato hexadecimal.

        @param ids: Lista de identificadores de los ficheros a recuperar. Si server_known es False, es una lista de cadenas. Si server_known es True, es una lista de tuplas, que incluyen el identificador del fichero y el número de servidor.
        @param servers_known: Indica si la lista de identificadores incluye el servidor donde se encuentra el fichero.


        @type bl: int o None
        @param bl: valor de bl para buscar, None para no restringir

        @rtype generator
        @return Generador con los documentos de ficheros
        '''

        if not ids: return ()

        sids = defaultdict(list)
        # si conoce los servidores en los que están los ficheros,
        # se analiza ids como un iterable (id, servidor, ...)
        # y evitamos buscar los servidores
        if servers_known:
            for x in ids:
                sids[x[1]].append(hex2mid(x[0]))
        else:
            # averigua en qué servidor está cada fichero
            nindir = self.server_conn.foofind.indir.find({"_id": {"$in": [hex2mid(fid) for fid in ids]}, "s": {"$exists": 1}})
            for ind in nindir:
                indserver = str(int(ind["s"])) # Bug en indir: 's' como float
                if indserver in self.servers_conn:
                    if "t" in ind: # si apunta a otro id, lo busca en vez del id dado
                        sids[indserver].append(ind["t"])
                    else:
                        sids[indserver].append(ind["_id"])
            self.server_conn.end_request()

        lsids = len(sids)
        if lsids == 0:
            # Si no hay servidores, no hay ficheros
            return ()
        elif lsids == 1:
            k, v = sids.iteritems().next()
            return self._get_server_files((k, v, bl))
        else:
            # crea el pool de hilos si no existe
            if not self.thread_pool:
                self.thread_pool = ThreadPool(processes=self.thread_pool_size)

            # obtiene la información de los ficheros de cada servidor
            results = []
            chunks = self.thread_pool.imap_unordered(self._get_server_files, ((k, v, bl) for k, v in sids.iteritems()))
            end = time.time()+self.get_files_timeout
            try:
                for i in xrange(len(sids)):
                    now = time.time()
                    if now>end:
                        break
                    for r in chunks.next(end-now):
                        results.append(r)
            except TimeoutError:
                pass
            except BaseException as e:
                logging.error("Error on get_files.")
            return results
Beispiel #24
0
 def get_file_comment_votes(self,file_id):
     '''
     Recuper los votos de los comentarios de un archivo
     '''
     return end_request(self.user_conn.foofind.comment_vote.find({"f":hex2mid(file_id)}))
Beispiel #25
0
 def get_file_comments(self,file_id,lang):
     '''
     Recupera los comentarios de un archivo
     '''
     return end_request(self.user_conn.foofind.comment.find({"f":hex2mid(file_id),"l":lang}))
Beispiel #26
0
def get_files_metadata(files, block_on_sphinx=True):
    names = {hex2mid(i["id"]):i["name"] for i in files}
    for f in get_files(
      [(i["id"], i["server"]) for i in files],
      block_on_sphinx = block_on_sphinx):
        yield fill_data(f, names[f["_id"]])
Beispiel #27
0
def db_confirm(collection, document_id=None):
    """
    Confirmación de edición de base de datos
    """
    page = request.args.get("page", 0, int)
    grps = request.args.get("mode", "all", str)
    mode = request.args.get("show", "current", str)
    size = request.args.get("size", 15, int)

    goback = lambda: redirect(url_for(url_id, page=page, mode=grps, show=mode, size=size))

    document = json.loads(request.form.get("defaults"))
    document_writeable = json.loads(request.form.get("editable"))

    request_form_dict = MultiDict(request.form)

    success_msgid = "admin_saved"
    unchanged_msgid = "admin_nochanges"

    if collection == "user":
        page_title = "admin_users"
        form_title = "admin_users_info"
        success_msgid = "admin_users_updated"
        url_id = "admin.users"
        save_fnc = lambda data: usersdb.update_user(data)
        new_password = request_form_dict.pop(db_fnm("new password"), None)
        if new_password:
            document_writeable.append("password")
            request_form_dict[db_fnm("password")] = new_password
    elif collection == "origin":
        page_title = "admin_origins_info"
        form_title = "admin_origins_info"
        url_id = "admin.origins"
        save_fnc = lambda data: filesdb.update_source(data)

    if request.form.get("confirmed", "False") == "True":
        # La petición ha sido realizada por el formulario de confirmación,
        # lo procesamos.
        check_form = expanded_instance(
            EditForm, {db_fnm(k): BooleanField(k) for k in document_writeable}, request_form_dict
        )
        data = {k: document[k] for k in document_writeable if check_form[db_fnm(k)].data}
        if data:
            data["_id"] = hex2mid(document_id)
            save_fnc(data)
            flash(success_msgid, "success")
            return goback()
        else:
            flash(unchanged_msgid, "error")
            return goback()
    else:
        # No se trata del petición confirmada, procesamos el formulario como
        # viene de db_edit, generamos el formulario de confirmación.

        edit_form = expanded_instance(
            EditForm,
            {db_fnm(k): TextField(k, default=db_dtf(collection, k, document[k])) for k in document_writeable},
            request_form_dict,
        )
        document_changes = [
            (k, document[k], db_ftd(collection, k, edit_form[db_fnm(k)].data))
            for k in document_writeable
            if edit_form[db_fnm(k)].data != db_dtf(collection, k, document[k])
        ]
        if document_changes:
            check_form = expanded_instance(
                EditForm, {db_fnm(k): BooleanField(k, default=False) for k, w, w in document_changes}
            )
            check_form.defaults.data = json.dumps({k: v for k, w, v in document_changes})
            check_form.editable.data = json.dumps([k for k, w, v in document_changes])
            check_form.confirmed.data = True
        else:
            flash(unchanged_msgid, "error")
            return goback()

    return render_template(
        "admin/confirm.html",
        collection=collection,
        document_id=document_id,
        title=admin_title(page_title),
        page_title=_(page_title),
        check_form=check_form,
        form_title=_(form_title),
        fieldname=db_fnm,
        repr=repr,
        document_changes=document_changes,
        list_mode=grps,
        mode=mode,
        page_size=size,
        page=page,
    )