Beispiel #1
0
 def test_add(self):
     u = Url('https://foob.ar/some/where/some/thing')
     a = Url('http://foob.it/')
     rel = Url('../../rville')
     self.assertEqual(a, u + a)
     self.assertEqual(u, a + u)
     self.assertEqual(Url('https://foob.ar/some/rville'), u + rel)
     self.assertEqual(u, rel + u)
Beispiel #2
0
 def test_init(self):
     flavours = self.url_flavours()
     for f in flavours:
         msg = reduce(lambda a, b: a + b[0], f, '')
         urlstr = reduce(lambda a, b: a + b[1][0], f, '')
         tests = reduce(lambda a, b: a + b[1][1], f, tuple())
         url = Url(urlstr)
         for tname, predicate in tests:
             self.assertTrue(predicate(url), msg=msg + ": " + tname)
         copy = Url(str(url))
         self.assertEqual(str(copy), str(url), msg="copy is not identical")
Beispiel #3
0
    def test_path_append(self):
        u = Url(host='foo.com', scheme='http')
        u.path.append('foo')
        u.path.append('bar')
        self.assertTrue(str(u), 'http://foo.com/foo/bar')

        u = Url(host='foo.com', scheme='http')
        u.path.append('foo/bar')
        self.assertEqual(len(u.path), 2)
        self.assertEqual(u.path[0], 'foo')
        self.assertEqual(u.path[1], 'bar')
        self.assertTrue(str(u), 'http://foo.com/foo/bar')
Beispiel #4
0
 def test_netloc(self):
     u=Url()
     self.assertTrue(u)
     u.username = '******'
     u.password = '******'
     u.host = 'foob.ar'
     self.assertEqual('toto:[email protected]', u.netloc)
     self.assertEqual(None, u.port)
     u.netloc = 'toto.com'
     self.assertEqual(None, u.username)
     self.assertEqual(None, u.password)
     self.assertEqual('toto.com', u.host)
     self.assertEqual(None, u.port)
Beispiel #5
0
 def handle_starttag(self, tag, attrs):
     tag = tag.lower()
     if tag == 'a':
         href = self.__get_attr('href', attrs)
         url = Url(href,
                   default_netloc=self.domain,
                   default_path=self.current.path)
         if self.__sameDomain(url.netloc) and url.scheme == self.scheme:
             req = GetRequest(url)
             if req not in self.requests:
                 self.requests.append(req)
     elif tag == 'img':
         src = self.__get_attr('src', attrs)
         for ext in self.config.AllowedExtensions:
             if re.match(".+\.%s.*" % ext, src):
                 url = Url(src,
                           default_netloc=self.domain,
                           default_path=self.current.path)
                 if self.__sameDomain(
                         url.netloc) and url.scheme == self.scheme:
                     req = GetRequest(url)
                     if req not in self.requests:
                         self.requests.append(req)
                         break
     elif tag == 'frame' or tag == 'iframe':
         src = self.__get_attr('src', attrs)
         url = Url(src,
                   default_netloc=self.domain,
                   default_path=self.current.path)
         if self.__sameDomain(url.netloc) and url.scheme == self.scheme:
             req = GetRequest(url)
             if req not in self.requests:
                 self.requests.append(req)
     elif tag == 'form':
         self.form = {}
         self.form['data'] = {}
         self.form['action'] = self.__get_attr('action', attrs,
                                               self.current.path)
         self.form['method'] = self.__get_attr('method', attrs,
                                               'get').lower()
     elif self.form != None:
         if tag == 'input':
             name = self.__get_attr('name', attrs)
             value = self.__get_attr('value', attrs)
             self.form['data'][name] = value
         elif tag == 'select':
             self.form['data'][self.__get_attr('name', attrs)] = ''
Beispiel #6
0
 def get_user(self, username):
     endpoint = Url(self.base_url)
     endpoint.path.append('users')
     endpoint.path.append(username)
     request = Request('GET', endpoint)
     response = self.user_agent.request(request)
     if response.is_success:
         return json.loads(response.content)
     else:
         raise Exception(response.status_line)
Beispiel #7
0
 def handle_starttag(self, tag, attrs):
     tag = tag.lower()
     if tag == 'a':
         href = self.__get_attr('href', attrs)
         url = Url(href,
                   default_netloc=self.domain,
                   default_path=self.current.path)
         if self.__sameDomain(url.netloc) and url.scheme == self.scheme:
             req = GetRequest(url)
             if req not in self.requests:
                 self.requests.append(req)
     elif tag == 'frame' or tag == 'iframe':
         src = self.__get_attr('src', attrs)
         url = Url(src,
                   default_netloc=self.domain,
                   default_path=self.current.path)
         if self.__sameDomain(url.netloc) and url.scheme == self.scheme:
             req = GetRequest(url)
             if req not in self.requests:
                 self.requests.append(req)
     elif tag == 'form':
         self.form = {}
         self.form['data'] = {}
         self.form['action'] = self.__get_attr('action', attrs,
                                               self.current.path)
         self.form['method'] = self.__get_attr('method', attrs,
                                               'get').lower()
     elif self.form != None:
         if tag == 'input':
             name = self.__get_attr('name', attrs)
             value = self.__get_attr('value', attrs)
             if value == "":
                 value = self.__auto_input_form(name)
             self.form['data'][name] = value
         elif tag == 'select':
             #name = self.__get_attr('name', attrs)   auto  select!!!
             #print  self.__get_attr('value', attrs)
             self.form['data'][self.__get_attr('name', attrs)] = ''
Beispiel #8
0
    def handle_endtag(self, tag):
        tag = tag.lower()
        if tag == 'form' and self.form != None:
            if self.form['method'] == 'get':
                link = self.form['action'] + "?" + urlencode(self.form['data'])
                url = Url(link, default_netloc=self.domain)
                if self.__sameDomain(url.netloc) and url.scheme == self.scheme:
                    req = GetRequest(url)
                    if req not in self.requests:
                        self.requests.append(req)
            elif self.form['method'] == 'post':
                link = self.form['action']
                url = Url(link,
                          default_netloc=self.domain,
                          default_path=self.current.path)
                if self.__sameDomain(url.netloc) and url.scheme == self.scheme:
                    req = PostRequest(url)
                    for name, value in self.form['data'].items():
                        req.addField(name, value)
                    if req not in self.requests:
                        self.requests.append(req)

            self.form = None
Beispiel #9
0
 def test_netloc(self):
     u = Url()
     self.assertTrue(u)
     u.username = '******'
     u.password = '******'
     u.host = 'foob.ar'
     self.assertEqual('toto:[email protected]', u.netloc)
     self.assertEqual(None, u.port)
     u.netloc = 'toto.com'
     self.assertEqual(None, u.username)
     self.assertEqual(None, u.password)
     self.assertEqual('toto.com', u.host)
     self.assertEqual(None, u.port)
Beispiel #10
0
    def parse(self, request):
        if g.O['file-ext'] != None:
            (root, ext) = os.path.splitext(request.url.path)
            if ext[1:] not in g.O['file-ext'] and ext != '':
                self.parsed.append(request)
                return

        if g.O['depth'] != None:
            if len(request.url.path.split('/')) + 1 > g.O['depth']:

                self.parsed.append(request)
                return
        try:
            response = request.fetch()
            response = re.sub("href\s*=\s*([^\"'\s>]+)", r'href="\1"',
                              response)
            response = re.sub("src\s*=\s*([^\"'\s>]+)", r'src="\1"', response)
            response = re.sub("action\s*=\s*([^\"'\s>]+)", r'action="\1"',
                              response)
            response = re.sub("method\s*=\s*([^\"'\s>]+)", r'method="\1"',
                              response)
            response = re.sub("name\s*=\s*([^\"'\s>]+)", r'name="\1"',
                              response)
            response = re.sub("value\s*=\s*([^\"'\s>]+)", r'value="\1"',
                              response)
            self.current = request.url
            self.feed(response)
            self.close()

        except Exception as e:
            #print e
            pass

        finally:
            self.parsed.append(request)
            if request.redirect != None:
                url = Url(request.redirect,
                          default_netloc=self.domain,
                          default_path=self.root.path)
                self.parsed.append(GetRequest(url))

        for req in self.requests:
            if req not in self.parsed:
                self.parse(req)
