Example #1
0
    def do_POST(self):

        # Security first
        self.__authorize()
        
        # Open a connection to the
        db = subi_db.subi_db_class()

        global rootnode
        try:
            # Get the file from the post
            ctype, pdict = cgi.parse_header(self.headers.getheader('content-type'))
            if ctype == 'multipart/form-data':
                query = cgi.parse_multipart(self.rfile, pdict)
            upfilecontent = query.get('filename')

            # First save it to the data dir
            filename = 'subi_backup_uploaded'
            filepath = path.join('data', filename)
            f = open(filepath, 'w')
            f.write(upfilecontent[0])
            f.close()
            
            # then instantiate it
            db.load_db(filename)

            # Send the filename back
            response = {'ok': True}

        except Exception as e:
            # add call and traceback info to error message so I can debug
            msg = "Requested " + self.path + "\n"
            msg += traceback.format_exc()
            response = {'ok': False, 'error': msg}

        json_response = json.dumps(response)
        self.send_response(200)
        #self.send_header('Content-type', 'application/json')
        self.end_headers()
        #self.wfile.write(json_response)
        return
Example #2
0
    def do_GET(self):

        # Security first
        self.__authorize()

        print ""
        print("Requested " + self.path)
        req = urlparse(self.path)
        q = parse_qs(req.query)
        
        try:
            # serve static content as is
            if req.path in [
                    "/jquery-1.7.1.min.js",
                    "/jquery-ui-1.8.16.min.js",
                    "/jquery.jeditable.mini.js",
                    "/jquery.form.js",
                    "/jquery-ui-1.8.css",
                    "/bootstrap.min.css",
                    "/bootstrap-dropdown.js",
                    "/favicon.ico"]:
                fpath = req.path

            # Handle erroneous requests
            elif req.path.endswith("/404"):
                fpath = "/404.html"

            # return the front page
            elif req.path == "/subi":
                fpath = "/subi.html"

            # handle data requests
            elif req.path == "/subi/ajax":
                self.do_AJAX()
                return

            # Give a csv from full text search
            # TODO move this with other full text search
            # into a non-redundant space
            elif req.path == "/subi/csv":
                self.__generate_temp_csv()

                # Send the file as a response
                self.__serve_file(
                    filename     = 'subi_results.csv', 
                    contents     = open('temp.csv').read(),
                    content_type = 'application/octet-stream'
                )

                return

            # Give a backup
            elif req.path == "/subi/backup":

                # make a new backup
                db = subi_db.subi_db_class()
                filename = db.backup_db()

                # open the backup file
                filepath = path.join('data', filename)

                # Send the file as a response
                self.__serve_file(
                    filename     = filename, 
                    contents     = open(filepath, 'r').read(),
                    content_type = 'application/octet-stream'
                )

                return


            # contents of the data folder should be accessible
            elif req.path == "/subi/data":

                # Determine the request
                requestfile = q['filename'][0]

                if requestfile not in listdir('data'):
                    # Make sure the requested file in in the data directory
                    self.__serve_404()
                    return

                else:
                    # Return the requested file
                    filepath = path.join('data', q['filename'][0])
                    self.__serve_file(
                        filename     = q['filename'][0], 
                        contents     = open(filepath).read(),
                        content_type = 'application/octet-stream'
                    )
                    return
                    
            # And they might want an offline manual
            elif req.path == "/subi/userguide.pdf":
                self.__serve_file(
                    filename     = 'userguide.pdf', 
                    contents     = open('userguide.pdf', 'rb').read(),
                    content_type = 'application/pdf'
                )
                return

            # if the request is not recognized return an error
            else:
                self.__serve_404()
                return

            # by default we return the corresponding file
            # in the web directory
            contents = open(webdir + fpath).read()

            # Determine the content type
            if fpath.endswith(".css"):
                content_type = 'text/css'
            elif fpath.endswith(".js"):
                content_type = 'application/javascript'
            else:
                content_type = 'text/html'
                # Preprocessing {{text_to_translate}} first
                if 'language' not in q:
                    q['language'] = ['english']
                contents = self.__preprocess(contents, q['language'][0])

            self.send_response(200)
            self.send_header('Content-type', content_type)
            self.end_headers()
            self.wfile.write(contents)
            return

        except IOError:
            self.__serve_404()
Example #3
0
    def __generate_temp_csv(self):

        req = urlparse(self.path)
        q = parse_qs(req.query)
    
        # Open a connection to the
        db = subi_db.subi_db_class()

        # Fill in default values
        if 'limit' not in q:
            q['limit'] = [10000]
        if 'offset' not in q:
            q['offset'] = [0]
        if 'search_terms' not in q:
            q['search_terms'] = []
        else:
            # Break search terms by spaces
            # TODO preserve quoted strings
            q['search_terms'] = q['search_terms'][0].split(' ')

        # Request the column info for descriptions
        col_info = db.col_info()
        col_descriptions = []
        col_names = []
        for col in col_info:
            # Remove animal id because its used internally
            # and doesn't make sense to the user
            if(col['col_name'] != 'animal_id'):
                col_names.append(col['col_name'])
                col_descriptions.append(col['col_description'])

        # Request the animals
        result = db.search_fulltext(
                        q['search_terms'],
                        q['offset'][0],
                        q['limit'][0],
                        )

        # Start a csv file
        # We have to jump through some hoops
        # so that excel will recognize our csv, actually tsv.
        # We can't use the built in csv module, b.c. it does 
        # not provide unicode support.
        #
        # Mostly we need to:
        #   Use UTF 16 little endian
        #   use tab seperation
        #   Supply a BOM at teh begining of file to indicate endiness
        #
        # see 
        #   http://stackoverflow.com/questions/451636/whats-the-best-way-to-export-utf8-data-into-excel
        
        f = codecs.open('temp.csv', encoding='utf-16-le', mode='w')
        
        # Write the BOM to let them know its unicode
        f.write('\ufeff')
        
        # Write out the column headers
        header = ''
        for description in col_descriptions:
            # remove dangerous csv chars
            description = str(description).replace(delimiter, '')
            header += description + delimiter
        
        header += '\n'
        f.write(header)

        # Then the animals
        for animal in result['animals']:
            row = ''
            for name in col_names:
                value = unicode(animal[name])
                # remove csv dangerous chars
                value = value.replace(delimiter, '')
                row += value + delimiter

            # Finish the line
            row += '\n'
            f.write(row)
        
        f.close()
