示例#1
0
文件: render.py 项目: zhiiker/FarBox
def render_template_for_farbox_bucket(**kwargs):
    #import time; time.sleep(5) # test timeout
    request_path = get_request_path()
    template_name = request_path.strip('/')
    if not template_name:
        template_name = 'index'
    try:
        template = farbox_bucket_env.get_template(template_name)
        html = template.render(**kwargs)
        return after_render_template_for_farbox_bucket(html)
    except TemplateNotFound as e:
        # 尝试走一些 builtin themes
        sub_site_html = show_builtin_theme_as_sub_site()
        if sub_site_html:
            return after_render_template_for_farbox_bucket(sub_site_html)
        bucket = get_bucket_in_request_context()
        hide_post_prefix = get_site_config('hide_post_prefix', default_value=False)
        if bucket and hide_post_prefix: # 不带 /post 前缀的
            post_doc = get_record_by_url(bucket, template_name)
            if post_doc:
                try: post_template = farbox_bucket_env.get_template("post")
                except: post_template = None
                if post_template:
                    html = post_template.render(**kwargs)
                    return after_render_template_for_farbox_bucket(html)
        if e.name == "index":
            abort(404, Html.i18n("please custom your template or choose a theme for site first, no homepage found."))
        else:
            if request_path.strip("/") == "feed" and not has_template_by_name("feed"):
                # 如果没有自定义 feed 页面,系统默认配置的
                return render_api_template_as_response("feed.jade")
            else:
                abort(404, 'not found for %s' % e.name)
    except Exception as e:
        raise e
示例#2
0
def get_site_config(fields, type_required=None, default_value=None):
    if isinstance(type_required, list):
        type_required = tuple(type_required)
    bucket = get_bucket_in_request_context()
    if not bucket:
        if default_value is not None:
            return default_value
        else:
            return None
    site_configs = get_bucket_site_configs(bucket)
    if not isinstance(fields, (list, tuple)):
        fields = [fields]
    for field in fields:
        if not isinstance(field, string_types):
            continue
        field_value = get_value_from_data(site_configs, field)
        if field_value is not None:
            if type_required:
                if isinstance(field_value, type_required):
                    return field_value
            else:
                return auto_type(field_value)
    if default_value is not None:
        return default_value
    else:
        return None
示例#3
0
def render_as_static_resource_in_pages_for_farbox_bucket(template_filename):
    ext = os.path.splitext(template_filename)[-1].lower()
    if ext not in [
            '.html', '.htm', '.js', '.css', '.json', '.jpg', '.png', '.scss',
            '.less', '.coffee'
    ]:
        return
    mime_type = ''
    raw_content = ''
    pages_configs = get_pages_configs()
    if not is_doc_modified(doc=pages_configs, date_field='mtime'):
        return get_304_response()
    if ext in ['.scss', '.less']:
        raw_content = get_template_static_resource_content('.'.join(
            [template_filename.rsplit('.')[0], 'css']))
        mime_type = 'text/css'
    elif ext in ['.coffee']:
        raw_content = get_template_static_resource_content('.'.join(
            [template_filename.rsplit('.')[0], 'js']))
        mime_type = 'application/javascript'
    if not raw_content:
        raw_content = get_template_static_resource_content(template_filename)
    if raw_content:
        raw_content = to_bytes(raw_content)
        mime_type = mime_type or guess_type(
            template_filename) or 'application/octet-stream'
        set_context_value_from_request("is_template_resource", True)
        file_response = send_file(io.BytesIO(raw_content), mimetype=mime_type)
        bucket = get_bucket_in_request_context()
        if bucket:
            set_304_response_for_doc(response=file_response,
                                     doc=pages_configs,
                                     date_field='mtime')
        return file_response
