Exemple #1
0
    def authenticate(self):
        """Checks the authentication credentials and sets the context user if all
        checks are ok.
        """
        self.user = None

        # 1. Get credentials with username and token
        try:
            username, token = self.get_authentication_credentials()
        except ValueError as error:
            msg = "Authentication error : %s " % error.message
            log_warning(msg, domain='ikaaro.web')
            return

        if not username or not token:
            return

        # 2. Get the user
        user = self.root.get_user(username)
        if not user:
            return

        # 3. Check the token
        user_token = user.get_auth_token()
        if token == self._get_auth_token(user_token):
            self.user = user
Exemple #2
0
 def get_value(self, name, language=None):
     field = self.get_field(name)
     if field is None:
         msg = 'field {name} is not defined on {class_id}'
         log_warning(msg.format(name=name, class_id=self.class_id))
         return None
     # Check context
     self.check_if_context_exists()
     # Check if field is obsolete
     if field.obsolete:
         msg = 'field {name} is obsolete on {class_id}'
         log_warning(msg.format(name=name, class_id=self.class_id))
     # TODO: Use decorator for cache
     # TODO: Reactivate when ready
     #cache_key = (name, language)
     #if self._values.has_key(cache_key):
     #    return self._values[cache_key]
     if self._brain and field.stored and not is_prototype(field.datatype, Decimal):
         try:
             value = self.get_value_from_brain(name, language)
         except Exception:
             # FIXME Sometimes we cannot get value from brain
             # We're tying to debug this problem
             msg = 'Warning: cannot get value from brain {0} {1}'
             msg = msg.format(self.abspath, name)
             print(msg)
             value = field.get_value(self, name, language)
     else:
         value = field.get_value(self, name, language)
     #self._values[cache_key] = value
     return value
Exemple #3
0
    def authenticate(self):
        """Checks the authentication cookie and sets the context user if all
        checks are ok.
        """
        self.user = None

        # 1. Get the cookie
        cookie = self.get_cookie('iauth')
        if not cookie:
            return

        # 2. Parse the cookie
        try:
            username, token = decodestring(unquote(cookie)).split(':', 1)
        except Exception:
            msg = 'bad authentication cookie "%s"' % cookie
            log_warning(msg, domain='itools.web')
            return

        if not username or not token:
            return

        # 3. Get the user
        user = self.root.get_user(username)
        if not user:
            return

        # 4. Check the token
        user_token = user.get_auth_token()
        if token == self._get_auth_token(user_token):
            self.user = user
Exemple #4
0
 def get_products_namespace(self, context):
     root = context.root
     query = AndQuery(
         get_base_path_query(self.get_canonical_path()),
         PhraseQuery('format', 'order-product'))
     l = []
     for brain in root.search(query).get_documents():
         resource = root.get_resource(brain.abspath, soft=True)
         if resource is None:
             log_warning('ORDER-PRODUCT not found : %s' % brain.abspath)
             continue
         # Get base product namespace
         kw = {}
         for key in ['reference', 'title', 'tax', 'quantity']:
             kw[key] = resource.get_property(key)
         kw['pre_tax_price'] = resource.get_property('pre_tax_price')
         tax = kw['tax'] / decimal(100) + 1
         kw['price_with_tax'] = get_arrondi(kw['pre_tax_price'] * tax)
         total_price = kw['price_with_tax'] * kw['quantity']
         kw['pre_tax_price'] = self.format_price(kw['pre_tax_price'])
         kw['total_price'] = self.format_price(total_price)
         kw['price_with_tax'] = self.format_price(kw['price_with_tax'])
         # Get product link (if exist)
         abspath = resource.get_property('abspath')
         product = root.get_resource(abspath, soft=True)
         if product:
             # Add link only if edit allowed
             link = None
             ac = resource.get_access_control()
             if ac.is_allowed_to_edit(context.user, product):
                 link = context.get_link(product)
             kw['link'] = link
         # Add product to list of products
         l.append(kw)
     return l
Exemple #5
0
    def handle_request(self, soup_message, path):
        # (1) If path is null => 400 Bad Request
        if path is None:
            log_warning('Unexpected HTTP path (null)', domain='itools.web')
            return set_response(soup_message, 400)

        # (2) Attach to the soup message and path
        context = self()
        context.soup_message = soup_message
        context.path = path

        # (3) Get the method that will handle the request
        method_name = soup_message.get_method()
        method = getattr(context, 'http_%s' % method_name.lower(), None)
        # 501 Not Implemented
        if method is None:
            log_warning('Unexpected "%s" HTTP method' % method_name,
                        domain='itools.web')
            return set_response(soup_message, 501)

        # (4) Go
        set_context(context)
        try:
            method()
        except StandardError:
            log_error('Internal error', domain='itools.web')
            return set_response(soup_message, 500)
        finally:
            set_context(None)
