]>
git.ipfire.org Git - ipfire.org.git/blob - src/backend/wiki.py
9 from .decorators
import *
11 # Used to automatically link some things
14 (re
.compile(r
"(?:#(\d+))", re
.I
), r
"https://bugzilla.ipfire.org/show_bug.cgi?id=\1"),
17 (re
.compile(r
"([a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+)"), r
"mailto:\1"),
20 (re
.compile(r
"(?:CVE)[\s\-](\d{4}\-\d+)"), r
"https://cve.mitre.org/cgi-bin/cvename.cgi?name=\1"),
23 class Wiki(misc
.Object
):
24 def _get_pages(self
, query
, *args
):
25 res
= self
.db
.query(query
, *args
)
28 yield Page(self
.backend
, row
.id, data
=row
)
30 def get_page_title(self
, page
, default
=None):
31 doc
= self
.get_page(page
)
37 def get_page(self
, page
, revision
=None):
38 page
= Page
.sanitise_page_name(page
)
42 res
= self
.db
.get("SELECT * FROM wiki WHERE page = %s \
43 AND timestamp = %s", page
, revision
)
45 res
= self
.db
.get("SELECT * FROM wiki WHERE page = %s \
46 ORDER BY timestamp DESC LIMIT 1", page
)
49 return Page(self
.backend
, res
.id, data
=res
)
51 def get_recent_changes(self
, limit
=None):
52 return self
._get
_pages
("SELECT * FROM wiki \
53 WHERE timestamp >= NOW() - INTERVAL '4 weeks' \
54 ORDER BY timestamp DESC LIMIT %s", limit
)
56 def create_page(self
, page
, author
, markdown
):
57 page
= Page
.sanitise_page_name(page
)
59 res
= self
.db
.get("INSERT INTO wiki(page, author_id, markdown) \
60 VALUES(%s, %s, %s) RETURNING id", page
, author
.id, markdown
)
63 return self
.get_page_by_id(res
.id)
65 def delete_page(self
, page
, author
):
66 # Do nothing if the page does not exist
67 if not self
.get_page(page
):
70 # Just creates a blank last version of the page
71 self
.create_page(page
, author
, None)
75 parts
= list(e
for e
in url
.split("/") if e
)
77 num_parts
= len(parts
)
78 for i
in range(num_parts
):
79 yield "/".join(parts
[:i
])
81 def make_breadcrumbs(self
, url
):
82 for part
in self
._split
_url
(url
):
83 title
= self
.get_page_title(part
, os
.path
.basename(part
))
85 yield ("/%s" % part
, title
)
88 class Page(misc
.Object
):
89 def init(self
, id, data
=None):
93 def __lt__(self
, other
):
94 if isinstance(other
, self
.__class
__):
95 if self
.page
== other
.page
:
96 return self
.timestamp
< other
.timestamp
98 return self
.page
< other
.page
101 def sanitise_page_name(page
):
105 # Make sure that the page name does NOT end with a /
106 if page
.endswith("/"):
109 # Make sure the page name starts with a /
110 if not page
.startswith("/"):
113 # Remove any double slashes
114 page
= page
.replace("//", "/")
124 return self
.data
.page
128 return self
._title
or self
.page
[1:]
132 if not self
.markdown
:
135 # Find first H1 headline in markdown
136 markdown
= self
.markdown
.splitlines()
138 m
= re
.match(r
"^# (.*)( #)?$", markdown
[0])
144 if self
.data
.author_uid
:
145 return self
.backend
.accounts
.get_by_uid(self
.data
.author_uid
)
147 def _render(self
, text
):
148 logging
.debug("Rendering %s" % self
)
150 return markdown2
.markdown(text
, link_patterns
=link_patterns
,
151 extras
=["footnotes", "link-patterns", "wiki-tables"])
155 return self
.data
.markdown
159 return self
.data
.html
or self
._render
(self
.markdown
)
163 return self
.data
.timestamp
165 def was_deleted(self
):
166 return self
.markdown
is None
169 def breadcrumbs(self
):
170 return self
.backend
.wiki
.make_breadcrumbs(self
.page
)
172 def get_latest_revision(self
):
173 return self
.backend
.wiki
.get_page(self
.page
)
179 parts
= self
.page
.split("/")
182 sidebar
= self
.backend
.wiki
.get_page(os
.path
.join(*parts
, "sidebar"))