1 """
2 MoinMoin - IncludeUrl macro
3
4 Copyright (c) 2000, 2001, 2002, 2003 by Jürgen Hermann <jh@web.de>
5 Copyright (c) 2000, 2001 by Richard Jones <richard@bizarsoftware.com.au>
6 Copyright (c) 2001-2003 by Conectiva, Inc.
7 All rights reserved, see COPYING for details.
8
9 This macro includes the formatted content of the given url, following
10 recursive includes if encountered. It has been implemented by
11 Gustavo Niemeyer <niemeyer@conectiva.com> by modifying the code of
12 Include macro. Check
13
14 http://purl.net/wiki/moinmaster/HelpOnMacros/Include
15
16 for detailed docs.
17
18 $Id: Include.py,v 1.21 2003/04/25 16:15:17 jhermann Exp $
19 """
20
21 import sys, re, cStringIO
22 from MoinMoin import config, user, wikiutil
23 from MoinMoin.Page import Page
24
25
26
27
28 __version__ = "2.0"
29
30 import urllib
31 try:
32 allowed_schemes = config.includeurl_schemes
33 except AttributeError:
34 allowed_schemes = ["http", "https", "ftp"]
35
36 class PageUrl(Page):
37 def split_title(self):
38 return self.page_name
39
40 def exists(self):
41 return 1
42
43 def link_to(self, text=None, querystr=None, anchor=None, **kw):
44 text = text or self.split_title()
45 return '<a href="%s">%s</a>' % (self.page_name, text)
46
47 def get_raw_body(self):
48 """Load the raw markup from the page file"""
49 if self._raw_body is not None:
50 return self._raw_body
51 try:
52 file = urllib.urlopen(self.page_name)
53 except IOError, er:
54 return ""
55 try:
56 self.set_raw_body(file.read())
57 finally:
58 file.close()
59 return self._raw_body
60
61
62
63 _sysmsg = '<p><strong class="%s">%s</strong></p>'
64 _arg_heading = r'(?P<heading>,)\s*(|(?P<hquote>[\'"])(?P<htext>.+?)(?P=hquote))'
65 _arg_level = r',\s*(?P<level>\d+)'
66 _arg_from = r'(,\s*from=(?P<fquote>[\'"])(?P<from>.+?)(?P=fquote))?'
67 _arg_to = r'(,\s*to=(?P<tquote>[\'"])(?P<to>.+?)(?P=tquote))?'
68 _arg_sort = r'(,\s*sort=(?P<sort>(ascending|descending)))?'
69 _arg_items = r'(,\s*items=(?P<items>\d+))?'
70 _args_re_pattern = r'^(?P<name>[^,]+)(%s(%s)?%s%s%s%s)?$' % (
71 _arg_heading, _arg_level, _arg_from, _arg_to, _arg_sort, _arg_items)
72
73 def execute(macro, text, args_re=re.compile(_args_re_pattern)):
74 _ = macro.request.getText
75
76
77 if macro.request.mode_getpagelinks:
78 return ''
79
80
81 args = args_re.match(text)
82 if not args:
83 return (_sysmsg % ('error', _('Invalid include arguments "%s"!')) % (text,))
84
85
86 result = []
87 print_mode = macro.form.has_key('action') and macro.form['action'].value == "print"
88 this_page = macro.formatter.page
89 if not hasattr(this_page, '_macroInclude_pagelist'):
90 this_page._macroInclude_pagelist = {}
91
92
93 inc_name = wikiutil.AbsPageName(macro.request, this_page.page_name, args.group('name'))
94 pagelist = [inc_name]
95
96 """
97 if inc_name.startswith("^"):
98 try:
99 inc_match = re.compile(inc_name)
100 except re.error:
101 pass # treat as plain page name
102 else:
103 pagelist = wikiutil.getPageList(config.text_dir)
104 pagelist = filter(inc_match.match, pagelist)
105 """
106
107
108 pagelist.sort()
109 sort_dir = args.group('sort')
110 if sort_dir == 'descending':
111 pagelist.reverse()
112 max_items = args.group('items')
113 if max_items:
114 pagelist = pagelist[:int(max_items)]
115
116
117 for inc_name in pagelist:
118
119 scheme = urllib.splittype(inc_name)[0]
120 if scheme not in allowed_schemes:
121 result.append('<p><strong class="error">Scheme "%s" not allowed for IncludeUrl</strong></p>' % scheme)
122 continue
123
124 if this_page._macroInclude_pagelist.has_key(inc_name):
125 result.append('<p><strong class="error">Recursive include of "%s" forbidden</strong></p>' % (inc_name,))
126 continue
127
128 inc_page = PageUrl(inc_name, formatter=macro.formatter.__class__(macro.request))
129 inc_page._macroInclude_pagelist = this_page._macroInclude_pagelist
130
131
132 body = inc_page.get_raw_body() + '\n'
133 from_pos = 0
134 to_pos = -1
135 from_re = args.group('from')
136 if from_re:
137 try:
138 from_match = re.compile(from_re, re.M).search(body)
139 except re.error, e:
140
141 from_match = re.compile(re.escape(from_re), re.M).search(body)
142 if from_match:
143 from_pos = from_match.end()
144 else:
145 result.append(_sysmsg % ('warning', 'Include: ' + _('Nothing found for "%s"!')) % from_re)
146 to_re = args.group('to')
147 if to_re:
148 try:
149 to_match = re.compile(to_re, re.M).search(body, from_pos)
150 except re.error:
151 to_match = re.compile(re.escape(to_re), re.M).search(body, from_pos)
152 if to_match:
153 to_pos = to_match.start()
154 else:
155 result.append(_sysmsg % ('warning', 'Include: ' + _('Nothing found for "%s"!')) % to_re)
156 if from_pos or to_pos != -1:
157 inc_page.set_raw_body(body[from_pos:to_pos])
158
159
160
161
162 edit_icon = ""
163 """
164 # edit icon
165 edit_icon = inc_page.link_to(
166 macro.formatter.image(border=0, hspace=2,
167 src="%s/img/moin-edit.gif" % (config.url_prefix,)),
168 css_class="include-edit-link",
169 querystr={'action': 'edit', 'backto': this_page.page_name})
170 """
171
172
173 level = None
174 if args.group('htext'):
175 heading = args.group('htext') or inc_page.split_title()
176 level = 1
177 if args.group('level'):
178 level = int(args.group('level'))
179 if print_mode:
180 result.append(macro.formatter.heading(level, heading))
181 else:
182 result.append(macro.formatter.heading(level,
183 inc_page.link_to(heading, css_class="include-heading-link"),
184 icons=edit_icon.replace('<img ', '<img align="right" ')
185 .replace('&', '&')))
186
187
188 this_page._macroInclude_pagelist[inc_name] = \
189 this_page._macroInclude_pagelist.get(inc_name, 0) + 1
190
191
192 stdout = sys.stdout
193 sys.stdout = cStringIO.StringIO()
194 try:
195 inc_page.send_page(macro.request, content_only=1)
196 result.append(sys.stdout.getvalue())
197 finally:
198 sys.stdout = stdout
199
200
201 if this_page._macroInclude_pagelist[inc_name] > 1:
202 this_page._macroInclude_pagelist[inc_name] = \
203 this_page._macroInclude_pagelist[inc_name] - 1
204 else:
205 del this_page._macroInclude_pagelist[inc_name]
206
207
208 if not (level or print_mode):
209 result.extend([
210 '<div class="include-link">',
211 inc_page.link_to('[%s]' % (inc_name,), css_class="include-page-link"),
212 edit_icon,
213 '</div>',
214 ])
215
216
217 return ''.join(result)
218
219