Exemple #6
0
    def _update_data(self):
        limit = self.get_property('limit')
        uri = self._get_account_uri()
        data = None
        # errors
        errors = []
        errors_str = []

        # backup the default timeout
        default_timeout = socket.getdefaulttimeout()
        socket.setdefaulttimeout(3) # timeout in seconds

        # TODO Use itools.vfs instead of urllib2
        try:
            req = urllib2.Request(uri)
            req.add_header('User-Agent', 'itools/%s' % itools_version)
            response = urllib2.urlopen(req)
            data = response.read()
        except (socket.error, socket.gaierror, Exception,
                urllib2.HTTPError, urllib2.URLError), e:
            msg = '%s -- Network error: "%s"'
            msg = msg % (XMLContent.encode(str(uri)), e)
            msg = msg.encode('utf-8')
            errors.append(XMLParser(msg))
            errors_str.append(msg)

            summary = 'sidebar/twitter, Error downloading feed\n'
            details = format_exc()
            log_warning(summary + details, domain='itws')
Exemple #7
0
    def _smtp_send(self):
        nb_max_mails_to_send = 2
        spool = lfs.open(self.spool)

        def get_names():
            # Find out emails to send
            locks = set()
            names = set()
            for name in spool.get_names():
                if name == 'failed':
                    # Skip "failed" special directory
                    continue
                if name[-5:] == '.lock':
                    locks.add(name[:-5])
                else:
                    names.add(name)
            names.difference_update(locks)
            return names

        # Send emails
        names = get_names()
        smtp_host = self.smtp_host
        for name in list(names)[:nb_max_mails_to_send]:
            # 1. Open connection
            try:
                smtp = SMTP(smtp_host)
            except gaierror, excp:
                log_warning('%s: "%s"' % (excp[1], smtp_host))
                return 60 # 1 minute
            except Exception:
                self.smtp_log_error()
                return 60 # 1 minute
Exemple #8
0
 def get_header(self, name):
     name = name.lower()
     datatype = get_type(name)
     value = self.soup_message.get_header(name)
     if value is None:
         return datatype.get_default()
     try:
         return datatype.decode(value)
     except ValueError:
         log_warning('malformed header: %s: %s' % (name, value),
                     domain='itools.web')
         return datatype.get_default()
Exemple #9
0
 def get_catalog_values(self):
     values = {}
     # Step 1. Automatically index fields
     root = self.get_root()
     languages = root.get_value('website_languages')
     for name, field in self.get_fields():
         if not field.indexed and not field.stored:
             continue
         if field.multilingual:
             value = {}
             for language in languages:
                 value[language] = field.get_value(self, name, language)
             values[name] = value
         else:
             values[name] = field.get_value(self, name)
     # Step 2. Index non-metadata properties
     # Path related fields
     abspath = self.abspath
     values['abspath'] = str(abspath)
     n = len(abspath)
     values['abspath_depth'] = n
     if n:
         values['parent_paths'] = [ str(abspath[:i]) for i in range(n) ]
     values['name'] = self.name
     # Class related fields
     values['format'] = self.metadata.format
     values['base_classes'] = self.get_base_classes()
     values['class_version'] = class_version_to_date(self.metadata.version)
     # Links to other resources
     values['owner'] = self.get_owner()
     values['share'] = self.get_share()
     values['links'] = list(self.get_links())
     values['onchange_reindex'] = self.get_onchange_reindex()
     # Full text indexation (not available in icms-init.py FIXME)
     context = get_context()
     server = context.server
     if server and server.index_text:
         try:
             values['text'] = self.to_text()
         except Exception:
             log = 'Indexation failed: %s' % abspath
             log_warning(log, domain='ikaaro')
     # Time events for the CRON
     reminder, payload = self.next_time_event()
     values['next_time_event'] = reminder
     if payload:
         values['next_time_event_payload'] = dumps(payload)
     else:
         values['next_time_event_payload'] = None
     # Ok
     return values
Exemple #10
0
 def check_consistency(self, quick):
     log_info('Check database consistency')
     # Check the server is not running
     if self.read_only:
         pid = get_pid('%s/pid_ro' % self.target)
     else:
         pid = get_pid('%s/pid' % self.target)
     if pid is not None:
         msg = '[%s] The Web Server is already running.' % self.target
         log_warning(msg)
         print(msg)
         return False
     # Ok
     return True