Example #4
0
    def do_AJAX(self):
        """
            This is outside the specification of the class.
            It will handle any ajax query with a json response.
            Errors will be noted in json.
        """

        # Security first
        # (though this should have been handled in get or post)
        self.__authorize()

        req = urlparse(self.path)
        q = parse_qs(req.query)

        # Convert query to unicode
        for key, value in q.items():
            q[key][0] = value[0].decode('UTF-8')

        # A helper for developers
        print("Query contains: ")
        for key, value in q.items():
            print("    " + str(key) + ": " + str(value))

        db = subi_db.subi_db_class()

        # Determine command
        if 'command' not in q:
            response = {'error': 'No command in query, ' + self.path}
        else:
            command = q['command'][0]

        # Response is innocent until proven guilty
        response = {}
        response['ok'] = True

        # Execute command
        try:
            if command == "NO COMMAND SENT":
                pass

            elif command == "create_col":
                if 'col_group' not in q:
                    q['col_group'] = [None]
                db.create_col(
                    q['col_name'][0],
                    q['col_type'][0],
                    q['col_desc'][0],
                    q['col_group'][0]
                )

            elif command == "update_col":
                if 'field_value' not in q:
                    q['field_value'] = [None]
                db.update_col(
                    q['col_name'][0],
                    q['field_name'][0],
                    q['field_value'][0]
                )

            elif command == "delete_col":
                db.delete_col(q['col_name'][0])

            elif command == "insert_new_animal":
                print q['animal_id'][0]
                db.insert_new_animal(q['animal_id'][0])

            elif command == "update_animal_field":
                if 'col_value' not in q:
                    q['col_value'] = [None]

                db.update_animal_field(
                        q['animal_id'][0],
                        q['col_name'][0],
                        q['col_value'][0]
                        )

            elif command == "lookup_animal":
                data = db.lookup_animal(q['animal_id'][0])
                response['data'] = data

            elif command == "copy_animal":
                db.copy_animal(q['origin_id'][0], q['copy_id'][0])

            elif command == "animal_exists":
                data = db.animal_exists(q['animal_id'][0])
                response['data'] = data

            elif command == "delete_animal":
                db.delete_animal(q['animal_id'][0])

            elif command == "search_fulltext":
                # Fill in default values
                if 'limit' not in q:
                    q['limit'] = [10]
                if 'offset' not in q:
                    q['offset'] = [0]
                if 'search_terms' not in q:
                    q['search_terms'] = []
                else:
                    # Break search terms by spaces
                    # while preserving quoted strings
                    # We aren't using shlex, b.c. it doesn't have
                    # unicode support.  It should in the future, we
                    # will download it then.
                    q['search_terms'] = q['search_terms'][0].split(' ')

                result = db.search_fulltext(
                        q['search_terms'],
                        q['offset'][0],
                        q['limit'][0],
                        )

                # Template the response
                response['data'] = {}
                response['data']['animals'] = []
                response['data']['count'] = None

                for animal in result['animals']:
                    a = {}
                    for key in animal.keys():
                        a[key] = animal[key]
                    response['data']['animals'].append(a)

                response['data']['count'] = result['count']

            elif command == "col_info":
                data = db.col_info()
                response['data'] = []

                for column in data:
                    d = {}
                    for key in column.keys():
                        d[key] = column[key]
                    response['data'].append(d)

            elif command == "get_unique_col_values":
                if 'min_freq' not in q:
                    q['min_freq'] = [1]
                col_values = db.get_unique_col_values(
                                q['col_name'][0],
                                q['min_freq'][0]
                                )
                response['data'] = col_values

            elif command == "backup_db":
                data = db.backup_db()
                response['data'] = data

            elif command == "delete_backup":
                db.delete_backup(q['filename'][0])

            elif command == "list_backups":
                data = db.list_backups()
                response['data'] = data

            elif command == "load_db":
                db.load_db(q['filename'][0])

            else:
                response = {
                        'ok': False,
                        'error': 'Unrecognized command, ' + command
                        }

        except Exception as e:
            # add call and traceback info to error message so I can debug
            msg = "Requested " + self.path + "\n"
            msg += traceback.format_exc()
            response = {'ok': False, 'error': msg}

        # Tell them we have a good response with json
        # safari coughs if this is not here
        self.send_response(200)
        self.send_header('Content-type', 'application/json')
        self.end_headers()

        # Send back some json
        json_response = json.dumps(response)
        self.wfile.write(json_response)
        return