示例#4
0
def cache_response_into_memcache(response):
    from farbox_bucket.server.web_app import sentry_client
    cache_client = get_cache_client()
    if not cache_client:
        return response
    bucket = get_bucket_in_request_context()
    if not bucket:
        return response

    render_data = response_to_render_data(response)
    if render_data:  # 尝试缓存到 memcache 里
        cache_expiration_time = 2 * 3600  # 2小时的缓存期
        cache_key = get_cache_key_for_page()  # 得到缓存的 key 值
        if not cache_key:
            return response
        to_cache = pickle.dumps(render_data)
        cache_client.set(cache_key,
                         to_cache,
                         zipped=True,
                         expiration=cache_expiration_time)

        if sentry_client:  # for debug
            cached_data = cache_client.get(cache_key, zipped=True)
            try:
                if cached_data and isinstance(cached_data,
                                              (str, unicode)) and re.match(
                                                  r'^\d$', cached_data):
                    raise TypeError("meme cache error?")
            except:
                sentry_client.captureException()
    return response
示例#5
0
def get_post_with_greed(url_body, parent_doc=None):
    pure_url_body = re.split("[?#]", url_body)[0]
    post_url = pure_url_body
    d = get_data_namespace()
    post_doc = d.get_doc(post_url)
    current_data_root = get_current_data_root()
    parent_doc = parent_doc or get_doc_in_request()
    if not post_doc and is_a_markdown_file(post_url) and parent_doc and isinstance(parent_doc, dict):
        filename = post_url
        if "/post/" in filename:
            filename = filename.split("/post/", 1)[-1]
        parent_post_doc_path = get_path_from_record(parent_doc)
        if parent_post_doc_path:
            post_doc_parent = os.path.split(parent_post_doc_path)[0]
            if post_doc_parent:
                abs_path = "%s/%s" % (post_doc_parent.strip("/"), filename.strip("/"))
                post_doc = d.get_doc_by_path(abs_path)

        if current_data_root and not post_doc:  # 增加 wiki_root 作为前缀,再尝试匹配
            abs_path = "%s/%s" % (current_data_root, filename.strip("/"))
            post_doc = d.get_doc_by_path(abs_path)

    if not post_doc:  # 尝试 hit keyword 的方式进行搜索匹配
        bucket = get_bucket_in_request_context()
        post_name = (get_get_var(url_body, "name") or "").strip()
        if post_name:
            if "." in post_name:
                post_name = os.path.splitext(post_name)[0]
            post_doc = get_one_post_by_es(bucket, keywords=post_name, under=current_data_root)
        if not post_doc and is_a_markdown_file(post_url): # 直接搜索 filename
            just_post_file_name = get_just_name(post_url)
            if just_post_file_name != post_name:
                post_doc = get_one_post_by_es(bucket, keywords=just_post_file_name, under=current_data_root)
    return post_doc
示例#6
0
def posts_count(obj):
    if get_type_from_record(obj) == "folder":
        bucket = get_bucket_in_request_context()
        return get_folder_children_count(bucket,
                                         obj.get("path"),
                                         field="posts")
    return 0
示例#7
0
def get_site_configs():
    bucket = get_bucket_in_request_context()
    if not bucket:
        return {}
    site_configs = get_bucket_site_configs(bucket)
    if not isinstance(site_configs, dict):
        site_configs = {}
    return site_configs
示例#8
0
def get_bucket_for_file_manager():
    bucket = get_bucket_in_request_context() or request.values.get('bucket')
    if not bucket:
        bucket = get_bucket_from_request()
    if not is_bucket_login(bucket=bucket):
        abort(401)
    if not bucket:
        abort(404)
    return bucket