Exemple #11
0
    def update_rss(self):
        handler = self.handler
        errors = []
        errors_str = []
        articles = []
        feeds_summary = {}
        # backup the default timeout
        default_timeout = socket.getdefaulttimeout()
        socket.setdefaulttimeout(self.get_property('timeout'))

        # Download the feeds
        for uri, keywords, active in handler.get_rows():
            if active is False:
                continue
            keywords = [x.strip().lower() for x in keywords.split(',')]

            # TODO Use itools.vfs instead of urllib2
            try:
                req = urllib2.Request(uri)
                req.add_header('User-Agent', 'itools/%s' % itools_version)
                response = urllib2.urlopen(req)
                data = response.read()
            except (socket.error, socket.gaierror, Exception,
                    urllib2.HTTPError), e:
                msg = '%s <br />-- Network error: "%s"'
                msg = msg % (XMLContent.encode(str(uri)), e)
                msg = msg.encode('utf-8')
                errors.append(XMLParser(msg))
                errors_str.append(msg)

                summary = ('rssfeeds, Error downloading feed\n'
                           'uri: %s\n\n' % str(uri))
                details = format_exc()
                log_warning(summary + details, domain='itws')
                continue

            # Parse
            try:
                feed = RSSFile(string=data)
            except Exception, e:
                msg = '%s <br />-- Error parsing: "%s"'
                msg = msg % (XMLContent.encode(str(uri)), e)
                msg = msg.encode('utf-8')
                errors.append(XMLParser(msg))
                errors_str.append(msg)
                summary = ('rssfeeds, Error parsing feed\n'
                           'uri: %s\n\n' % str(uri))
                details = format_exc()
                log_warning(summary + details, domain='itws')
                continue
Exemple #12
0
    def get_handler_class(self, key):
        mimetype = self.get_mimetype(key)

        try:
            return get_handler_class_by_mimetype(mimetype)
        except ValueError:
            log_warning('unknown handler class "{0}"'.format(mimetype))
            if fs.is_file(key):
                from itools.handlers import File
                return File
            elif fs.is_folder(key):
                from itools.handlers import Folder
                return Folder

        raise ValueError
Exemple #13
0
 def get_header(self, name):
     name = name.lower()
     datatype = get_type(name)
     name = name.replace('-', '_')
     if name == 'content_type':
         value = self.environ.get('CONTENT_TYPE')
     else:
         value = self.environ.get('HTTP_'+ name.upper())
     if value is None:
         return datatype.get_default() or ''
     try:
         return datatype.decode(value) or ''
     except ValueError:
         log_warning('malformed header: %s: %s' % (name, value),
                     domain='ikaaro.web')
         return datatype.get_default()
Exemple #14
0
    def to_str(self):
        resource_class = self.get_resource_class(self.format)

        if self.version is None:
            lines = ['format:%s\n' % self.format]
        else:
            lines = ['format;version=%s:%s\n' % (self.version, self.format)]
        # Properties are to be sorted by alphabetical order
        properties = self.properties
        names = properties.keys()
        names.sort()

        # Properties
        for name in names:
            property = properties[name]

            # Get the field
            field = resource_class.get_field(name)
            if field is None:
                msg = 'unexpected field "{0}" in resource "{1}" (format "{2}")'
                msg = msg.format(name, self.key, self.format)
                if resource_class.fields_soft:
                    log_warning(msg, domain='itools.database')
                    continue
                raise ValueError, msg

            datatype = field.datatype
            params_schema = field.parameters_schema
            is_empty = datatype.is_empty
            p_type = type(property)
            if p_type is dict:
                languages = property.keys()
                languages.sort()
                lines += [
                    property_to_str(name, property[x], datatype, params_schema)
                    for x in languages if not is_empty(property[x].value) ]
            elif p_type is list:
                lines += [
                    property_to_str(name, x, datatype, params_schema)
                    for x in property if not is_empty(x.value) ]
            elif property.value is None:
                pass
            elif not is_empty(property.value):
                lines.append(
                    property_to_str(name, property, datatype, params_schema))

        return ''.join(lines)
Exemple #15
0
    def get_user_title(self, userid):
        if not userid:
            return None

        # Userid (abspath) or username
        if userid[0] != '/':
            userid = '/users/%s' % userid

        # Get user
        user = self.get_resource(userid, soft=True)
        if user is None:
            username = userid.rsplit('/', 1)[-1]
            log_warning('unkwnown user %s' % username, domain='ikaaro')
            return unicode(username)

        # Ok
        return user.get_title()
Exemple #16
0
    def path_callback(self, soup_message, path):
        # (1) Get the class that will handle the request
        method_name = soup_message.get_method()
        method = methods.get(method_name)
        # 501 Not Implemented
        if method is None:
            log_warning('Unexpected "%s" HTTP method' % method_name, domain="itools.web")
            return set_response(soup_message, 501)

        # (2) Initialize the context
        context = Context(soup_message, path)
        self.init_context(context)

        # (3) Pass control to the Get method class
        try:
            method.handle_request(self, context)
        except Exception:
            log_error("Failed to handle request", domain="itools.web")
            set_response(soup_message, 500)
Exemple #17
0
def read_headers(file):
    entity_headers = {}
    # Setup
    line = file.readline().strip()
    while not line:
        line = file.readline().strip()
    # Go
    while line:
        name, value = line.split(':', 1)
        name = name.strip().lower()
        datatype = get_type(name)
        value = value.strip()
        try:
            value = datatype.decode(value)
        except Exception:
            log_warning("Failed to parse the '%s' header" % name,
                        domain='itools.web')
        else:
            entity_headers[name] = value
        # Next
        line = file.readline().strip()

    return entity_headers
