You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

webutils.py 7.2 KiB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276
  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. import webnotes.utils
  7. class PageNotFoundError(Exception): pass
  8. def render(page_name):
  9. """render html page"""
  10. try:
  11. html = render_page(page_name or "index")
  12. except PageNotFoundError:
  13. html = render_page("404")
  14. except Exception:
  15. html = render_page('error')
  16. from webnotes.handler import eprint, print_zip
  17. eprint("Content-Type: text/html; charset: utf-8")
  18. print_zip(html)
  19. def render_page(page_name):
  20. """get page html"""
  21. page_name = scrub_page_name(page_name)
  22. html = ''
  23. if page_name=="index":
  24. page_name = get_home_page()
  25. if not (hasattr(conf, 'auto_cache_clear') and conf.auto_cache_clear or 0):
  26. html = webnotes.cache().get_value("page:" + page_name)
  27. from_cache = True
  28. if not html:
  29. from webnotes.auth import HTTPRequest
  30. webnotes.http_request = HTTPRequest()
  31. html = build_page(page_name)
  32. from_cache = False
  33. if not html:
  34. raise PageNotFoundError
  35. if page_name=="error":
  36. html = html.replace("%(error)s", webnotes.getTraceback())
  37. else:
  38. comments = "\n\npage:"+page_name+\
  39. "\nload status: " + (from_cache and "cache" or "fresh")
  40. html += """\n<!-- %s -->""" % webnotes.utils.cstr(comments)
  41. return html
  42. def build_page(page_name):
  43. from jinja2 import Environment, FileSystemLoader
  44. import os
  45. if not webnotes.conn:
  46. webnotes.connect()
  47. sitemap = webnotes.cache().get_value("website_sitemap", build_sitemap)
  48. page_options = sitemap.get(page_name)
  49. basepath = webnotes.utils.get_base_path()
  50. module = None
  51. no_cache = False
  52. if page_options.get("controller"):
  53. module = webnotes.get_module(page_options["controller"])
  54. no_cache = getattr(module, "no_cache", False)
  55. # if generator, then load bean, pass arguments
  56. if page_options.get("is_generator"):
  57. if not module:
  58. raise Exception("Generator controller not defined")
  59. name = webnotes.conn.get_value(module.doctype, {"page_name": page_name})
  60. obj = webnotes.get_obj(module.doctype, name, with_children=True)
  61. if hasattr(obj, 'get_context'):
  62. obj.get_context()
  63. context = webnotes._dict(obj.doc.fields)
  64. context["obj"] = obj
  65. else:
  66. # page
  67. context = webnotes._dict({ 'name': page_name })
  68. if module:
  69. context.update(module.get_context())
  70. context = update_context(context)
  71. jenv = Environment(loader = FileSystemLoader(basepath))
  72. context["base_template"] = jenv.get_template(webnotes.get_config().get("base_template"))
  73. template_name = page_options['template']
  74. html = jenv.get_template(template_name).render(context)
  75. if not no_cache:
  76. webnotes.cache().set_value("page:" + page_name, html)
  77. return html
  78. def build_sitemap():
  79. sitemap = {}
  80. config = webnotes.cache().get_value("website_sitemap_config", build_website_sitemap_config)
  81. sitemap.update(config["pages"])
  82. # generators
  83. for g in config["generators"].values():
  84. g["is_generator"] = True
  85. module = webnotes.get_module(g["controller"])
  86. doctype = module.doctype
  87. for name in webnotes.conn.sql_list("""select name from `tab%s` where
  88. ifnull(%s, 0)=1""" % (module.doctype, module.condition_field)):
  89. sitemap[name] = g
  90. return sitemap
  91. def get_home_page():
  92. if not webnotes.conn:
  93. webnotes.connect()
  94. doc_name = webnotes.conn.get_value('Website Settings', None, 'home_page')
  95. if doc_name:
  96. page_name = webnotes.conn.get_value('Web Page', doc_name, 'page_name')
  97. else:
  98. page_name = 'login'
  99. return page_name
  100. def update_context(context):
  101. try:
  102. from startup.webutils import update_template_args
  103. context = update_template_args(page_name, context)
  104. except ImportError:
  105. pass
  106. return context
  107. def build_website_sitemap_config():
  108. import os, json
  109. config = {"pages": {}, "generators":{}}
  110. basepath = webnotes.utils.get_base_path()
  111. def get_options(path, fname):
  112. name = fname[:-5]
  113. options = webnotes._dict({
  114. "link_name": name,
  115. "template": os.path.relpath(os.path.join(path, fname), basepath),
  116. })
  117. controller_path = os.path.join(path, name + ".py")
  118. if os.path.exists(controller_path):
  119. options.controller = os.path.relpath(controller_path[:-3], basepath).replace(os.path.sep, ".")
  120. options.controller = ".".join(options.controller.split(".")[1:])
  121. return options
  122. for path, folders, files in os.walk(basepath):
  123. if os.path.basename(path)=="pages" and os.path.basename(os.path.dirname(path))=="templates":
  124. for fname in files:
  125. if fname.endswith(".html"):
  126. options = get_options(path, fname)
  127. config["pages"][options.link_name] = options
  128. if os.path.basename(path)=="generators" and os.path.basename(os.path.dirname(path))=="templates":
  129. for fname in files:
  130. if fname.endswith(".html"):
  131. options = get_options(path, fname)
  132. config["generators"][fname] = options
  133. return config
  134. def clear_cache(page_name=None):
  135. if page_name:
  136. delete_page_cache(page_name)
  137. else:
  138. cache = webnotes.cache()
  139. for p in get_all_pages():
  140. cache.delete_value("page:" + p)
  141. def get_all_pages():
  142. return webnotes.cache().get_value("website_sitemap", build_sitemap).keys()
  143. def delete_page_cache(page_name):
  144. if page_name:
  145. webnotes.cache().delete_value("page:" + page_name)
  146. def get_hex_shade(color, percent):
  147. def p(c):
  148. v = int(c, 16) + int(int('ff', 16) * (float(percent)/100))
  149. if v < 0:
  150. v=0
  151. if v > 255:
  152. v=255
  153. h = hex(v)[2:]
  154. if len(h) < 2:
  155. h = "0" + h
  156. return h
  157. r, g, b = color[0:2], color[2:4], color[4:6]
  158. avg = (float(int(r, 16) + int(g, 16) + int(b, 16)) / 3)
  159. # switch dark and light shades
  160. if avg > 128:
  161. percent = -percent
  162. # stronger diff for darker shades
  163. if percent < 25 and avg < 64:
  164. percent = percent * 2
  165. return p(r) + p(g) + p(b)
  166. def scrub_page_name(page_name):
  167. if page_name.endswith('.html'):
  168. page_name = page_name[:-5]
  169. return page_name
  170. def get_portal_links():
  171. portal_args = {}
  172. for page, opts in webnotes.get_config()["web"]["pages"].items():
  173. if opts.get("portal"):
  174. portal_args[opts["portal"]["doctype"]] = {
  175. "page": page,
  176. "conditions": opts["portal"].get("conditions")
  177. }
  178. return portal_args
  179. _is_portal_enabled = None
  180. def is_portal_enabled():
  181. global _is_portal_enabled
  182. if _is_portal_enabled is None:
  183. _is_portal_enabled = True
  184. if webnotes.utils.cint(webnotes.conn.get_value("Website Settings",
  185. "Website Settings", "disable_signup")):
  186. _is_portal_enabled = False
  187. return _is_portal_enabled
  188. def update_page_name(doc, title):
  189. """set page_name and check if it is unique"""
  190. webnotes.conn.set(doc, "page_name", page_name(title))
  191. if doc.page_name in get_all_pages():
  192. webnotes.conn.sql("""Page Name cannot be one of %s""" % ', '.join(get_standard_pages()))
  193. res = webnotes.conn.sql("""\
  194. select count(*) from `tab%s`
  195. where page_name=%s and name!=%s""" % (doc.doctype, '%s', '%s'),
  196. (doc.page_name, doc.name))
  197. if res and res[0][0] > 0:
  198. webnotes.msgprint("""A %s with the same title already exists.
  199. Please change the title of %s and save again."""
  200. % (doc.doctype, doc.name), raise_exception=1)
  201. delete_page_cache(doc.page_name)
  202. def page_name(title):
  203. """make page name from title"""
  204. import re
  205. name = title.lower()
  206. name = re.sub('[~!@#$%^&*()<>,."\']', '', name)
  207. name = re.sub('[:/]', '-', name)
  208. name = '-'.join(name.split())
  209. # replace repeating hyphens
  210. name = re.sub(r"(-)\1+", r"\1", name)
  211. return name