示例#9
0
文件: record.py 项目: zhiiker/FarBox
def get_records_for_request_resolver(key):
    if not hasattr(request, 'cached_records_for_resolver'):
        request.cached_records_for_resolver = {}

    key = key.lower().strip()
    if key in request.cached_records_for_resolver:  # cached value
        return request.cached_records_for_resolver[key]

    if not re.match('r?records(_\d+)?$', key):
        return None

    bucket = get_bucket_in_request_context()
    if not bucket:
        return []

    if key.startswith('rrecords'):
        reverse_scan = True
    else:
        reverse_scan = False

    if '_' in key:
        per_page = key.split('_')[-1]
        if not per_page:
            per_page = 100  # default value
        else:
            per_page = int(per_page)
    else:
        per_page = 100

    if per_page < 1:
        per_page = 1
    if per_page > 1000:  # max_value
        per_page = 1000

    icursor = request.values.get('icursor')
    cursor = request.values.get('cursor') or icursor
    if not reverse_scan:
        start_record_id = cursor or zero_id_for_finder
        end_record_id = ''
    else:
        start_record_id = cursor or ''
        end_record_id = zero_id_for_finder

    includes_start_record_id = bool(icursor)

    records = get_records_for_bucket(
        bucket,
        start_record_id=start_record_id,
        end_record_id=end_record_id,
        limit=per_page,
        reverse_scan=reverse_scan,
        includes_start_record_id=includes_start_record_id,
    )

    request.cached_records_for_resolver[key] = records

    return records
示例#10
0
文件: html.py 项目: zhiiker/FarBox
 def debug(self):
     bucket = get_bucket_in_request_context()
     if not bucket:
         return ''
     js_script_content = self.load('/__realtime.js') + self.load(
         '/__debug_template.js')
     js_script_content += '<script>connect_to_ws_by_listen_files("%s")</script>' % get_bucket_ws_url(
         bucket)
     return js_script_content
示例#11
0
def just_get_site_config(config_key, default_value=None):
    bucket = get_bucket_in_request_context()
    if not bucket:
        if default_value is not None:
            return default_value
        else:
            return None
    site_configs = get_bucket_site_configs(bucket) or {}
    value = site_configs.get(config_key, default_value)
    return value
示例#12
0
文件: render.py 项目: zhiiker/FarBox
def render_404_for_farbox_bucket():
    bucket = get_bucket_in_request_context()
    if not bucket:
        return
    try:
        reset_loads_in_page_in_request()
        template = farbox_bucket_env.get_template("404")
        html = template.render()
        return html
    except:
        return
示例#13
0
def do_get_smart_scss_url(scss_filepath, **kwargs):
    # 根据其内容内的变量名,进行替换处理;
    #  总是要读取源文件的,不然不知道是否要重新编译; 由于页面本身的缓存逻辑,性能影响有限
    # filename.scss -> filename-xxxxxxxxxxxx.css
    ext = os.path.splitext(scss_filepath)[-1]
    if ext not in [".less", ".scss"]:
        return scss_filepath  #ignore

    prefix_name = get_prefix_name_from_source_filepath(scss_filepath)
    filename = get_md5(get_md5(kwargs.keys()) +
                       get_md5(kwargs.values())) + '.css'
    filepath = '/_cache/scss/%s-%s' % (prefix_name, filename)

    bucket = get_bucket_in_request_context() or get_bucket_from_request()
    if not bucket:
        return scss_filepath  # ignore

    if has_record_by_path(bucket, path=filepath):
        # 缓存的文件已经存在了
        return filepath

    raw_content = ""
    if scss_filepath.startswith("/fb_static/"):
        raw_content = get_static_raw_content(scss_filepath)
    else:
        bucket = get_bucket_in_request_context()
        if bucket:
            raw_content = get_raw_content_by_path(bucket=bucket,
                                                  path=scss_filepath)
    if not raw_content:
        return scss_filepath  #ignore

    css_content = replace_vars_in_scss(raw_content=raw_content,
                                       new_vars=kwargs,
                                       compile_scss=True)
    sync_file_by_server_side(bucket=bucket,
                             relative_path=filepath,
                             content=css_content)

    return filepath
示例#14
0
def get_request_path_for_bucket(path=None):
    if path is None:
        request_path = request.path
    else:
        request_path = path
    bucket = get_bucket_in_request_context()
    if bucket and bucket in request_path:
        try:
            request_path = re.search('/%s/\w+(/.*|$)' % bucket,
                                     request_path).group(1)
        except:
            pass
    return request_path