Exemple #18
0
    def _load_state_from_file(self, file):
        properties = self.properties
        data = file.read()
        parser = parse_table(data)

        # Read the format & version
        name, value, parameters = parser.next()
        if name != 'format':
            raise ValueError, 'unexpected "%s" property' % name
        if 'version' in parameters:
            version = parameters.pop('version')
            if len(version) > 1:
                raise ValueError, 'version parameter cannot be repeated'
            self.version = version[0]
        if parameters:
            raise ValueError, 'unexpected parameters for the format property'
        self.format = value
        # Get the schema
        resource_class = self.database.get_resource_class(value)

        # Parse
        for name, value, parameters in parser:
            if name == 'format':
                raise ValueError, 'unexpected "format" property'

            # 1. Get the field
            field = resource_class.get_field(name)
            if field is None:
                msg = 'unexpected field "%s"' % name
                if resource_class.fields_soft:
                    log_warning(msg, domain='itools.database')
                    field = DefaultField
                else:
                    raise ValueError, msg

            # 2. Deserialize the parameters
            params_schema = field.parameters_schema
            params_default = field.parameters_schema_default
            try:
                deserialize_parameters(parameters, params_schema,
                                       params_default)
            except ValueError, e:
                msg = 'in class "{0}" property "{1}": {2}'
                raise ValueError, msg.format(resource_class, name, e)

            # 3. Get the datatype properties
            if field.multiple and field.multilingual:
                error = 'property "%s" is both multilingual and multiple'
                raise ValueError, error % name

            # 4. Build the property
            datatype = field.datatype
            value = datatype.decode(value)
            property = Property(value, **parameters)

            # Case 1: Multilingual
            if field.multilingual:
                language = parameters.get('lang')
                if language is None:
                    err = 'multilingual property "%s" is missing the language'
                    raise ValueError, err % name
                properties.setdefault(name, {})[language] = property
            # Case 2: multiple
            elif field.multiple:
                properties.setdefault(name, []).append(property)
            # Case 3: simple
            else:
                properties[name] = property
Exemple #19
0
def make_namespaces(context):
    # Shortcuts
    elements = context['elements']
    references = context['references']

    # Find all namespaces, and fill them with elements
    namespaces = {}
    for element in elements:
        qnames = element['qnames']
        attributes = element['attributes']
        data = element['data']
        is_empty = element['is_empty']
        refs = element['refs']

        # Replace the references of "refs"
        while refs:
            new_refs = []
            for ref in refs:
                try:
                    ref = references[ref]
                except KeyError:
                    raise KeyError, ('the define "%s" is missing in your '
                                     'relax NG file') % ref
                attributes.extend(ref['attributes'])
                new_refs.extend(ref['refs'])
                is_empty = is_empty and ref['is_empty']

                ref_data = ref['data']
                if ref_data is not None:
                    if data is not None and data != ref_data:
                        data = ''
                    elif data is None:
                        data = ref_data

            refs = new_refs

        # Now, data is good
        if data is not None:
            is_empty = False

        # Replace the references of "attributes"
        for attribute in attributes:
            refs = attribute['refs']
            while refs:
                new_refs = []
                for ref in refs:
                    try:
                        ref = references[ref]
                    except KeyError:
                        raise KeyError, ('the define "%s" is missing in your '
                                         'relax NG file') % ref
                    new_refs.extend(ref['refs'])

                    ref_data = ref['data']
                    attr_data = attribute['data']

                    if ref_data is not None:
                        if attr_data is not None and attr_data != ref_data:
                            attr_data = ''
                        elif attr_data is None:
                            attr_data = ref_data

                refs = new_refs

        # Update the good namespaces
        if qnames is not None:
            for uri, name in element['qnames']:
                own, free = split_attributes(uri, attributes)

                # Element + its attributes
                namespace = namespaces.setdefault(uri, {'elements': {},
                                                  'free_attributes': {}})
                element = ElementSchema(name,
                                        default_datatype=String,
                                        is_empty=is_empty,
                                        attributes=own)
                namespace['elements'][name] = element

                # Free attributes
                for (uri, name), datatype in free.iteritems():
                    namespace = namespaces.setdefault(uri, {'elements': {},
                                                      'free_attributes': {}})
                    namespace['free_attributes'][name] = datatype

    result = {}
    prefix2uri = context['prefix']
    for namespace, data in namespaces.iteritems():
        # Find the prefix
        for prefix, uri in prefix2uri.iteritems():
            if uri == namespace:
                result[uri] = XMLNamespace(uri, prefix,
                                           data['elements'].values(),
                                           data['free_attributes'], String)
                break
        else:
            log_warning('relaxng: namespace "%s" not found' % namespace)

    return result
Exemple #20
0
def warn_not_indexed(name):
    log_warning(MSG_NOT_INDEXED.format(name=name), 'itools.database')