Beispiel #11
0
    def search(
            self,
            # Search parameters
            client_id=None,
            contact_id=None,
            invoice_number=None,
            status=None,
            payment_type=None,
            from_date=None,
            to_date=None,
            label=None,
            intro=None,
            note=None,
            tags=None,
            article_id=None,
            order_by=None,
            fetch_all=False,
            allow_empty_filter=False,
            keep_old_items=False,
            page=1,
            per_page=None):
        """
        Fills the list with Invoice-objects

        If no search criteria given --> all invoices will returned (REALLY ALL!).

        :param client_id: ID of the client
        :param contact_id: ID of the contact
        :param invoice_number: invoice number
        :param status: Status (DRAFT, OPEN, PAID, OVERDUE, CANCELED).
            More than one statuses could be given as a comma separated list.
            Theses statuses will be logically OR-connected.
        :param payment_type: Payment Type (eg. CASH, BANK_TRANSFER, PAYPAL, ...).
            More than one payment type could be given as a comma separated list.
            Theses payment types will be logically OR-connected.
            You can find a overview of all payment types at API documentation
            of payments.
        :param from_date: (originaly: "from") Only show invoices since this
            date (format YYYY-MM-DD)
        :param to_date: (originaly: "to") Only show invoices up to this
            date (format YYYY-MM-DD)
        :param label: Free text search in label text
        :param intro: Free text search in introductory text
        :param note: Free text search in explanatory notes
        :param tags: Comma seperated list of tags
        :param article_id: ID of an article
        :param order_by: Sortings consist of the name of the field and
            sort order: ASC for ascending resp. DESC for descending order.
            If no order is specified, ascending order (ASC) is used.
            Nested sort orders are possible. Please separate the sort orders by
            comma.

        :param allow_empty_filter: If `True`, every filter-parameter may be empty.
            So, all invoices will returned. !!! EVERY INVOICE !!!
        """

        # Check empty filter
        if not allow_empty_filter:
            if not any([
                    client_id,
                    contact_id,
                    invoice_number,
                    status,
                    payment_type,
                    from_date,
                    to_date,
                    label,
                    intro,
                    note,
                    tags,
                    article_id,
            ]):
                raise errors.EmptyFilterError()

        # Empty the list
        if not keep_old_items:
            while True:
                try:
                    self.pop()
                except IndexError:
                    break

        # Url and system-parameters
        url = Url(path="/api/invoices")
        url.query["page"] = page
        if per_page:
            url.query["per_page"] = per_page
        if order_by:
            url.query["order_by"] = order_by

        # Search parameters
        if client_id:
            url.query["client_id"] = client_id
        if contact_id:
            url.query["contact_id"] = contact_id
        if invoice_number:
            url.query["invoice_number"] = invoice_number
        if status:
            url.query["status"] = status
        if payment_type:
            url.query["payment_type"] = payment_type
        if from_date:
            url.query["from"] = from_date
        if to_date:
            url.query["to"] = to_date
        if label:
            url.query["label"] = label
        if intro:
            url.query["intro"] = intro
        if note:
            url.query["note"] = note
        if tags:
            url.query["tags"] = tags
        if article_id:
            url.query["article_id"] = article_id

        # Fetch data
        response = self.conn.get(path=str(url))

        # Parse XML
        invoices_etree = ET.fromstring(response.data)

        self.per_page = int(invoices_etree.attrib.get("per_page", "100"))
        self.total = int(invoices_etree.attrib.get("total", "0"))
        self.page = int(invoices_etree.attrib.get("page", "1"))
        try:
            self.pages = (self.total // self.per_page) + int(
                bool(self.total % self.per_page))
        except ZeroDivisionError:
            self.pages = 0

        # Iterate over all invoices
        for invoice_etree in invoices_etree:
            self.append(Invoice(conn=self.conn, invoice_etree=invoice_etree))

        # Fetch all
        if fetch_all and self.total > (self.page * self.per_page):
            self.search(
                # Search parameters
                client_id=client_id,
                contact_id=contact_id,
                invoice_number=invoice_number,
                status=status,
                payment_type=payment_type,
                from_date=from_date,
                to_date=to_date,
                label=label,
                intro=intro,
                note=note,
                tags=tags,
                article_id=article_id,
                order_by=order_by,
                fetch_all=fetch_all,
                allow_empty_filter=allow_empty_filter,
                keep_old_items=True,
                page=page + 1,
                per_page=per_page)