示例#15
0
def cover(obj):
    if get_type_from_record(obj) == "folder":
        bucket = get_bucket_in_request_context()
        path = obj.get("path")
        if bucket and path:
            result = get_data(type="image",
                              path=path,
                              level=1,
                              limit=1,
                              sort="-date")
            if result:
                return get_doc_url(result[0])
    return ""
示例#16
0
def get_post_visits_count(doc, field='visits'):
    # field is in ['visits', 'visitors']
    bucket = get_bucket_in_request_context()
    if not bucket:
        return 0
    visits_db_name = get_visits_db_name_for_bucket(bucket)
    doc_path = doc.get('path')
    if not doc_path:
        return 0
    key = get_visits_key(doc_path, field=field)
    count = hget(visits_db_name, key) or 0
    count = to_int(count, default_if_fail=0)
    return count
示例#17
0
 def is_trade_under_this_site(self):
     # 校验当前回调的交易,是不是从当前网站发出去的
     out_trade_no = request.values.get('out_trade_no') or ''
     if '-' not in out_trade_no:
         # 没有在trade_no 中增加site的信息,ignore掉, return True
         return True
     bucket = get_bucket_in_request_context()
     if bucket:  # site_id hashed 长度为 32, 总长度为 14+8+1+32=55 < 64
         hashed_bucket_id = get_md5(bucket)  # 主要用作校验,避免跨站的交易被验证成功
         if out_trade_no and out_trade_no.endswith(
                 '-%s' % hashed_bucket_id):
             return True
     return False
示例#18
0
def get_current_data_root():
    bucket = get_bucket_in_request_context()
    if not bucket:
        return ""
    data_root = get_data_root_in_request()
    if data_root:
        return data_root
    site_configs = get_bucket_site_configs(bucket)
    if site_configs:
        data_root = smart_unicode(site_configs.get("posts_root") or "").strip().strip("/")
        return data_root
    else:
        return ""
示例#19
0
def get_cache_key_for_page():
    bucket = get_bucket_in_request_context()
    if not bucket:
        return
    bucket_last_updated_at = get_bucket_last_updated_at(bucket)
    if not bucket_last_updated_at:
        return
    url = request.url
    raw_cache_key = '%s-%s-%s-%s' % (bucket, bucket_last_updated_at, url,
                                     PAGE_CACHE_VERSION)
    lang = get_language()
    if lang:
        raw_cache_key += "-%s" % lang
    cache_key = "page-%s" % get_md5(raw_cache_key)
    return cache_key
示例#20
0
    def get_out_trade_no(self, prefix=''):  # 64位最长
        # 商户网站唯一订单号
        prefix = smart_unicode(prefix)[:10]  # 最多10位
        now = get_cn_timestamp('%Y%m%d%H%M%S')  # 14位了已经
        uid = uuid.uuid1().hex[:8]
        no = '%s%s%s' % (prefix, now, uid)
        try:
            bucket = get_bucket_in_request_context()
            if bucket:  # site_id hashed 长度为 32, 总长度为 14+8+1+32=55 < 64
                hashed_bucket_id = get_md5(bucket)  # 主要用作校验,避免跨站的交易被验证成功
                no = '%s-%s' % (no, hashed_bucket_id)
        except:
            pass

        return no
示例#21
0
def auto_bucket_url_path(url_path):
    if not url_path.startswith('/'):
        return url_path
    if url_path.startswith('/__'):
        return url_path
    if url_path.startswith('#'):
        return url_path
    request_path = request.path
    bucket = get_bucket_in_request_context()
    if bucket and bucket in request_path:
        p1, p2 = request_path.split(bucket, 1)
        prefix = p1 + bucket + '/' + p2.strip('/').split('/')[0]
        if url_path.lstrip('/').startswith(prefix.lstrip('/')):
            return url_path
        url_path = prefix + '/' + url_path.lstrip('/')
    return url_path