Exemple #21
0
    def get_catalog_values(self):
        values = {}

        # Step 1. Automatically index fields
        languages = self.get_root().get_value('website_languages')
        for name, field in self.get_fields():
            if not field.indexed and not field.stored:
                continue

            if field.multilingual:
                value = {}
                for language in languages:
                    value[language] = field.get_value(self, name, language)
                values[name] = value
            else:
                values[name] = field.get_value(self, name)

        # Step 2. Index non-metadata properties
        # Path related fields
        abspath = self.abspath
        values['abspath'] = str(abspath)
        n = len(abspath)
        values['abspath_depth'] = n
        if n:
            values['parent_paths'] = [ str(abspath[:i]) for i in range(n) ]

        values['name'] = self.name
        values['is_content'] = self.is_content

        # Class related fields
        values['format'] = self.metadata.format
        values['base_classes'] = []
        for cls in self.__class__.__mro__:
            class_id = getattr(cls, 'class_id', None)
            if class_id:
                values['base_classes'].append(class_id)

        # Links to other resources
        values['owner'] = self.get_owner()
        values['share'] = self.get_share()
        values['links'] = list(self.get_links())

        # Full text
        context = get_context()
        try:
            server = context.server
        except AttributeError:
            server = None
        if server is not None and server.index_text:
            try:
                values['text'] = self.to_text()
            except NotImplementedError:
                pass
            except Exception:
                log = 'Indexation failed: %s' % abspath
                log_warning(log, domain='ikaaro')

        # Time events
        reminder, payload = self.next_time_event()
        values['next_time_event'] = reminder
        values['next_time_event_payload'] = dumps(payload)

        # Ok
        return values
Exemple #22
0
def warn_not_indexed_nor_stored(name):
    log_warning(MSG_NOT_INDEXED_NOR_STORED.format(name=name))
Exemple #23
0
def warn_not_stored(name):
    log_warning(MSG_NOT_STORED.format(name=name))
Exemple #24
0
def warn_not_indexed(name):
    log_warning(MSG_NOT_INDEXED.format(name=name))
Exemple #25
0
def _choice_widget(context, form, datatype, name, value, schema, fields,
                   readonly, container, container_attributes, choice,
                   choice_attributes, choice_checked, multiline, tabindex):
    html = []

    # True -> '1' ; False -> '2'
    data = datatype.encode(value)

    if readonly:
        for option in datatype.get_namespace(data):
            attributes = merge_dicts(choice_attributes,
                                     value=option['name'],
                                     disabled=u"disabled")
            attributes.setdefault(u"class", []).append(u"disabled")
            if option['selected']:
                attributes[choice_checked] = choice_checked
            value = option['value']
            if is_prototype(value, MSG):
                value = value.gettext()
            content = XMLContent.encode(value)
            input = make_element(choice, attributes, content)
            if multiline is True:
                # Une option par ligne
                html.append(make_element(u"div", content=input))
            else:
                html.append(input)
    else:
        if type(data) == type("") or type(data) == type(u""):
            try:
                data_tmp = data.decode("utf-8").split('|')
            except:
                data_tmp = data
        else:
            data_tmp = data
        for option in datatype.get_namespace(data_tmp):
            js = []
            opt_name = option['name']
            attributes = merge_dicts(choice_attributes, value=opt_name)
            if option['selected'] or data == option['name'].strip().encode(
                    'utf-8'):
                attributes[choice_checked] = choice_checked
            if form.is_disabled_by_dependency(name, schema, fields):
                attributes[u"disabled"] = u"disabled"
                attributes.setdefault(u"class", []).append(u"disabled")

            # 0005970: Le Javascript pour (dés)activer les autres champs
            dep_names = form.get_dep_names(name, schema)
            for dep_name in dep_names:
                dependency = schema[dep_name].dependency
                if not dependency:
                    continue
                # Add js action on simple boolean expressions. ie: "C11"
                if not Expression.is_simple(dependency):
                    # Authorized operators are "==", "=" and "in"
                    # ie:"C11=='others'", "C11='others'", "'others' in  C11"
                    if 'in' in dependency:
                        dep_value = dependency.split('in', 1)[0].strip()
                    elif '==' in dependency:
                        exclusive, dep_value = dependency.rsplit('==', 1)
                    elif '!=' in dependency:
                        exclusive, dep_value = dependency.rsplit('!=', 1)
                    else:
                        msg = 'K col operator unknown in "%s"' % dependency
                        log_warning(msg)
                        continue
                    if dep_value[:1] in ("u'", 'u"'):
                        dep_value = dep_value[:2]
                    dep_value = (dep_value.replace("'", '').replace('"', ''))
                    #dep_value = checkid(dep_value)
                else:
                    dep_value = 'false'

                js_code = (
                    '$("input[name=\\"%s\\"][value=\\"%s\\"]")'
                    '.change(function(){switch_input($(this),"%s","%s");});' %
                    (name, opt_name, dep_name, dep_value))
                js.append(js_code)

            # 0005970 fin
            value = option['value']
            if is_prototype(value, MSG):
                value = value.gettext()
            content = XMLContent.encode(value)
            input = make_element(choice, attributes, content)
            if multiline is True:
                # Une option par ligne
                html.append(make_element(u"div", content=input))
            else:
                html.append(input)

            # Append JS code
            content = XMLContent.encode(u'\n'.join(js))
            attributes = {u'type': "text/javascript"}
            html.append(make_element(u'script', attributes, content))

    attributes = merge_dicts(container_attributes,
                             id=u"field_{name}".format(name=name))
    check_errors(context,
                 form,
                 datatype,
                 name,
                 data,
                 schema,
                 fields,
                 readonly,
                 attributes,
                 tabindex=None)
    return make_element(container, attributes, u"".join(html))
