Nevar pievienot vairāk kā 25 tēmas Tēmai ir jāsākas ar burtu vai ciparu, tā var saturēt domu zīmes ('-') un var būt līdz 35 simboliem gara.

pirms 12 gadiem
pirms 12 gadiem
pirms 12 gadiem
pirms 12 gadiem
pirms 12 gadiem
pirms 12 gadiem
pirms 12 gadiem
pirms 12 gadiem
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349
  1. # Copyright (c) 2013, Web Notes Technologies Pvt. Ltd.
  2. # MIT License. See license.txt
  3. from __future__ import unicode_literals
  4. import conf
  5. import webnotes
  6. from webnotes import _
  7. import webnotes.utils
  8. class PageNotFoundError(Exception): pass
  9. def render(page_name):
  10. """render html page"""
  11. try:
  12. html = render_page(page_name or "index")
  13. except PageNotFoundError:
  14. html = render_page("404")
  15. except Exception:
  16. html = render_page('error')
  17. webnotes._response.headers["Content-Type"] = "text/html; charset: utf-8"
  18. webnotes._response.data = html
  19. def render_page(page_name):
  20. """get page html"""
  21. page_name = scrub_page_name(page_name)
  22. html = ''
  23. if not (hasattr(conf, 'auto_cache_clear') and conf.auto_cache_clear or 0):
  24. html = webnotes.cache().get_value("page:" + page_name)
  25. from_cache = True
  26. if not html:
  27. from webnotes.auth import HTTPRequest
  28. webnotes.http_request = HTTPRequest()
  29. html = build_page(page_name)
  30. from_cache = False
  31. if not html:
  32. raise PageNotFoundError
  33. if page_name=="error":
  34. html = html.replace("%(error)s", webnotes.getTraceback())
  35. else:
  36. comments = "\npage:"+page_name+\
  37. "\nload status: " + (from_cache and "cache" or "fresh")
  38. html += """\n<!-- %s -->""" % webnotes.utils.cstr(comments)
  39. return html
  40. def build_page(page_name):
  41. from jinja2 import Environment, FileSystemLoader
  42. from markdown2 import markdown
  43. if not webnotes.conn:
  44. webnotes.connect()
  45. sitemap = get_website_sitemap()
  46. page_options = sitemap.get(page_name)
  47. if not page_options:
  48. if page_name=="index":
  49. # page not found, try home page
  50. home_page = get_home_page()
  51. page_options = sitemap.get(home_page)
  52. if not page_options:
  53. raise PageNotFoundError
  54. page_options["page_name"] = home_page
  55. else:
  56. raise PageNotFoundError
  57. else:
  58. page_options["page_name"] = page_name
  59. basepath = webnotes.utils.get_base_path()
  60. module = None
  61. no_cache = False
  62. if page_options.get("controller"):
  63. module = webnotes.get_module(page_options["controller"])
  64. no_cache = getattr(module, "no_cache", False)
  65. # if generator, then load bean, pass arguments
  66. if page_options.get("is_generator"):
  67. if not module:
  68. raise Exception("Generator controller not defined")
  69. name = webnotes.conn.get_value(module.doctype, {
  70. page_options.get("page_name_field", "page_name"): page_options["page_name"]})
  71. obj = webnotes.get_obj(module.doctype, name, with_children=True)
  72. if hasattr(obj, 'get_context'):
  73. obj.get_context()
  74. context = webnotes._dict(obj.doc.fields)
  75. context["obj"] = obj
  76. else:
  77. # page
  78. context = webnotes._dict({ 'name': page_name })
  79. if module and hasattr(module, "get_context"):
  80. context.update(module.get_context())
  81. context.update(get_website_settings())
  82. jenv = Environment(loader = FileSystemLoader(basepath))
  83. jenv.filters["markdown"] = markdown
  84. context["base_template"] = jenv.get_template(webnotes.get_config().get("base_template"))
  85. template_name = page_options['template']
  86. html = jenv.get_template(template_name).render(context)
  87. if not no_cache:
  88. webnotes.cache().set_value("page:" + page_name, html)
  89. return html
  90. def build_sitemap():
  91. sitemap = {}
  92. config = webnotes.cache().get_value("website_sitemap_config", build_website_sitemap_config)
  93. sitemap.update(config["pages"])
  94. # generators
  95. for g in config["generators"].values():
  96. g["is_generator"] = True
  97. module = webnotes.get_module(g["controller"])
  98. condition = ""
  99. page_name_field = "page_name"
  100. if hasattr(module, "page_name_field"):
  101. page_name_field = module.page_name_field
  102. if hasattr(module, "condition_field"):
  103. condition = " where ifnull(%s, 0)=1" % module.condition_field
  104. for page_name, name, modified in webnotes.conn.sql("""select %s, name, modified from
  105. `tab%s` %s""" % (page_name_field, module.doctype, condition)):
  106. opts = g.copy()
  107. opts["doctype"] = module.doctype
  108. opts["page_name"] = page_name
  109. if page_name_field != "page_name":
  110. opts["page_name_field"] = page_name_field
  111. opts["docname"] = name
  112. opts["lastmod"] = modified.strftime("%Y-%m-%d %H:%M:%S")
  113. sitemap[page_name] = opts
  114. return sitemap
  115. def get_home_page():
  116. if not webnotes.conn:
  117. webnotes.connect()
  118. doc_name = webnotes.conn.get_value('Website Settings', None, 'home_page')
  119. if doc_name:
  120. page_name = webnotes.conn.get_value('Web Page', doc_name, 'page_name')
  121. else:
  122. page_name = 'login'
  123. return page_name
  124. def build_website_sitemap_config():
  125. import os, time
  126. config = {"pages": {}, "generators":{}}
  127. basepath = webnotes.utils.get_base_path()
  128. def get_options(path, fname):
  129. name = fname
  130. if fname.endswith(".html"):
  131. name = fname[:-5]
  132. template_path = os.path.relpath(os.path.join(path, fname), basepath)
  133. options = webnotes._dict({
  134. "link_name": name,
  135. "template": template_path,
  136. "lastmod": time.ctime(os.path.getmtime(template_path))
  137. })
  138. controller_name = fname.split(".")[0].replace("-", "_") + ".py"
  139. controller_path = os.path.join(path, controller_name)
  140. if os.path.exists(controller_path):
  141. options.controller = os.path.relpath(controller_path[:-3], basepath).replace(os.path.sep, ".")
  142. options.controller = ".".join(options.controller.split(".")[1:])
  143. return options
  144. for path, folders, files in os.walk(basepath):
  145. if os.path.basename(path)=="pages" and os.path.basename(os.path.dirname(path))=="templates":
  146. for fname in files:
  147. if fname.split(".")[-1] in ("html", "xml"):
  148. options = get_options(path, fname)
  149. config["pages"][options.link_name] = options
  150. if os.path.basename(path)=="generators" and os.path.basename(os.path.dirname(path))=="templates":
  151. for fname in files:
  152. if fname.endswith(".html"):
  153. options = get_options(path, fname)
  154. config["generators"][fname] = options
  155. return config
  156. def get_website_settings():
  157. from webnotes.utils import get_request_site_address, encode, cint
  158. from urllib import quote
  159. all_top_items = webnotes.conn.sql("""\
  160. select * from `tabTop Bar Item`
  161. where parent='Website Settings' and parentfield='top_bar_items'
  162. order by idx asc""", as_dict=1)
  163. top_items = [d for d in all_top_items if not d['parent_label']]
  164. # attach child items to top bar
  165. for d in all_top_items:
  166. if d['parent_label']:
  167. for t in top_items:
  168. if t['label']==d['parent_label']:
  169. if not 'child_items' in t:
  170. t['child_items'] = []
  171. t['child_items'].append(d)
  172. break
  173. context = webnotes._dict({
  174. 'top_bar_items': top_items,
  175. 'footer_items': webnotes.conn.sql("""\
  176. select * from `tabTop Bar Item`
  177. where parent='Website Settings' and parentfield='footer_items'
  178. order by idx asc""", as_dict=1),
  179. "webnotes": webnotes,
  180. "utils": webnotes.utils,
  181. "post_login": [
  182. {"label": "Reset Password", "url": "update-password", "icon": "icon-key"},
  183. {"label": "Logout", "url": "server.py?cmd=web_logout", "icon": "icon-signout"}
  184. ]
  185. })
  186. settings = webnotes.doc("Website Settings", "Website Settings")
  187. for k in ["banner_html", "brand_html", "copyright", "twitter_share_via",
  188. "favicon", "facebook_share", "google_plus_one", "twitter_share", "linked_in_share",
  189. "disable_signup"]:
  190. if k in settings.fields:
  191. context[k] = settings.fields.get(k)
  192. if settings.address:
  193. context["footer_address"] = settings.address
  194. for k in ["facebook_share", "google_plus_one", "twitter_share", "linked_in_share",
  195. "disable_signup"]:
  196. context[k] = cint(context.get(k) or 0)
  197. context.url = quote(str(get_request_site_address(full_address=True)), str(""))
  198. context.encoded_title = quote(encode(context.title or ""), str(""))
  199. try:
  200. import startup.webutils
  201. if hasattr(startup.webutils, "get_website_settings"):
  202. startup.webutils.get_website_settings(context)
  203. except:
  204. pass
  205. return context
  206. def clear_cache(page_name=None):
  207. if page_name:
  208. delete_page_cache(page_name)
  209. else:
  210. cache = webnotes.cache()
  211. for p in get_all_pages():
  212. cache.delete_value("page:" + p)
  213. cache.delete_value("website_sitemap")
  214. cache.delete_value("website_sitemap_config")
  215. def get_website_sitemap():
  216. return webnotes.cache().get_value("website_sitemap", build_sitemap)
  217. def get_all_pages():
  218. return get_website_sitemap().keys()
  219. def delete_page_cache(page_name):
  220. if page_name:
  221. webnotes.cache().delete_value("page:" + page_name)
  222. def get_hex_shade(color, percent):
  223. def p(c):
  224. v = int(c, 16) + int(int('ff', 16) * (float(percent)/100))
  225. if v < 0:
  226. v=0
  227. if v > 255:
  228. v=255
  229. h = hex(v)[2:]
  230. if len(h) < 2:
  231. h = "0" + h
  232. return h
  233. r, g, b = color[0:2], color[2:4], color[4:6]
  234. avg = (float(int(r, 16) + int(g, 16) + int(b, 16)) / 3)
  235. # switch dark and light shades
  236. if avg > 128:
  237. percent = -percent
  238. # stronger diff for darker shades
  239. if percent < 25 and avg < 64:
  240. percent = percent * 2
  241. return p(r) + p(g) + p(b)
  242. def scrub_page_name(page_name):
  243. if page_name.endswith('.html'):
  244. page_name = page_name[:-5]
  245. return page_name
  246. _is_signup_enabled = None
  247. def is_signup_enabled():
  248. global _is_signup_enabled
  249. if _is_signup_enabled is None:
  250. _is_signup_enabled = True
  251. if webnotes.utils.cint(webnotes.conn.get_value("Website Settings",
  252. "Website Settings", "disable_signup")):
  253. _is_signup_enabled = False
  254. return _is_signup_enabled
  255. def update_page_name(doc, title):
  256. """set page_name and check if it is unique"""
  257. new_page_name = page_name(title)
  258. sitemap = get_website_sitemap()
  259. if new_page_name in sitemap and \
  260. not (sitemap[new_page_name].doctype == doc.doctype and sitemap[new_page_name].docname == doc.name):
  261. webnotes.throw("%s: %s. %s: %s" % (new_page_name, _("Page already exists"),
  262. _("Please change the value"), title))
  263. if doc.page_name: delete_page_cache(doc.page_name)
  264. webnotes.conn.set(doc, "page_name", new_page_name)
  265. delete_page_cache(doc.page_name)
  266. def page_name(title):
  267. """make page name from title"""
  268. import re
  269. name = title.lower()
  270. name = re.sub('[~!@#$%^&*()<>,."\']', '', name)
  271. name = re.sub('[:/]', '-', name)
  272. name = '-'.join(name.split())
  273. # replace repeating hyphens
  274. name = re.sub(r"(-)\1+", r"\1", name)
  275. return name