示例#22
0
 def __init__(self, path_or_record):
     # the record is folder
     self.bucket = get_bucket_in_request_context()
     if isinstance(path_or_record, dict):
         self.raw = path_or_record
         self.path = self.raw.get('path')
     else:
         path = path_or_record
         path = smart_unicode(path).strip()
         self.path = path
         record = get_record_by_path(bucket=self.bucket, path=path) or {}
         self.raw = record
     self.path = self.path.lower()
     if self.raw and self.raw.get('_type') != 'folder':
         # must be folder
         self.raw = {}
示例#23
0
def update_usage_statistics(response):
    bucket = get_bucket_in_request_context()
    if not bucket:
        return

    if not isinstance(response, Response):
        return
    # requests + 1
    spawn(increase_request_for_bucket, bucket)

    if response.status_code not in [
            301,
            302,
    ]:
        bandwidth = response.content_length
        if bandwidth:
            spawn(increase_bandwidth_for_bucket, bucket, bandwidth)
示例#24
0
def render_as_static_file_for_farbox_bucket(path):
    if not path or path == "/":
        path = "index.html"
    bucket = get_bucket_in_request_context()
    if not bucket:
        return
    record = get_record_by_path(bucket, path)
    if path == "favicon.ico" and not record:
        record = get_record_by_path(bucket,
                                    "_direct/favicon.ico")  # 兼容 Bitcron
    if not record:
        return
    record_path = get_path_from_record(record)
    if record_path and record_path.startswith("/_data/"):
        ext = os.path.splitext(record_path)[-1].strip(".").lower()
        if ext in ["csv"] and not is_bucket_login(bucket):
            return abort(
                404, "csv under /_data is not allowed to download directly")
    set_context_value_from_request("is_static_file", True)
    if record.get('compiled_type') and record.get('compiled_content'):
        raw_content = record.get('compiled_content')
        content_type = record.get('compiled_type')
        raw_content = to_bytes(raw_content)
        mimetype = content_type or guess_type(
            path) or 'application/octet-stream'
        compiled_file_response = send_file(io.BytesIO(to_bytes(raw_content)),
                                           mimetype=mimetype)
        return compiled_file_response
    else:
        # 先对应是否防盗链的逻辑
        site_configs = get_bucket_site_configs(bucket)
        anti_theft_chain = site_configs.get("anti_theft_chain", True)
        if anti_theft_chain and request.path.strip('/') in ['favicon.ico']:
            anti_theft_chain = False
        if anti_theft_chain and request.referrer:
            refer_host = get_host_from_url(request.referrer)
            if refer_host != request.host and "." in request.path:
                return abort(404, "this url is not allowed for outside")

        return storage.get_download_response_for_record(bucket=bucket,
                                                        record_data=record,
                                                        try_resized_image=True)
示例#25
0
def get_template_source(template_name):
    bucket = get_bucket_in_request_context()
    pages_configs = get_bucket_pages_configs(bucket)
    template_source = get_template_content_from_name(template_name, pages_configs)
    just_template_name = re.sub(r'\.(jade|html|htm)$', '', template_name)
    template_name_without_dot = just_template_name.replace('.', '_')
    template_name_without_dot2 = just_template_name.replace('.', '/')
    template_source = template_source or get_template_content_from_name(just_template_name, pages_configs)
    template_source = template_source or get_template_content_from_name(template_name_without_dot, pages_configs)
    if '.' in template_name:
        template_source = template_source or get_template_content_from_name(template_name_without_dot2, pages_configs)
    if not template_source:
        if template_name.startswith("builtin_theme_"):
            # 一些内置模板的匹配,这样可以使用 extends mixin 之类的逻辑
            builtin_template_source = system_builtin_templates.get(just_template_name)
            if builtin_template_source:
                template_source = builtin_template_source
    if template_source:
        return smart_unicode(template_source)
    else:
        return