Exemple #26
0
def make_namespaces(context):
    # Shortcuts
    elements = context['elements']
    references = context['references']

    # Find all namespaces, and fill them with elements
    namespaces = {}
    for element in elements:
        qnames = element['qnames']
        attributes = element['attributes']
        data = element['data']
        is_empty = element['is_empty']
        refs = element['refs']

        # Replace the references of "refs"
        while refs:
            new_refs = []
            for ref in refs:
                try:
                    ref = references[ref]
                except KeyError:
                    raise KeyError, ('the define "%s" is missing in your '
                                     'relax NG file') % ref
                attributes.extend(ref['attributes'])
                new_refs.extend(ref['refs'])
                is_empty = is_empty and ref['is_empty']

                ref_data = ref['data']
                if ref_data is not None:
                    if data is not None and data != ref_data:
                        data = ''
                    elif data is None:
                        data = ref_data

            refs = new_refs

        # Now, data is good
        if data is not None:
            is_empty = False

        # Replace the references of "attributes"
        for attribute in attributes:
            refs = attribute['refs']
            while refs:
                new_refs = []
                for ref in refs:
                    try:
                        ref = references[ref]
                    except KeyError:
                        raise KeyError, ('the define "%s" is missing in your '
                                         'relax NG file') % ref
                    new_refs.extend(ref['refs'])

                    ref_data = ref['data']
                    attr_data = attribute['data']

                    if ref_data is not None:
                        if attr_data is not None and attr_data != ref_data:
                            attr_data = ''
                        elif attr_data is None:
                            attr_data = ref_data

                refs = new_refs

        # Update the good namespaces
        if qnames is not None:
            for uri, name in element['qnames']:
                own, free = split_attributes(uri, attributes)

                # Element + its attributes
                namespace = namespaces.setdefault(uri, {
                    'elements': {},
                    'free_attributes': {}
                })
                element = ElementSchema(name,
                                        default_datatype=String,
                                        is_empty=is_empty,
                                        attributes=own)
                namespace['elements'][name] = element

                # Free attributes
                for (uri, name), datatype in free.iteritems():
                    namespace = namespaces.setdefault(uri, {
                        'elements': {},
                        'free_attributes': {}
                    })
                    namespace['free_attributes'][name] = datatype

    result = {}
    prefix2uri = context['prefix']
    for namespace, data in namespaces.iteritems():
        # Find the prefix
        for prefix, uri in prefix2uri.iteritems():
            if uri == namespace:
                result[uri] = XMLNamespace(uri, prefix,
                                           data['elements'].values(),
                                           data['free_attributes'], String)
                break
        else:
            log_warning('relaxng: namespace "%s" not found' % namespace)

    return result
Exemple #27
0
def warn_not_stored(name):
    log_warning(MSG_NOT_STORED.format(name=name), 'itools.database')
Exemple #28
0
    def _load_state_from_file(self, file):
        properties = self.properties
        data = file.read()
        parser = parse_table(data)

        # Read the format & version
        name, value, parameters = parser.next()
        if name != 'format':
            raise ValueError, 'unexpected "%s" property' % name
        if 'version' in parameters:
            version = parameters.pop('version')
            if len(version) > 1:
                raise ValueError, 'version parameter cannot be repeated'
            self.version = version[0]
        if parameters:
            raise ValueError, 'unexpected parameters for the format property'
        self.format = value
        # Get the schema
        resource_class = self.database.get_resource_class(value)

        # Parse
        for name, value, parameters in parser:
            if name == 'format':
                raise ValueError, 'unexpected "format" property'

            # 1. Get the field
            field = resource_class.get_field(name)
            if field is None:
                msg = 'unexpected field "%s"' % name
                if resource_class.fields_soft:
                    log_warning(msg, domain='itools.database')
                    field = DefaultField
                else:
                    raise ValueError, msg

            # 2. Deserialize the parameters
            params_schema = field.parameters_schema
            params_default = field.parameters_schema_default
            try:
                deserialize_parameters(parameters, params_schema,
                                       params_default)
            except ValueError, e:
                msg = 'in class "{0}" property "{1}": {2}'
                raise ValueError, msg.format(resource_class, name, e)

            # 3. Get the datatype properties
            if field.multiple and field.multilingual:
                error = 'property "%s" is both multilingual and multiple'
                raise ValueError, error % name

            # 4. Build the property
            datatype = field.datatype
            value = datatype.decode(value)
            property = Property(value, **parameters)

            # Case 1: Multilingual
            if field.multilingual:
                language = parameters.get('lang')
                if language is None:
                    err = 'multilingual property "%s" is missing the language'
                    raise ValueError, err % name
                properties.setdefault(name, {})[language] = property
            # Case 2: multiple
            elif field.multiple:
                properties.setdefault(name, []).append(property)
            # Case 3: simple
            else:
                properties[name] = property