Beispiel #12
0
    def search(
        self,
        # Search parameters
        invoice_id = None,
        from_date = None,
        to_date = None,
        type = None,
        user_id = None,
        order_by = None,

        fetch_all = False,
        allow_empty_filter = False,
        keep_old_items = False,
        page = 1,
        per_page = None
    ):
        """
        Fills the (internal) list with InvoicePayment-objects

        If no search criteria given --> all payments will returned (REALLY ALL!).

        :param invoice_id: ID of the invoice

        :param from_date: Original "from"; Only payments since this date

        :param to_date: Original "to"; Only payments up to this date

        :param type: Payment type (eg. CASH, BANK_TRANSFER, PAYPAL, ...).
            More than one payment type could be given as a comma separated list.
            Theses payment types will be logically OR-connected.

        :param user_id: ID of the user

        :param order_by: Sortings consist of the name of the field and
            sort order: ASC for ascending resp. DESC for descending order.
            If no order is specified, ascending order (ASC) is used.
            Nested sort orders are possible. Please separate the sort orders by
            comma.

        :param allow_empty_filter: If `True`, every filter-parameter may be empty.
            All invoice-payments will returned. !!! EVERY !!!
        """

        # Check empty filter
        if not allow_empty_filter:
            if not any([
                invoice_id,
                from_date,
                to_date,
                type,
                user_id,
            ]):
                raise errors.EmptyFilterError()

        # Empty the list
        if not keep_old_items:
            while True:
                try:
                    self.pop()
                except IndexError:
                    break

        # Url and system-parameters
        url = Url(path = "/api/invoice-payments")
        url.query["page"] = page
        if per_page:
            url.query["per_page"] = per_page
        if order_by:
            url.query["order_by"] = order_by

        # Search parameters
        if invoice_id:
            url.query["invoice_id"] = invoice_id
        if from_date:
            url.query["from"] = from_date
        if to_date:
            url.query["to"] = to_date
        if type:
            url.query["type"] = type
        if user_id:
            url.query["user_id"] = user_id

        # Fetch data
        response = self.conn.get(path = str(url))
        if response.status != 200:
            # Check if "Unothorized" --> raise NotFoundError
            errors_etree = ET.fromstring(response.data)
            for error_etree in errors_etree:
                text = error_etree.text
                if text.lower() == "unauthorized":
                    raise errors.NotFoundError(
                        u"invoice_id: {invoice_id}".format(invoice_id = invoice_id)
                    )
            # Other Error
            raise errors.BillomatError(response.data)

        # No response (workaround for inconsistent gziped answer; DecodeError)
        try:
            if len(response.data) == 0:
                return
        except urllib3.exceptions.DecodeError:
            if response.headers.get("content-type", "").lower() != "application/xml":
                return
            else:
                raise

        # Parse XML
        payments_etree = ET.fromstring(response.data)

        self.per_page = int(payments_etree.attrib.get("per_page", "0"))
        self.total = int(payments_etree.attrib.get("total", "0"))
        self.page = int(payments_etree.attrib.get("page", "1"))
        try:
            self.pages = (self.total // self.per_page) + int(bool(self.total % self.per_page))
        except ZeroDivisionError:
            self.pages = 0

        # Iterate over all payments
        for payment_etree in payments_etree:
            self.append(
                InvoicePayment(conn = self.conn, payment_etree = payment_etree)
            )

        # Fetch all
        if fetch_all and self.total > (self.page * self.per_page):
            self.search(
                # Search parameters
                invoice_id = invoice_id,
                from_date = from_date,
                to_date = to_date,
                type = type,
                user_id = user_id,
                order_by = order_by,

                fetch_all = fetch_all,
                allow_empty_filter = allow_empty_filter,
                keep_old_items = True,
                page = page + 1,
                per_page = per_page
            )
Beispiel #13
0
 def test_path_unicode(self):
     u = Url(host='foo.com', scheme='http')
     u.path.append(unicode('/foo/bar/baz'))
     self.assertEqual(len(u.path), 4)
     self.assertEqual(str(u), 'http://foo.com/foo/bar/baz')
Beispiel #14
0
    def search(
        self,
        # Search parameters
        name = None,
        client_number = None,
        email = None,
        first_name = None,
        last_name = None,
        country_code = None,
        note = None,
        invoice_id = None,
        tags = None,
        order_by = None,

        fetch_all = False,
        allow_empty_filter = False,
        keep_old_items = False,
        page = 1,
        per_page = None
    ):
        """
        Fills the (internal) list with Client-objects

        If no search criteria given --> all clients will returned (REALLY ALL!).

        :param name: Company name
        :param client_number: Client number
        :param email: E-mail address
        :param first_name: First name of the contact person
        :param last_name: Last name of the contact person
        :param country_code: Country code as ISO 3166 Alpha-2
        :param note: Note
        :param invoice_id: ID of an invoice of this client,
            multiple values seperated with comma
        :param tags: Comma seperated list of tags
        :param order_by: Sortings consist of the name of the field and
            sort order: ASC for ascending resp. DESC for descending order.
            If no order is specified, ascending order (ASC) is used.
            Nested sort orders are possible. Please separate the sort orders by
            comma.

        :param allow_empty_filter: If `True`, every filter-parameter may be empty.
            All clients will returned. !!! EVERY CLIENT !!!
        """
        
        # Check empty filter
        if not allow_empty_filter:
            if not any([
                name,
                client_number,
                email,
                first_name,
                last_name,
                country_code,
                note,
                invoice_id,
                tags,
            ]):
                raise errors.EmptyFilterError()

        # Empty the list
        if not keep_old_items:
            while True:
                try:
                    self.pop()
                except IndexError:
                    break

        # Url and system-parameters
        url = Url(path = "/api/clients")
        url.query["page"] = page
        if per_page:
            url.query["per_page"] = per_page
        if order_by:
            url.query["order_by"] = order_by

        # Search parameters
        if name:
            url.query["name"] = name
        if client_number:
            url.query["client_number"] = client_number
        if email:
            url.query["email"] = email
        if first_name:
            url.query["first_name"] = first_name
        if last_name:
            url.query["last_name"] = last_name
        if country_code:
            url.query["country_code"] = country_code
        if note:
            url.query["note"] = note
        if invoice_id:
            url.query["invoice_id"] = invoice_id
        if tags:
            url.query["tags"] = tags

        # Fetch data
        response = self.conn.get(path = str(url))

        # Parse XML
        clients_etree = ET.fromstring(response.data)

        self.per_page = int(clients_etree.attrib.get("per_page", "0"))
        self.total = int(clients_etree.attrib.get("total", "0"))
        self.page = int(clients_etree.attrib.get("page", "1"))
        try:
            self.pages = (self.total // self.per_page) + int(bool(self.total % self.per_page))
        except ZeroDivisionError:
            self.pages = 0

        # Iterate over all clients
        for client_etree in clients_etree:
            self.append(Client(conn = self.conn, client_etree = client_etree))

        # Fetch all
        if fetch_all and self.total > (self.page * self.per_page):
            self.search(
                # Search parameters
                name = name,
                client_number = client_number,
                email = email,
                first_name = first_name,
                last_name = last_name,
                country_code = country_code,
                note = note,
                invoice_id = invoice_id,
                tags = tags,
                order_by = order_by,

                fetch_all = fetch_all,
                allow_empty_filter = allow_empty_filter,
                keep_old_items = True,
                page = page + 1,
                per_page = per_page
            )
Beispiel #15
0
    def search(
            self,
            # Search parameters
            reminder_id=None,
            order_by=None,
            fetch_all=False,
            allow_empty_filter=False,
            keep_old_items=False,
            page=1,
            per_page=None):
        """
        Fills the (internal) list with ReminderTag-objects

        If no search criteria given --> all tags will returned (REALLY ALL!).

        :param reminder_id: Reminder ID
        :param order_by: Sortings consist of the name of the field and
            sort order: ASC for ascending resp. DESC for descending order.
            If no order is specified, ascending order (ASC) is used.
            Nested sort orders are possible. Please separate the sort orders by
            comma.

        :param allow_empty_filter: If `True`, every filter-parameter may be empty.
            All reminder-tags will returned. !!! EVERY !!!
        """

        # Check empty filter
        if not allow_empty_filter:
            if not any([
                    reminder_id,
            ]):
                raise errors.EmptyFilterError()

        # Empty the list
        if not keep_old_items:
            while True:
                try:
                    self.pop()
                except IndexError:
                    break

        # Url and system-parameters
        url = Url(path="/api/reminder-tags")
        url.query["page"] = page
        if per_page:
            url.query["per_page"] = per_page
        if order_by:
            url.query["order_by"] = order_by

        # Search parameters
        if reminder_id:
            url.query["reminder_id"] = reminder_id

        # Fetch data
        response = self.conn.get(path=str(url))
        if response.status != 200:
            # Check if "Unothorized" --> raise NotFoundError
            errors_etree = ET.fromstring(response.data)
            for error_etree in errors_etree:
                text = error_etree.text
                if text.lower() == "unauthorized":
                    raise errors.NotFoundError(
                        u"reminder_id: {reminder_id}".format(
                            reminder_id=reminder_id))
            # Other Error
            raise errors.BillomatError(response.data)

        # No response (workaround for inconsistent gziped answer; DecodeError)
        try:
            if len(response.data) == 0:
                return
        except urllib3.exceptions.DecodeError:
            if response.headers.get("content-type",
                                    "").lower() != "application/xml":
                return
            else:
                raise

        # Parse XML
        tags_etree = ET.fromstring(response.data)

        self.per_page = int(tags_etree.attrib.get("per_page", "0"))
        self.total = int(tags_etree.attrib.get("total", "0"))
        self.page = int(tags_etree.attrib.get("page", "1"))
        try:
            self.pages = (self.total // self.per_page) + int(
                bool(self.total % self.per_page))
        except ZeroDivisionError:
            self.pages = 0

        # Iterate over all tags
        for tag_etree in tags_etree:
            self.append(ReminderTag(conn=self.conn, tag_etree=tag_etree))

        # Fetch all
        if fetch_all and self.total > (self.page * self.per_page):
            self.search(
                # Search parameters
                reminder_id=reminder_id,
                fetch_all=fetch_all,
                allow_empty_filter=allow_empty_filter,
                keep_old_items=True,
                page=page + 1,
                per_page=per_page)
    def search(
            self,
            # Search parameters
            client_id=None,
            contact_id=None,
            name=None,
            payment_type=None,
            cycle=None,
            label=None,
            intro=None,
            note=None,
            tags=None,
            order_by=None,
            fetch_all=False,
            allow_empty_filter=False,
            keep_old_items=False,
            page=1,
            per_page=None):
        """
        Fills the list with Recurring-objects

        If no search criteria given --> all recurrings will returned (REALLY ALL!).

        :param client_id: ID of the client
        :param contact_id: ID of the contact
        :param name: The Name of the recurring
        :param payment_type: Payment Type (eg. CASH, BANK_TRANSFER, PAYPAL, ...).
            More than one payment type could be given as a comma separated list.
            Theses payment types will be logically OR-connected.
            You can find a overview of all payment types at API documentation
            of payments.
        :param cycle: Interval (DAILY, WEEKLY, MONTHLY, YEARLY).
        :param label: Free text search in label text
        :param intro: Free text search in introductory text
        :param note: Free text search in explanatory notes
        :param tags: Comma seperated list of tags

        :param order_by: Sortings consist of the name of the field and
            sort order: ASC for ascending resp. DESC for descending order.
            If no order is specified, ascending order (ASC) is used.
            Nested sort orders are possible. Please separate the sort orders by
            comma.

        :param allow_empty_filter: If `True`, every filter-parameter may be empty.
            So, all invoices will returned. !!! EVERY INVOICE !!!
        """

        # Check empty filter
        if not allow_empty_filter:
            if not any([
                    client_id,
                    contact_id,
                    name,
                    payment_type,
                    cycle,
                    label,
                    intro,
                    note,
                    tags,
            ]):
                raise errors.EmptyFilterError()

        # Empty the list
        if not keep_old_items:
            while True:
                try:
                    self.pop()
                except IndexError:
                    break

        # Url and system-parameters
        url = Url(path="/api/recurrings")
        url.query["page"] = page
        if per_page:
            url.query["per_page"] = per_page
        if order_by:
            url.query["order_by"] = order_by

        # Search parameters
        if client_id:
            url.query["client_id"] = client_id
        if contact_id:
            url.query["contact_id"] = contact_id
        if name:
            url.query["name"] = name
        if payment_type:
            url.query["payment_type"] = payment_type
        if cycle:
            url.query["cycle"] = cycle
        if label:
            url.query["label"] = label
        if intro:
            url.query["intro"] = intro
        if note:
            url.query["note"] = note
        if tags:
            url.query["tags"] = tags

        # Fetch data
        response = self.conn.get(path=str(url))

        # Parse XML
        recurrings_etree = ET.fromstring(response.data)

        self.per_page = int(recurrings_etree.attrib.get("per_page", "100"))
        self.total = int(recurrings_etree.attrib.get("total", "0"))
        self.page = int(recurrings_etree.attrib.get("page", "1"))
        try:
            self.pages = (self.total // self.per_page) + int(
                bool(self.total % self.per_page))
        except ZeroDivisionError:
            self.pages = 0

        # Iterate over all recurrings
        for recurring_etree in recurrings_etree:
            self.append(
                Recurring(conn=self.conn, recurring_etree=recurring_etree))

        # Fetch all
        if fetch_all and self.total > (self.page * self.per_page):
            self.search(
                # Search parameters
                client_id=client_id,
                contact_id=contact_id,
                name=name,
                payment_type=payment_type,
                cycle=cycle,
                label=label,
                intro=intro,
                note=note,
                tags=tags,
                order_by=order_by,
                fetch_all=fetch_all,
                allow_empty_filter=allow_empty_filter,
                keep_old_items=True,
                page=page + 1,
                per_page=per_page)
Beispiel #17
0
    def search(
            self,
            # Search parameters
            order_by=None,
            fetch_all=False,
            keep_old_items=False,
            page=1,
            per_page=None):
        """
        Fills the (internal) list with ReminderText-objects

        If no search criteria given --> all email templates will returned (REALLY ALL!).

        :param order_by: Sortings consist of the name of the field and
            sort order: ASC for ascending resp. DESC for descending order.
            If no order is specified, ascending order (ASC) is used.
            Nested sort orders are possible. Please separate the sort orders by
            comma.
        """

        # Empty the list
        if not keep_old_items:
            while True:
                try:
                    self.pop()
                except IndexError:
                    break

        # Url and system-parameters
        url = Url(path="/api/reminder-texts")
        url.query["page"] = page
        if per_page:
            url.query["per_page"] = per_page
        if order_by:
            url.query["order_by"] = order_by

        # Fetch data
        response = self.conn.get(path=str(url))

        # Parse XML
        reminder_texts_etree = ET.fromstring(response.data)

        self.per_page = int(reminder_texts_etree.attrib.get("per_page", "0"))
        self.total = int(reminder_texts_etree.attrib.get("total", "0"))
        self.page = int(reminder_texts_etree.attrib.get("page", "1"))
        try:
            self.pages = (self.total // self.per_page) + int(
                bool(self.total % self.per_page))
        except ZeroDivisionError:
            self.pages = 0

        # Iterate over all email templates
        for reminder_text_etree in reminder_texts_etree:
            self.append(
                ReminderText(conn=self.conn,
                             reminder_text_etree=reminder_text_etree))

        # Fetch all
        if fetch_all and self.total > (self.page * self.per_page):
            self.search(order_by=order_by,
                        fetch_all=fetch_all,
                        keep_old_items=True,
                        page=page + 1,
                        per_page=per_page)
Beispiel #18
0
    def search(
            self,
            # Search parameters
            name=None,
            client_number=None,
            email=None,
            first_name=None,
            last_name=None,
            country_code=None,
            note=None,
            invoice_id=None,
            tags=None,
            order_by=None,
            fetch_all=False,
            allow_empty_filter=False,
            keep_old_items=False,
            page=1,
            per_page=None):
        """
        Fills the (internal) list with Client-objects

        If no search criteria given --> all clients will returned (REALLY ALL!).

        :param name: Company name
        :param client_number: Client number
        :param email: E-mail address
        :param first_name: First name of the contact person
        :param last_name: Last name of the contact person
        :param country_code: Country code as ISO 3166 Alpha-2
        :param note: Note
        :param invoice_id: ID of an invoice of this client,
            multiple values seperated with comma
        :param tags: Comma seperated list of tags
        :param order_by: Sortings consist of the name of the field and
            sort order: ASC for ascending resp. DESC for descending order.
            If no order is specified, ascending order (ASC) is used.
            Nested sort orders are possible. Please separate the sort orders by
            comma.

        :param allow_empty_filter: If `True`, every filter-parameter may be empty.
            All clients will returned. !!! EVERY CLIENT !!!
        """

        # Check empty filter
        if not allow_empty_filter:
            if not any([
                    name,
                    client_number,
                    email,
                    first_name,
                    last_name,
                    country_code,
                    note,
                    invoice_id,
                    tags,
            ]):
                raise errors.EmptyFilterError()

        # Empty the list
        if not keep_old_items:
            while True:
                try:
                    self.pop()
                except IndexError:
                    break

        # Url and system-parameters
        url = Url(path="/api/clients")
        url.query["page"] = page
        if per_page:
            url.query["per_page"] = per_page
        if order_by:
            url.query["order_by"] = order_by

        # Search parameters
        if name:
            url.query["name"] = name
        if client_number:
            url.query["client_number"] = client_number
        if email:
            url.query["email"] = email
        if first_name:
            url.query["first_name"] = first_name
        if last_name:
            url.query["last_name"] = last_name
        if country_code:
            url.query["country_code"] = country_code
        if note:
            url.query["note"] = note
        if invoice_id:
            url.query["invoice_id"] = invoice_id
        if tags:
            url.query["tags"] = tags

        # Fetch data
        response = self.conn.get(path=str(url))

        # Parse XML
        clients_etree = ET.fromstring(response.data)

        self.per_page = int(clients_etree.attrib.get("per_page", "0"))
        self.total = int(clients_etree.attrib.get("total", "0"))
        self.page = int(clients_etree.attrib.get("page", "1"))
        try:
            self.pages = (self.total // self.per_page) + int(
                bool(self.total % self.per_page))
        except ZeroDivisionError:
            self.pages = 0

        # Iterate over all clients
        for client_etree in clients_etree:
            self.append(Client(conn=self.conn, client_etree=client_etree))

        # Fetch all
        if fetch_all and self.total > (self.page * self.per_page):
            self.search(
                # Search parameters
                name=name,
                client_number=client_number,
                email=email,
                first_name=first_name,
                last_name=last_name,
                country_code=country_code,
                note=note,
                invoice_id=invoice_id,
                tags=tags,
                order_by=order_by,
                fetch_all=fetch_all,
                allow_empty_filter=allow_empty_filter,
                keep_old_items=True,
                page=page + 1,
                per_page=per_page)
    def search(
        self,
        # Search parameters
        order_by = None,

        fetch_all = False,
        keep_old_items = False,
        page = 1,
        per_page = None
    ):
        """
        Fills the (internal) list with ReminderText-objects

        If no search criteria given --> all email templates will returned (REALLY ALL!).

        :param order_by: Sortings consist of the name of the field and
            sort order: ASC for ascending resp. DESC for descending order.
            If no order is specified, ascending order (ASC) is used.
            Nested sort orders are possible. Please separate the sort orders by
            comma.
        """
        
        # Empty the list
        if not keep_old_items:
            while True:
                try:
                    self.pop()
                except IndexError:
                    break

        # Url and system-parameters
        url = Url(path = "/api/reminder-texts")
        url.query["page"] = page
        if per_page:
            url.query["per_page"] = per_page
        if order_by:
            url.query["order_by"] = order_by

        # Fetch data
        response = self.conn.get(path = str(url))

        # Parse XML
        reminder_texts_etree = ET.fromstring(response.data)

        self.per_page = int(reminder_texts_etree.attrib.get("per_page", "0"))
        self.total = int(reminder_texts_etree.attrib.get("total", "0"))
        self.page = int(reminder_texts_etree.attrib.get("page", "1"))
        try:
            self.pages = (self.total // self.per_page) + int(bool(self.total % self.per_page))
        except ZeroDivisionError:
            self.pages = 0

        # Iterate over all email templates
        for reminder_text_etree in reminder_texts_etree:
            self.append(
                ReminderText(
                    conn = self.conn,
                    reminder_text_etree = reminder_text_etree
                )
            )

        # Fetch all
        if fetch_all and self.total > (self.page * self.per_page):
            self.search(
                order_by = order_by,
                fetch_all = fetch_all,
                keep_old_items = True,
                page = page + 1,
                per_page = per_page
            )
    def search(
        self,
        # Search parameters
        invoice_id = None,
        from_date = None,
        to_date = None,
        type = None,
        user_id = None,
        order_by = None,

        fetch_all = False,
        allow_empty_filter = False,
        keep_old_items = False,
        page = 1,
        per_page = None
    ):
        """
        Fills the (internal) list with InvoicePayment-objects

        If no search criteria given --> all payments will returned (REALLY ALL!).

        :param invoice_id: ID of the invoice

        :param from_date: Original "from"; Only payments since this date

        :param to_date: Original "to"; Only payments up to this date

        :param type: Payment type (eg. CASH, BANK_TRANSFER, PAYPAL, ...).
            More than one payment type could be given as a comma separated list.
            Theses payment types will be logically OR-connected.

        :param user_id: ID of the user

        :param order_by: Sortings consist of the name of the field and
            sort order: ASC for ascending resp. DESC for descending order.
            If no order is specified, ascending order (ASC) is used.
            Nested sort orders are possible. Please separate the sort orders by
            comma.

        :param allow_empty_filter: If `True`, every filter-parameter may be empty.
            All invoice-payments will returned. !!! EVERY !!!
        """

        # Check empty filter
        if not allow_empty_filter:
            if not any([
                invoice_id,
                from_date,
                to_date,
                type,
                user_id,
            ]):
                raise errors.EmptyFilterError()

        # Empty the list
        if not keep_old_items:
            while True:
                try:
                    self.pop()
                except IndexError:
                    break

        # Url and system-parameters
        url = Url(path = "/api/invoice-payments")
        url.query["page"] = page
        if per_page:
            url.query["per_page"] = per_page
        if order_by:
            url.query["order_by"] = order_by

        # Search parameters
        if invoice_id:
            url.query["invoice_id"] = invoice_id
        if from_date:
            url.query["from"] = from_date
        if to_date:
            url.query["to"] = to_date
        if type:
            url.query["type"] = type
        if user_id:
            url.query["user_id"] = user_id

        # Fetch data
        response = self.conn.get(path = str(url))
        if response.status != 200:
            # Check if "Unothorized" --> raise NotFoundError
            errors_etree = ET.fromstring(response.data)
            for error_etree in errors_etree:
                text = error_etree.text
                if text.lower() == "unauthorized":
                    raise errors.NotFoundError(
                        u"invoice_id: {invoice_id}".format(invoice_id = invoice_id)
                    )
            # Other Error
            raise errors.BillomatError(response.data)

        # No response (workaround for inconsistent gziped answer; DecodeError)
        try:
            if len(response.data) == 0:
                return
        except urllib3.exceptions.DecodeError:
            if response.headers.get("content-type", "").lower() != "application/xml":
                return
            else:
                raise

        # Parse XML
        payments_etree = ET.fromstring(response.data)

        self.per_page = int(payments_etree.attrib.get("per_page", "0"))
        self.total = int(payments_etree.attrib.get("total", "0"))
        self.page = int(payments_etree.attrib.get("page", "1"))
        try:
            self.pages = (self.total // self.per_page) + int(bool(self.total % self.per_page))
        except ZeroDivisionError:
            self.pages = 0

        # Iterate over all payments
        for payment_etree in payments_etree:
            self.append(
                InvoicePayment(conn = self.conn, payment_etree = payment_etree)
            )

        # Fetch all
        if fetch_all and self.total > (self.page * self.per_page):
            self.search(
                # Search parameters
                invoice_id = invoice_id,
                from_date = from_date,
                to_date = to_date,
                type = type,
                user_id = user_id,
                order_by = order_by,

                fetch_all = fetch_all,
                allow_empty_filter = allow_empty_filter,
                keep_old_items = True,
                page = page + 1,
                per_page = per_page
            )
    def search(
        self,
        # Search parameters
        client_id = None,
        client_property_id = None,
        value = None,
        order_by = None,

        fetch_all = False,
        allow_empty_filter = False,
        keep_old_items = False,
        page = 1,
        per_page = None
    ):
        """
        Fills the (internal) list with ClientPropertyValue-objects

        If no search criteria given --> all properties will returned (REALLY ALL!).

        :param client_id: Client ID
        :param client_property_id: Client-Property-ID
        :param value: Value of the Client-Property
        :param order_by: Sortings consist of the name of the field and
            sort order: ASC for ascending resp. DESC for descending order.
            If no order is specified, ascending order (ASC) is used.
            Nested sort orders are possible. Please separate the sort orders by
            comma.

        :param allow_empty_filter: If `True`, every filter-parameter may be empty.
            All client-properties will returned. !!! EVERY !!!
        """

        # Check empty filter
        if not allow_empty_filter:
            if not any([
                client_id,
                client_property_id,
                value
            ]):
                raise errors.EmptyFilterError()

        # Empty the list
        if not keep_old_items:
            while True:
                try:
                    self.pop()
                except IndexError:
                    break

        # Url and system-parameters
        url = Url(path = "/api/client-property-values")
        url.query["page"] = page
        if per_page:
            url.query["per_page"] = per_page
        if order_by:
            url.query["order_by"] = order_by

        # Search parameters
        if client_id:
            url.query["client_id"] = client_id
        if client_property_id:
            url.query["client_property_id"] = client_property_id
        if value is not None:
            url.query["value"] = value

        # Fetch data
        response = self.conn.get(path = str(url))
        if response.status != 200:
            # Check if "Unothorized" --> raise NoClientFoundError
            errors_etree = ET.fromstring(response.data)
            for error_etree in errors_etree:
                text = error_etree.text
                if text.lower() == "unauthorized":
                    raise errors.NotFoundError(
                        u"client_id: {client_id}".format(client_id = client_id)
                    )
            # Other Error
            raise errors.BillomatError(response.data)

        # No response (workaround for inconsistent gziped answer; DecodeError)
        try:
            if len(response.data) == 0:
                return
        except urllib3.exceptions.DecodeError:
            if response.headers.get("content-type", "").lower() != "application/xml":
                return
            else:
                raise

        # Parse XML
        properties_etree = ET.fromstring(response.data)

        self.per_page = int(properties_etree.attrib.get("per_page", "0"))
        self.total = int(properties_etree.attrib.get("total", "0"))
        self.page = int(properties_etree.attrib.get("page", "1"))
        try:
            self.pages = (self.total // self.per_page) + int(bool(self.total % self.per_page))
        except ZeroDivisionError:
            self.pages = 0

        # Iterate over all client-properties
        for property_etree in properties_etree:
            self.append(
                ClientProperty(conn = self.conn, property_etree = property_etree)
            )

        # Fetch all
        if fetch_all and self.total > (self.page * self.per_page):
            self.search(
                # Search parameters
                client_id = client_id,
                client_property_id = client_property_id,
                value = value,

                fetch_all = fetch_all,
                allow_empty_filter = allow_empty_filter,
                keep_old_items = True,
                page = page + 1,
                per_page = per_page
            )
Beispiel #22
0
    def search(
        self,
        # Search parameters
        article_number = None,
        title = None,
        description = None,
        currency_code = None,
        unit_id = None,
        tags = None,
        supplier_id = None,

        order_by = None,
        fetch_all = False,
        allow_empty_filter = False,
        keep_old_items = False,
        page = 1,
        per_page = None
    ):
        """
        Fills the list with Article-objects

        If no search criteria given --> all articles will returned (REALLY ALL!).

        :param article_number: Article number
        :param title: Title
        :param description: Description
        :param currency_code: ISO code of the currency
        :param unit_id: ID of the chosen unit
        :param tags: Comma seperated list of tags
        :param supplier_id: ID of the chosen supplier

        :param order_by: Sortings consist of the name of the field and
            sort order: ASC for ascending resp. DESC for descending order.
            If no order is specified, ascending order (ASC) is used.
            Nested sort orders are possible. Please separate the sort orders by
            comma.

        :param allow_empty_filter: If `True`, every filter-parameter may be empty.
            So, all articles will returned. !!! EVERY INVOICE !!!
        """
        
        # Check empty filter
        if not allow_empty_filter:
            if not any([
                article_number,
                title,
                description,
                currency_code,
                unit_id,
                tags,
                supplier_id,
            ]):
                raise errors.EmptyFilterError()

        # Empty the list
        if not keep_old_items:
            while True:
                try:
                    self.pop()
                except IndexError:
                    break

        # Url and system-parameters
        url = Url(path = "/api/articles")
        url.query["page"] = page
        if per_page:
            url.query["per_page"] = per_page
        if order_by:
            url.query["order_by"] = order_by

        # Search parameters
        if article_number:
            url.query["article_number"] = article_number
        if title:
            url.query["title"] = title
        if description:
            url.query["description"] = description
        if currency_code:
            url.query["currency_code"] = currency_code
        if unit_id:
            url.query["unit_id"] = unit_id
        if tags:
            url.query["tags"] = tags
        if supplier_id:
            url.query["supplier_id"] = supplier_id

        # Fetch data
        response = self.conn.get(path = str(url))

        # Parse XML
        articles_etree = ET.fromstring(response.data)

        self.per_page = int(articles_etree.attrib.get("per_page", "100"))
        self.total = int(articles_etree.attrib.get("total", "0"))
        self.page = int(articles_etree.attrib.get("page", "1"))
        try:
            self.pages = (self.total // self.per_page) + int(bool(self.total % self.per_page))
        except ZeroDivisionError:
            self.pages = 0

        # Iterate over all articles
        for article_etree in articles_etree:
            self.append(Article(conn = self.conn, article_etree = article_etree))

        # Fetch all
        if fetch_all and self.total > (self.page * self.per_page):
            self.search(
                # Search parameters
                article_number = article_number,
                title = title,
                description = description,
                currency_code = currency_code,
                unit_id = unit_id,
                tags = tags,
                supplier_id = supplier_id,

                order_by = order_by,
                fetch_all = fetch_all,
                allow_empty_filter = allow_empty_filter,
                keep_old_items = True,
                page = page + 1,
                per_page = per_page
            )
    def search(
        self,
        # Search parameters
        reminder_id = None,

        order_by = None,
        fetch_all = False,
        keep_old_items = False,
        page = 1,
        per_page = None
    ):
        """
        Fills the list with ReminderItem-objects

        :param reminder_id: ID of the reminder (mandatory)

        :param order_by: Sortings consist of the name of the field and
            sort order: ASC for ascending resp. DESC for descending order.
            If no order is specified, ascending order (ASC) is used.
            Nested sort orders are possible. Please separate the sort orders by
            comma.

        """

        # Check empty param
        if not reminder_id:
            raise errors.EmptyFilterError()

        # Empty the list
        if not keep_old_items:
            while True:
                try:
                    self.pop()
                except IndexError:
                    break

        # Url and system-parameters
        url = Url(path = "/api/reminder-items")
        url.query["page"] = page
        if per_page:
            url.query["per_page"] = per_page
        if order_by:
            url.query["order_by"] = order_by

        # Search parameter
        url.query["reminder_id"] = reminder_id

        # Fetch data
        response = self.conn.get(path = str(url))

        # Parse XML
        reminder_items_etree = ET.fromstring(response.data)

        self.per_page = int(reminder_items_etree.attrib.get("per_page", "100"))
        self.total = int(reminder_items_etree.attrib.get("total", "0"))
        self.page = int(reminder_items_etree.attrib.get("page", "1"))
        try:
            self.pages = (self.total // self.per_page) + int(bool(self.total % self.per_page))
        except ZeroDivisionError:
            self.pages = 0

        # Iterate over all items
        for reminder_item_etree in reminder_items_etree:
            self.append(
                ReminderItem(conn = self.conn, reminder_item_etree = reminder_item_etree)
            )

        # Fetch all
        if fetch_all and self.total > (self.page * self.per_page):
            self.search(
                # Search parameters
                reminder_id = reminder_id,

                order_by = order_by,
                fetch_all = fetch_all,
                keep_old_items = True,
                page = page + 1,
                per_page = per_page
            )
    def search(
            self,
            # Search parameters
            credit_note_id=None,
            order_by=None,
            fetch_all=False,
            keep_old_items=False,
            page=1,
            per_page=None,
            credit_note_ids=None):
        """
        Fills the list with CreditNoteItem-objects

        :param credit_note_id: ID of the credit note (mandatory) or a list of IDs.
            If list with IDs given: The result contains the credit note items of
            many credit notes. Be careful: Too many credit note IDs can produce to
            large responses or to large SQL statements.
            My recommendation: 10-50 credit note IDs at one time.

        :param order_by: Sortings consist of the name of the field and
            sort order: ASC for ascending resp. DESC for descending order.
            If no order is specified, ascending order (ASC) is used.
            Nested sort orders are possible. Please separate the sort orders by
            comma.
        """

        # Check empty param
        if not credit_note_id:
            raise errors.EmptyFilterError()

        # Empty the list
        if not keep_old_items:
            while True:
                try:
                    self.pop()
                except IndexError:
                    break

        # Url and system-parameters
        url = Url(path=CreditNoteItem.base_path)
        url.query["page"] = page
        if per_page:
            url.query["per_page"] = per_page
        if order_by:
            url.query["order_by"] = order_by

        # Search parameter
        if isinstance(credit_note_id, (list, tuple)):
            credit_note_id = ",".join(str(id) for id in set(credit_note_id))

        url.query["credit_note_id"] = credit_note_id

        # Fetch data
        response = self.conn.get(path=str(url))

        # Parse XML
        credit_note_items_etree = ET.fromstring(response.data)

        self.per_page = int(
            credit_note_items_etree.attrib.get("per_page", "100"))
        self.total = int(credit_note_items_etree.attrib.get("total", "0"))
        self.page = int(credit_note_items_etree.attrib.get("page", "1"))
        try:
            self.pages = (self.total // self.per_page) + int(
                bool(self.total % self.per_page))
        except ZeroDivisionError:
            self.pages = 0

        # Iterate over all items
        for credit_note_item_etree in credit_note_items_etree:
            self.append(
                CreditNoteItem(conn=self.conn,
                               credit_note_item_etree=credit_note_item_etree))

        # Fetch all
        if fetch_all and self.total > (self.page * self.per_page):
            self.search(
                # Search parameters
                credit_note_id=credit_note_id,
                order_by=order_by,
                fetch_all=fetch_all,
                keep_old_items=True,
                page=page + 1,
                per_page=per_page)
Beispiel #25
0
    def search(
            self,
            # Search parameters
            client_id=None,
            order_by=None,
            fetch_all=False,
            keep_old_items=False,
            page=1,
            per_page=None):
        """
        Fills the list with Contact-objects

        :param client_id: ID of the client (mandatory)

        :param order_by: Sortings consist of the name of the field and
            sort order: ASC for ascending resp. DESC for descending order.
            If no order is specified, ascending order (ASC) is used.
            Nested sort orders are possible. Please separate the sort orders by
            comma.

        """

        # Check empty param
        if not client_id:
            raise errors.EmptyFilterError()

        # Empty the list
        if not keep_old_items:
            while True:
                try:
                    self.pop()
                except IndexError:
                    break

        # Url and system-parameters
        url = Url(path="/api/contacts")
        url.query["page"] = page
        if per_page:
            url.query["per_page"] = per_page
        if order_by:
            url.query["order_by"] = order_by

        # Search parameter
        url.query["client_id"] = client_id

        # Fetch data
        response = self.conn.get(path=str(url))

        # Parse XML
        contacts_etree = ET.fromstring(response.data)

        self.per_page = int(contacts_etree.attrib.get("per_page", "100"))
        self.total = int(contacts_etree.attrib.get("total", "0"))
        self.page = int(contacts_etree.attrib.get("page", "1"))
        try:
            self.pages = (self.total // self.per_page) + int(
                bool(self.total % self.per_page))
        except ZeroDivisionError:
            self.pages = 0

        # Iterate over all contacts
        for contact_etree in contacts_etree:
            self.append(Contact(conn=self.conn, contact_etree=contact_etree))

        # Fetch all
        if fetch_all and self.total > (self.page * self.per_page):
            self.search(
                # Search parameters
                client_id=client_id,
                order_by=order_by,
                fetch_all=fetch_all,
                keep_old_items=True,
                page=page + 1,
                per_page=per_page)
Beispiel #26
0
    def search(
        self,
        # Search parameters
        client_id = None,
        contact_id = None,
        invoice_number = None,
        status = None,
        payment_type = None,
        from_date = None,
        to_date = None,
        label = None,
        intro = None,
        note = None,
        tags = None,
        article_id = None,

        order_by = None,
        fetch_all = False,
        allow_empty_filter = False,
        keep_old_items = False,
        page = 1,
        per_page = None
    ):
        """
        Fills the list with Invoice-objects

        If no search criteria given --> all invoices will returned (REALLY ALL!).

        :param client_id: ID of the client
        :param contact_id: ID of the contact
        :param invoice_number: invoice number
        :param status: Status (DRAFT, OPEN, PAID, OVERDUE, CANCELED).
            More than one statuses could be given as a comma separated list.
            Theses statuses will be logically OR-connected.
        :param payment_type: Payment Type (eg. CASH, BANK_TRANSFER, PAYPAL, ...).
            More than one payment type could be given as a comma separated list.
            Theses payment types will be logically OR-connected.
            You can find a overview of all payment types at API documentation
            of payments.
        :param from_date: (originaly: "from") Only show invoices since this
            date (format YYYY-MM-DD)
        :param to_date: (originaly: "to") Only show invoices up to this
            date (format YYYY-MM-DD)
        :param label: Free text search in label text
        :param intro: Free text search in introductory text
        :param note: Free text search in explanatory notes
        :param tags: Comma seperated list of tags
        :param article_id: ID of an article
        :param order_by: Sortings consist of the name of the field and
            sort order: ASC for ascending resp. DESC for descending order.
            If no order is specified, ascending order (ASC) is used.
            Nested sort orders are possible. Please separate the sort orders by
            comma.

        :param allow_empty_filter: If `True`, every filter-parameter may be empty.
            So, all invoices will returned. !!! EVERY INVOICE !!!
        """
        
        # Check empty filter
        if not allow_empty_filter:
            if not any([
                client_id,
                contact_id,
                invoice_number,
                status,
                payment_type,
                from_date,
                to_date,
                label,
                intro,
                note,
                tags,
                article_id,
            ]):
                raise errors.EmptyFilterError()

        # Empty the list
        if not keep_old_items:
            while True:
                try:
                    self.pop()
                except IndexError:
                    break

        # Url and system-parameters
        url = Url(path = "/api/invoices")
        url.query["page"] = page
        if per_page:
            url.query["per_page"] = per_page
        if order_by:
            url.query["order_by"] = order_by

        # Search parameters
        if client_id:
            url.query["client_id"] = client_id
        if contact_id:
            url.query["contact_id"] = contact_id
        if invoice_number:
            url.query["invoice_number"] = invoice_number
        if status:
            url.query["status"] = status
        if payment_type:
            url.query["payment_type"] = payment_type
        if from_date:
            url.query["from"] = from_date
        if to_date:
            url.query["to"] = to_date
        if label:
            url.query["label"] = label
        if intro:
            url.query["intro"] = intro
        if note:
            url.query["note"] = note
        if tags:
            url.query["tags"] = tags
        if article_id:
            url.query["article_id"] = article_id

        # Fetch data
        response = self.conn.get(path = str(url))

        # Parse XML
        invoices_etree = ET.fromstring(response.data)

        self.per_page = int(invoices_etree.attrib.get("per_page", "100"))
        self.total = int(invoices_etree.attrib.get("total", "0"))
        self.page = int(invoices_etree.attrib.get("page", "1"))
        try:
            self.pages = (self.total // self.per_page) + int(bool(self.total % self.per_page))
        except ZeroDivisionError:
            self.pages = 0

        # Iterate over all invoices
        for invoice_etree in invoices_etree:
            self.append(Invoice(conn = self.conn, invoice_etree = invoice_etree))

        # Fetch all
        if fetch_all and self.total > (self.page * self.per_page):
            self.search(
                # Search parameters
                client_id = client_id,
                contact_id = contact_id,
                invoice_number = invoice_number,
                status = status,
                payment_type = payment_type,
                from_date = from_date,
                to_date = to_date,
                label = label,
                intro = intro,
                note = note,
                tags = tags,
                article_id = article_id,

                order_by = order_by,
                fetch_all = fetch_all,
                allow_empty_filter = allow_empty_filter,
                keep_old_items = True,
                page = page + 1,
                per_page = per_page
            )
Beispiel #27
0
    def test_final_slash(self):
        u = Url(host='foo.com', scheme='http')
        self.assertEqual(u, 'http://foo.com/')

        u = Url('http://foo.com')
        self.assertEqual(u, 'http://foo.com/')
Beispiel #28
0
    def search(
        self,
        # Search parameters
        client_id = None,
        contact_id = None,
        name = None,
        payment_type = None,
        cycle = None,
        label = None,
        intro = None,
        note = None,
        tags = None,

        order_by = None,
        fetch_all = False,
        allow_empty_filter = False,
        keep_old_items = False,
        page = 1,
        per_page = None
    ):
        """
        Fills the list with Recurring-objects

        If no search criteria given --> all recurrings will returned (REALLY ALL!).

        :param client_id: ID of the client
        :param contact_id: ID of the contact
        :param name: The Name of the recurring
        :param payment_type: Payment Type (eg. CASH, BANK_TRANSFER, PAYPAL, ...).
            More than one payment type could be given as a comma separated list.
            Theses payment types will be logically OR-connected.
            You can find a overview of all payment types at API documentation
            of payments.
        :param cycle: Interval (DAILY, WEEKLY, MONTHLY, YEARLY).
        :param label: Free text search in label text
        :param intro: Free text search in introductory text
        :param note: Free text search in explanatory notes
        :param tags: Comma seperated list of tags

        :param order_by: Sortings consist of the name of the field and
            sort order: ASC for ascending resp. DESC for descending order.
            If no order is specified, ascending order (ASC) is used.
            Nested sort orders are possible. Please separate the sort orders by
            comma.

        :param allow_empty_filter: If `True`, every filter-parameter may be empty.
            So, all invoices will returned. !!! EVERY INVOICE !!!
        """

        # Check empty filter
        if not allow_empty_filter:
            if not any([
                client_id,
                contact_id,
                name,
                payment_type,
                cycle,
                label,
                intro,
                note,
                tags,
            ]):
                raise errors.EmptyFilterError()

        # Empty the list
        if not keep_old_items:
            while True:
                try:
                    self.pop()
                except IndexError:
                    break

        # Url and system-parameters
        url = Url(path = "/api/recurrings")
        url.query["page"] = page
        if per_page:
            url.query["per_page"] = per_page
        if order_by:
            url.query["order_by"] = order_by

        # Search parameters
        if client_id:
            url.query["client_id"] = client_id
        if contact_id:
            url.query["contact_id"] = contact_id
        if name:
            url.query["name"] = name
        if payment_type:
            url.query["payment_type"] = payment_type
        if cycle:
            url.query["cycle"] = cycle
        if label:
            url.query["label"] = label
        if intro:
            url.query["intro"] = intro
        if note:
            url.query["note"] = note
        if tags:
            url.query["tags"] = tags

        # Fetch data
        response = self.conn.get(path = str(url))

        # Parse XML
        recurrings_etree = ET.fromstring(response.data)

        self.per_page = int(recurrings_etree.attrib.get("per_page", "100"))
        self.total = int(recurrings_etree.attrib.get("total", "0"))
        self.page = int(recurrings_etree.attrib.get("page", "1"))
        try:
            self.pages = (self.total // self.per_page) + int(bool(self.total % self.per_page))
        except ZeroDivisionError:
            self.pages = 0

        # Iterate over all recurrings
        for recurring_etree in recurrings_etree:
            self.append(Recurring(conn = self.conn, recurring_etree = recurring_etree))

        # Fetch all
        if fetch_all and self.total > (self.page * self.per_page):
            self.search(
                # Search parameters
                client_id = client_id,
                contact_id = contact_id,
                name = name,
                payment_type = payment_type,
                cycle = cycle,
                label = label,
                intro = intro,
                note = note,
                tags = tags,

                order_by = order_by,
                fetch_all = fetch_all,
                allow_empty_filter = allow_empty_filter,
                keep_old_items = True,
                page = page + 1,
                per_page = per_page
            )
Beispiel #29
0

class Worker(threading.Thread):
    def __init__(self):
        threading.Thread.__init__(self)

    def run(self):
        while 1:
            if task_queue.empty() == True:
                break
            task = task_queue.get()
            module[task['module']].exploit(task['request'])


if __name__ == '__main__':
    target = Url("http://w")
    o = {
        "depth": 5,
        "ext":
        ['cgi', 'cfm', 'asp', 'aspx', 'jsp', 'php', 'htm', 'html', 'do'],
    }
    thread = 10
    #module_list=["sqli","xss","lfi","ftp_login","ssh_login"]
    module_list = ["sqli", "xss"]
    module = {}
    ya = Crawler(target, o)
    ya.parse(GetRequest(target))
    task_queue = Queue.Queue()
    for item in module_list:
        module[item] = __import__(item)
        for request in ya.requests:
Beispiel #30
0
    def parse(self, request):
        # check for a valid extension
        if self.config.AllowedExtensions != None:
            (root, ext) = os.path.splitext(request.url.path)
            if ext[1:] not in self.config.AllowedExtensions and ext != '':
                self.ed.warning(
                    "Skipping page with unallowed extension '%s' ." %
                    request.url.path)
                self.parsed.append(request)
                return
        # check directory depth
        if self.config.MaxDirectoryDepth != None:
            if len(request.url.path.split(
                    '/')) + 1 > self.config.MaxDirectoryDepth:
                self.ed.warning("Max directory depth exceeded '%s' ." %
                                request.url.path)
                self.parsed.append(request)
                return
        # if enabled, delay the crawl process
        if self.config.CrawlDelayEnabled != None and self.config.CrawlDelayEnabled == True:
            self.ed.warning("Delaying crawling process of %d ms ..." %
                            self.config.CrawlDelay)
            time.sleep(self.config.CrawlDelay / 1000.0)

        try:
            # set user-agent if specified
            if self.config.UserAgent != None:
                request.setHeader('User-Agent', self.config.UserAgent)
            # set proxy if specified
            if self.config.ProxyEnabled != None and self.config.ProxyEnabled == True:
                self.ed.status(
                    "Setting request proxy to %s:%d ." %
                    (self.config.ProxyServer, self.config.ProxyPort))
                request.setProxy(self.config.ProxyServer,
                                 self.config.ProxyPort)

            response = request.fetch()
            # fix broken html
            response = re.sub("href\s*=\s*([^\"'\s>]+)", r'href="\1"',
                              response)
            response = re.sub("src\s*=\s*([^\"'\s>]+)", r'src="\1"', response)
            response = re.sub("action\s*=\s*([^\"'\s>]+)", r'action="\1"',
                              response)
            response = re.sub("method\s*=\s*([^\"'\s>]+)", r'method="\1"',
                              response)
            response = re.sub("name\s*=\s*([^\"'\s>]+)", r'name="\1"',
                              response)
            response = re.sub("value\s*=\s*([^\"'\s>]+)", r'value="\1"',
                              response)

            response = BeautifulSoup(response).prettify()

            self.current = request.url

            self.ed.parsing(request.url)

            self.feed(response)
            self.close()

            # custom parsing
            pages = re.findall('window\.open\s*\(\s*[\'"]([^\'"]+)', response)
            if pages != None:
                for page in pages:
                    url = Url(page,
                              default_netloc=self.domain,
                              default_path=self.root.path)
                    if url.netloc == self.domain and url.scheme == self.scheme:
                        req = GetRequest(url)
                        if req not in self.requests:
                            self.requests.append(req)
        except HTTPError as e:
            self.ed.warning("%s (%s)" % (request.url.get(), e))
        except Exception as e:
            self.ed.warning(e)
        finally:
            self.parsed.append(request)
            if request.redirect != None:
                url = Url(request.redirect,
                          default_netloc=self.domain,
                          default_path=self.root.path)
                self.parsed.append(GetRequest(url))

        for req in self.requests:
            if req not in self.parsed:
                self.parse(req)
Beispiel #31
0
    def search(
            self,
            # Search parameters
            article_number=None,
            title=None,
            description=None,
            currency_code=None,
            unit_id=None,
            tags=None,
            supplier_id=None,
            order_by=None,
            fetch_all=False,
            allow_empty_filter=False,
            keep_old_items=False,
            page=1,
            per_page=None):
        """
        Fills the list with Article-objects

        If no search criteria given --> all articles will returned (REALLY ALL!).

        :param article_number: Article number
        :param title: Title
        :param description: Description
        :param currency_code: ISO code of the currency
        :param unit_id: ID of the chosen unit
        :param tags: Comma seperated list of tags
        :param supplier_id: ID of the chosen supplier

        :param order_by: Sortings consist of the name of the field and
            sort order: ASC for ascending resp. DESC for descending order.
            If no order is specified, ascending order (ASC) is used.
            Nested sort orders are possible. Please separate the sort orders by
            comma.

        :param allow_empty_filter: If `True`, every filter-parameter may be empty.
            So, all articles will returned. !!! EVERY INVOICE !!!
        """

        # Check empty filter
        if not allow_empty_filter:
            if not any([
                    article_number,
                    title,
                    description,
                    currency_code,
                    unit_id,
                    tags,
                    supplier_id,
            ]):
                raise errors.EmptyFilterError()

        # Empty the list
        if not keep_old_items:
            while True:
                try:
                    self.pop()
                except IndexError:
                    break

        # Url and system-parameters
        url = Url(path="/api/articles")
        url.query["page"] = page
        if per_page:
            url.query["per_page"] = per_page
        if order_by:
            url.query["order_by"] = order_by

        # Search parameters
        if article_number:
            url.query["article_number"] = article_number
        if title:
            url.query["title"] = title
        if description:
            url.query["description"] = description
        if currency_code:
            url.query["currency_code"] = currency_code
        if unit_id:
            url.query["unit_id"] = unit_id
        if tags:
            url.query["tags"] = tags
        if supplier_id:
            url.query["supplier_id"] = supplier_id

        # Fetch data
        response = self.conn.get(path=str(url))

        # Parse XML
        articles_etree = ET.fromstring(response.data)

        self.per_page = int(articles_etree.attrib.get("per_page", "100"))
        self.total = int(articles_etree.attrib.get("total", "0"))
        self.page = int(articles_etree.attrib.get("page", "1"))
        try:
            self.pages = (self.total // self.per_page) + int(
                bool(self.total % self.per_page))
        except ZeroDivisionError:
            self.pages = 0

        # Iterate over all articles
        for article_etree in articles_etree:
            self.append(Article(conn=self.conn, article_etree=article_etree))

        # Fetch all
        if fetch_all and self.total > (self.page * self.per_page):
            self.search(
                # Search parameters
                article_number=article_number,
                title=title,
                description=description,
                currency_code=currency_code,
                unit_id=unit_id,
                tags=tags,
                supplier_id=supplier_id,
                order_by=order_by,
                fetch_all=fetch_all,
                allow_empty_filter=allow_empty_filter,
                keep_old_items=True,
                page=page + 1,
                per_page=per_page)
    def search(
        self,
        # Search parameters
        invoice_id = None,

        order_by = None,
        fetch_all = False,
        keep_old_items = False,
        page = 1,
        per_page = None,

        invoice_ids = None
    ):
        """
        Fills the list with InvoiceItem-objects

        :param invoice_id: ID of the invoice (mandatory) or a list of IDs.
            If list with IDs given: The result contains the invoice-items of
            many invoices. Be careful: Too many invoice IDs can produce to
            large responses or to large SQL statements.
            My recommendation: 10-50 invoice IDs at one time.

        :param order_by: Sortings consist of the name of the field and
            sort order: ASC for ascending resp. DESC for descending order.
            If no order is specified, ascending order (ASC) is used.
            Nested sort orders are possible. Please separate the sort orders by
            comma.
        """

        # Check empty param
        if not invoice_id:
            raise errors.EmptyFilterError()

        # Empty the list
        if not keep_old_items:
            while True:
                try:
                    self.pop()
                except IndexError:
                    break

        # Url and system-parameters
        url = Url(path = "/api/invoice-items")
        url.query["page"] = page
        if per_page:
            url.query["per_page"] = per_page
        if order_by:
            url.query["order_by"] = order_by

        # Search parameter
        if isinstance(invoice_id, (list, tuple)):
            invoice_id = ",".join(str(id) for id in set(invoice_id))

        url.query["invoice_id"] = invoice_id

        # Fetch data
        response = self.conn.get(path = str(url))

        # Parse XML
        invoice_items_etree = ET.fromstring(response.data)

        self.per_page = int(invoice_items_etree.attrib.get("per_page", "100"))
        self.total = int(invoice_items_etree.attrib.get("total", "0"))
        self.page = int(invoice_items_etree.attrib.get("page", "1"))
        try:
            self.pages = (self.total // self.per_page) + int(bool(self.total % self.per_page))
        except ZeroDivisionError:
            self.pages = 0

        # Iterate over all items
        for invoice_item_etree in invoice_items_etree:
            self.append(
                InvoiceItem(conn = self.conn, invoice_item_etree = invoice_item_etree)
            )

        # Fetch all
        if fetch_all and self.total > (self.page * self.per_page):
            self.search(
                # Search parameters
                invoice_id = invoice_id,

                order_by = order_by,
                fetch_all = fetch_all,
                keep_old_items = True,
                page = page + 1,
                per_page = per_page
            )