示例#26
0
文件: wiki.py 项目: zhiiker/FarBox
def show_wiki_nodes_as_sub_site():
    bucket = get_bucket_in_request_context()
    if not bucket:
        return
    request_path = get_request_path().strip("/")
    if not re.match("wiki_nodes(/|$)", request_path):
        return
    wiki_configs = get_json_content_by_path(bucket, "__wiki.json", force_dict=True)
    enable_wiki_nodes = auto_type(wiki_configs.get("enable_wiki_nodes", True))
    if not enable_wiki_nodes:
        return
    wiki_root = smart_unicode(wiki_configs.get("wiki_root", ""))
    if not wiki_root:
        return
    wiki_root = wiki_root.strip("/")
    wiki_title = wiki_configs.get("wiki_title") or get_just_name(wiki_root, for_folder=True)
    path = request.values.get("path", "").strip("/")
    if request.values.get("type") == "data":
        # return json data
        wiki_root = wiki_root.lower()
        under = "%s/%s" % (wiki_root, path)
        posts_info = get_bucket_posts_info(bucket)
        data = filter_and_get_posts_link_points_info(posts_info, under=under)
        nodes = data.get("nodes")
        if nodes:
            for node in nodes:
                node_id = node.get("id")
                if node_id and isinstance(node_id, string_types):
                    if node_id.startswith("#"):
                        tag = node_id.lstrip("#")
                        url = "/wiki/tag/%s" % tag
                        node["url"] = url
                    else:
                        relative_path = get_relative_path(node_id.strip("/"), wiki_root, return_name_if_fail=False)
                        if relative_path:
                            url = "/wiki/post/%s" % relative_path
                            node["url"] =  url
        return force_response(data)
    else:
        return render_api_template("builtin_theme_wiki_nodes.jade", wiki_title=wiki_title)
示例#27
0
文件: utils.py 项目: zhiiker/FarBox
def get_comments(parent_doc, bucket=None, as_tree=None):
    bucket = bucket or get_bucket_in_request_context() or request.values.get('bucket')
    if not bucket:
        return []
    path = to_doc_path(parent_doc)

    comments_doc = get_comments_record(bucket, path)

    site_configs = get_bucket_site_configs(bucket)

    if not get_value_from_data(site_configs, "comments", default=True):
        return []

    if as_tree is None: # 自动匹配, 网站设置中对应
        comments_type = get_value_from_data(site_configs, 'comments_type') or 'tree'
        if comments_type in ['tree']:
            as_tree = True
        else:
            as_tree = False

    utc_offset = to_float(parent_doc.get('_utc_offset'), 8)

    return get_comments_by_comments_doc(comments_doc, as_tree=as_tree, utc_offset=utc_offset)
示例#28
0
def update_post_visits_for_response(response):
    doc = get_doc_in_request()
    if doc:
        doc_type = doc.get('_type')
        doc_path = doc.get('path')
    else:
        doc_type = get_doc_type_in_request()
        doc_path = get_doc_path_in_request()
    bucket = get_bucket_in_request_context()
    if bucket and doc_type == 'post' and doc_path:
        pass
    else:
        return

    visits_key = get_visits_key(doc_path, field='visits')
    visitors_key = get_visits_key(doc_path, field='visitors')

    now = time.time()
    # 直接在这里处理cookie
    # set cookie to know it's not a new visitor
    response.set_cookie('last_visited_at', str(now), max_age=one_year_seconds)

    last_visited_at = to_float(request.cookies.get('last_visited_at', 0)) or 0

    diff = now - last_visited_at
    if diff > 24 * 60 * 60:  # 24小时内的,认为是同一个visitor
        is_visitor = True
    else:
        is_visitor = False

    # 异步更新到数据库
    spawn(async_update_visits,
          bucket,
          visits_key,
          visitors_key,
          is_visitor=is_visitor)
示例#29
0
文件: bucket.py 项目: zhiiker/FarBox
 def current_bucket(self):
     return get_bucket_in_request_context() or ""
示例#30
0
文件: post.py 项目: zhiiker/FarBox
 def bucket(self):
     return get_bucket_in_request_context()