Exemple #29
0
def warn_not_stored(name):
    log_warning(MSG_NOT_STORED.format(name=name), 'itools.database')
Exemple #30
0
    def get_catalog_values(self):
        values = {}

        # Step 1. Automatically index fields
        languages = self.get_root().get_value('website_languages')
        for name, field in self.get_fields():
            if not field.indexed and not field.stored:
                continue

            if field.multilingual:
                value = {}
                for language in languages:
                    value[language] = field.get_value(self, name, language)
                values[name] = value
            else:
                values[name] = field.get_value(self, name)

        # Step 2. Index non-metadata properties
        # Path related fields
        abspath = self.abspath
        values['abspath'] = str(abspath)
        n = len(abspath)
        values['abspath_depth'] = n
        if n:
            values['parent_paths'] = [str(abspath[:i]) for i in range(n)]

        values['name'] = self.name
        values['is_content'] = self.is_content

        # Class related fields
        values['format'] = self.metadata.format
        values['base_classes'] = []
        for cls in self.__class__.__mro__:
            class_id = getattr(cls, 'class_id', None)
            if class_id:
                values['base_classes'].append(class_id)

        # Links to other resources
        values['owner'] = self.get_owner()
        values['share'] = self.get_share()
        values['links'] = list(self.get_links())
        values['onchange_reindex'] = self.get_onchange_reindex()

        # Full text
        context = get_context()
        try:
            server = context.server
        except AttributeError:
            server = None
        if server is not None and server.index_text:
            try:
                values['text'] = self.to_text()
            except NotImplementedError:
                pass
            except Exception:
                log = 'Indexation failed: %s' % abspath
                log_warning(log, domain='ikaaro')

        # Time events
        reminder, payload = self.next_time_event()
        values['next_time_event'] = reminder
        values['next_time_event_payload'] = dumps(payload)

        # Ok
        return values
Exemple #31
0
def warn_not_indexed_nor_stored(name):
    log_warning(MSG_NOT_INDEXED_NOR_STORED.format(name=name), 'itools.database')
Exemple #32
0
    def get_products(self, context, product_format, categories=[], excluded_products=[]):
        shop = get_shop(self)
        table = self
        if self.get_property("use_shop_configuration"):
            table = shop.get_resource("cross-selling")
        if table.get_property("enabled") is False:
            return

        root = context.root
        products_quantity = table.get_property("products_quantity")

        # Base query
        query = [PhraseQuery("format", product_format), PhraseQuery("workflow_state", "public")]
        # Do not show now buyable products
        group_name = get_group_name(shop, context)
        q = PhraseQuery("not_buyable_by_groups", group_name)
        query.append(NotQuery(q))
        # Excluded products query
        if excluded_products:
            exclude_query = [PhraseQuery("abspath", str(abspath)) for abspath in excluded_products]
            if len(exclude_query) > 1:
                exclude_query = OrQuery(*exclude_query)
            else:
                exclude_query = exclude_query[0]
            query.append(NotQuery(exclude_query))
        # Filter on product title
        filter_text = table.get_property("filter_text")
        if filter_text:
            query.append(PhraseQuery("title", filter_text))
        # Categories query
        mode_categories = table.get_property("categories")
        if mode_categories == "current_category":
            query_categorie = [PhraseQuery("parent_paths", str(x.get_abspath())) for x in categories]
            if len(query_categorie) > 1:
                query.append(OrQuery(*query_categorie))
            elif len(query_categorie) == 1:
                query.append(query_categorie[0])
        elif mode_categories == "one_category":
            query.append(PhraseQuery("parent_paths", table.get_property("specific_category")))
        # Show reductions ?
        promotion = table.get_property("show_product_with_promotion")
        if promotion in ("0", "1"):
            query.append(PhraseQuery("has_reduction", bool(promotion)))

        # Product model
        product_model = table.get_property("product_model")
        if product_model:
            query.append(PhraseQuery("product_model", product_model))
        # Tags
        if table.get_property("tags"):
            query.append(OrQuery(*[PhraseQuery("tags", x) for x in table.get_property("tags")]))

        # Selection in cross selling table
        handler = table.handler
        get_value = handler.get_record_value
        ids = list(handler.get_record_ids_in_order())
        names = []
        for id in ids[:products_quantity]:
            record = handler.get_record(id)
            path = get_value(record, "name")
            names.append(path)
            products_quantity -= 1
            resource = self.get_resource(path, soft=True)
            if resource is None:
                log_warning("Error cross selling, %s" % path)
            elif resource.get_property("state") == "public":
                yield resource

        if products_quantity <= 0:
            return

        if names:
            names_query = [PhraseQuery("name", name) for name in names]
            if len(names_query) > 1:
                names_query = OrQuery(*names_query)
            else:
                names_query = names_query[0]
            query.append(NotQuery(names_query))

        # Complete results
        sort = table.get_property("sort")
        if sort == "random":
            # Random selection
            results = root.search(AndQuery(*query))
            # XXX It's not relevant to make a random cross selling
            # with more than 1000 products
            brains = list(results.get_documents(size=1000))
            shuffle(brains)
            for brain in brains[:products_quantity]:
                yield root.get_resource(brain.abspath)
        elif sort == "last":
            results = root.search(AndQuery(*query))
            brains = list(results.get_documents(sort_by="ctime", reverse=True, size=products_quantity))
            for brain in brains:
                yield root.get_resource(brain.abspath)
Exemple #33
0
    def get_products(self,
                     context,
                     product_format,
                     categories=[],
                     excluded_products=[]):
        shop = get_shop(self)
        table = self
        if self.get_property('use_shop_configuration'):
            table = shop.get_resource('cross-selling')
        if table.get_property('enabled') is False:
            return

        root = context.root
        products_quantity = table.get_property('products_quantity')

        # Base query
        query = [
            PhraseQuery('format', product_format),
            PhraseQuery('workflow_state', 'public')
        ]
        # Do not show now buyable products
        group_name = get_group_name(shop, context)
        q = PhraseQuery('not_buyable_by_groups', group_name)
        query.append(NotQuery(q))
        # Excluded products query
        if excluded_products:
            exclude_query = [
                PhraseQuery('abspath', str(abspath))
                for abspath in excluded_products
            ]
            if len(exclude_query) > 1:
                exclude_query = OrQuery(*exclude_query)
            else:
                exclude_query = exclude_query[0]
            query.append(NotQuery(exclude_query))
        # Filter on product title
        filter_text = table.get_property('filter_text')
        if filter_text:
            query.append(PhraseQuery('title', filter_text))
        # Categories query
        mode_categories = table.get_property('categories')
        if mode_categories == 'current_category':
            query_categorie = [
                PhraseQuery('parent_paths', str(x.get_abspath()))
                for x in categories
            ]
            if len(query_categorie) > 1:
                query.append(OrQuery(*query_categorie))
            elif len(query_categorie) == 1:
                query.append(query_categorie[0])
        elif mode_categories == 'one_category':
            query.append(
                PhraseQuery('parent_paths',
                            table.get_property('specific_category')))
        # Show reductions ?
        promotion = table.get_property('show_product_with_promotion')
        if promotion in ('0', '1'):
            query.append(PhraseQuery('has_reduction', bool(promotion)))

        # Product model
        product_model = table.get_property('product_model')
        if product_model:
            query.append(PhraseQuery('product_model', product_model))
        # Tags
        if table.get_property('tags'):
            query.append(
                OrQuery(*[
                    PhraseQuery('tags', x) for x in table.get_property('tags')
                ]))

        # Selection in cross selling table
        handler = table.handler
        get_value = handler.get_record_value
        ids = list(handler.get_record_ids_in_order())
        names = []
        for id in ids[:products_quantity]:
            record = handler.get_record(id)
            path = get_value(record, 'name')
            names.append(path)
            products_quantity -= 1
            resource = self.get_resource(path, soft=True)
            if resource is None:
                log_warning('Error cross selling, %s' % path)
            elif resource.get_property('state') == 'public':
                yield resource

        if products_quantity <= 0:
            return

        if names:
            names_query = [PhraseQuery('name', name) for name in names]
            if len(names_query) > 1:
                names_query = OrQuery(*names_query)
            else:
                names_query = names_query[0]
            query.append(NotQuery(names_query))

        # Complete results
        sort = table.get_property('sort')
        if sort == 'random':
            # Random selection
            results = root.search(AndQuery(*query))
            # XXX It's not relevant to make a random cross selling
            # with more than 1000 products
            brains = list(results.get_documents(size=1000))
            shuffle(brains)
            for brain in brains[:products_quantity]:
                yield root.get_resource(brain.abspath)
        elif sort == 'last':
            results = root.search(AndQuery(*query))
            brains = list(
                results.get_documents(sort_by='ctime',
                                      reverse=True,
                                      size=products_quantity))
            for brain in brains:
                yield root.get_resource(brain.abspath)