def get_link(self, tooltip=False, url_suffix=''): # TODO: EDIT permission should immediately imply view permission # everywhere, not only here. # If prerequisites not met, do not output link. if EDIT not in getattr(self, '_cache_perm', []) \ and not getattr(self, 'cache_prerequisites_met', False): # Do not show if this is a file or not, it doesn't matter. # Especially, don't put the link to the file itself! return mark_safe(u'<i class="icon-lock" title="Niste riješili neke ' u'od preduvjeta za ovaj zadatak!"></i> ' u'<span class="task-locked">{}</span>'.format( xss.escape(self.name))) if self.file_attachment_id: url = self.cache_file_attachment_url icon = 'icon-book' if self.is_lecture else 'icon-file' file = u'<a href="{}" title="{}">' \ u'<i class="{}"></i>' \ u'</a> '.format(url, url[url.rfind('/') + 1:], icon) else: file = u'' # If not solvable, automatically there is no tooltip. return mark_safe(u'{}<a href="/task/{}/{}" class="task{}">{}</a>'.format( file, self.id, url_suffix, ' task-tt-marker' if tooltip and self.solvable else '', xss.escape(self.name)))
def __init__(self, *args, **kwargs): self.competition = kwargs.pop('competition') self.evaluator = get_evaluator(self.competition.evaluator_version) self.fixed_score = self.competition.fixed_task_score user = kwargs.pop('user') super(CompetitionTaskForm, self).__init__(*args, **kwargs) self.t_comment_extra_class = "ctask-comment" if self.instance.pk: self.fields['text'].initial = self.instance.task.content.text self.fields['comment'].initial = self.instance.comment.text self.t_comment_extra_class += \ " " + ctask_comment_class(self.instance, user) descriptor = self.initial.get('descriptor') if descriptor: variables = safe_parse_descriptor(self.evaluator, descriptor) self.fields['descriptor'].help_text = get_solution_help_text( variables, error_message=_("Invalid!"), show_types=True) self.fields['descriptor'].label = mark_safe( xss.escape(_("Solution")) + \ ' <a href="' + comp_url(self.competition, 'rules') + '" target="_blank"><i class="icon-question-sign" title="' + xss.escape(_("Help")) + '"></i></a>') if self.fixed_score: del self.fields['score'] self.fields['text'].widget.attrs.update( {'class': 'comp-mathcontent-text', 'rows': 5}) self.fields['comment'].widget.attrs.update( {'class': 'comp-mathcontent-text ctask-comment', 'rows': 3})
def get_latex_html(latex_element, force_inline): """Given LatexElement instance generate <img> HTML.""" inline = force_inline or latex_element.format in ['$%s$', '\(%s\)'] latex_escaped = xss.escape(latex_element.text) depth = latex_element.depth if depth == ERROR_DEPTH_VALUE: # TODO: link to the log file. return u'<span class="mc-error-source" title="{}">{}</span>'.format( xss.escape(_("Invalid LaTeX.")), xss.escape(latex_element.format % latex_element.text)) hash = latex_element.hash url = '%s%s/%s/%s/%s.png' % (IMG_URL_PATH, hash[0], hash[1], hash[2], hash) if inline: return u'<img src="%s" alt="%s" class="latex" ' \ 'style="vertical-align:%dpx">' % (url, latex_escaped, -depth) else: return u'<img src="%s" alt="%s" class="latex-center">' % \ (url, latex_escaped) # # FIXME: don't save error message to depth # hash, depth = generate_svg(latex, format, inline) # if depth == ERROR_DEPTH_VALUE: # # TODO: link to the log file. # out.append('{{ INVALID LATEX }}') # else: # url = '%s%s/%s/%s/%s.svg' % (IMG_URL_PATH, hash[0], hash[1], hash[2], hash) # if inline: # obj = '<object data="%s" type="image/svg+xml" alt="%s" class="latex" style="vertical-align:%fpt"></object>' % (url, latex_escaped, -depth) # else: # obj = '<object data="%s" type="image/svg+xml" alt="%s" class="latex-center"></object>' % (url, latex_escaped) return img
def to_html(self, token, converter): if token.is_open(): if len(token.attrs) > 1: raise BBUnexpectedParameters() if token.content is not None: return u'<a href="{}" rel="nofollow">{}</a>'.format( xss.escape(token.content), xss.escape(token.content)) return u'<a href="{}" rel="nofollow">'.format( xss.escape(dict(token.attrs)['url'])) return '</a>'
def _handle_latex_html(cnt, latex): """ Generates LaTeX PNGs and outputs <img> tag. """ latex_escaped = xss.escape(latex) inline = cnt == 1 if cnt == 1: format = inline_format elif cnt == 2: format = block_format else: format = advanced_format # FIXME: don't save error message to depth hash, depth = generate_png(latex, format) if depth == ERROR_DEPTH_VALUE: return '{{ INVALID LATEX }}' else: url = '%s%s/%s/%s/%s.png' % (img_url_path, hash[0], hash[1], hash[2], hash) if inline: img = '<img src="%s" alt="%s" class="latex" style="vertical-align:%dpx">' % (url, latex_escaped, -depth) else: img = '<img src="%s" alt="%s" class="latex_center">' % (url, latex_escaped) return img
def _handle_latex_html(cnt, latex): """Generate LaTeX PNGs and outputs <img> tag.""" latex_escaped = xss.escape(latex) inline = cnt == 1 if cnt == 1: format = inline_format elif cnt == 2: format = block_format else: format = advanced_format # FIXME: don't save error message to depth latex_element = get_or_generate_png(format, latex) if latex_element.depth == ERROR_DEPTH_VALUE: return '{{ INVALID LATEX }}' else: hash = latex_element.hash url = '%s%s/%s/%s/%s.png' % (IMG_URL_PATH, hash[0], hash[1], hash[2], hash) if inline: img = '<img src="%s" alt="%s" class="latex" style="vertical-align:%dpx">' % (url, latex_escaped, -latex_element.depth) else: img = '<img src="%s" alt="%s" class="latex-center">' % (url, latex_escaped) return img
def userlink(user, what=None): name = None if what == 'full': name = user.get_full_name().strip() elif what: name = getattr(user, what, None) # full_name kao default bi stvarao gadne probleme kod PM-a if not name: name = user.username return mark_safe(u'<a href="/profile/%d/" title="%s">%s</a>' % (user.pk, escape(user.get_full_name()), escape(name)))
def to_html(self, token, converter): if not token.is_open(): return '</div></div>' if len(token.attrs) != 1: raise BBUnexpectedParameters() if token.attrs[0][1]: link_text = xss.escape(token.attrs[0][1]) else: link_text = '+/-' return u'<div><a href="#" class="mc-hide-link">{}</a>' \ u'<div class="mc-hide-content" style="display:none;">'.format( link_text)
def generate_get_query_string(context, *args, **kwargs): """ Generates GET part of URL given keys to remove (*args) and key-value pairs to add (**kwargs). Additionally, removes all keys specified in context[GENERATE_URL_TMP_KEYS] set. (for more info about this set, look at temporary_get_key) """ get = context['request'].GET.copy() for key in args: if key in get: del get[key] for key in context.get(GENERATE_URL_TMP_KEYS, []): if key in get: del get[key] for key, value in kwargs.iteritems(): get[key] = value return escape(get.urlencode())
def add(actor, type_desc, **kwargs): type, subtype = type_desc action = Action(actor=actor, type=type, subtype=subtype, **kwargs) # can this be DRY-ed somehow? # ----- global ----- if action.action_object: if hasattr(action.action_object, "name"): action.action_object_cache = action.action_object.name elif hasattr(action.action_object, "username"): action.action_object_cache = action.action_object.username elif hasattr(action.action_object, "value"): # rating action.action_object_cache = str(action.action_object.value) if action.target: if hasattr(action.target, "name"): action.target_cache = action.target.name elif hasattr(action.target, "username"): action.target_cache = action.target.username elif action.target._meta.app_label == 'solution' and action.target._meta.module_name == 'solution': data = [ action.target.author_id, action.target.author.username, action.target.task_id, action.target.task.name, action.target.task.author_id, ] # 250 chars should be enough for this action.target_cache = POST_SEND_CACHE_SEPARATOR.join([xss.escape(unicode(x)) for x in data]) # ----- type specific ----- if type == POST_SEND: T = action.action_object.content.text action.action_object_cache = T[:78] + '...' if len(T) > 80 else T action.save()
def to_html(self, token, converter): if len(token.attrs) != 1 or token.attrs[0][1] is not None: raise BBUnexpectedParameters() return self.html_open + xss.escape(token.content) + self.html_close
def get_link(self): return mark_safe(u'<a href="{}">{}</a>'.format( self.get_absolute_url(), xss.escape(self.get_name())))
def _convert(T, type, handle_latex_func, escape_table, content=None, attachment_path=None): # XSS danger!!! Be careful """ Converts MathContent format to HTML (type 0) or LaTeX (type 1) To support features like [img], it must be called with a a content instance. """ # force strip T = T.strip() if type == TYPE_HTML: newline = '<br>' else: newline = '\n' i = 0 n = len(T) out = [] tag_stack = [] while i < n: if T[i] == '\\': # parse \$ and similar if i + 1 < n: out.append(escape_table.get(T[i + 1], T[i + 1])) i += 2 elif T[i:i+2] == '\r\n': out.append(newline) i += 2 elif T[i] == '\r' or T[i] == '\n': out.append(newline) i += 1 elif T[i] == '[': # BBCode # TODO: [url] can't contain ] end = T.find(']', i) if end == -1: out.append('[') # no error messages for now i += 1 elif end == i + 1: out.append('[]') i += 2 elif end == i + 2 and T[i+1] == '/': out.append('[/]') i += 3 else: # non empty tag # here we make difference between TYPE_HTML and TYPE_LATEX # TYPE_HTML = first element of tag tuple # TYPE_LATEX = second element of tag tuple try: tag, attrs = parse_bb_code(T[i+1:end]) except: # if bb code not valid (or if not bb code at all), output original text out.append('[%s]' % T[i+1:end]) i = end + 1 continue if tag[0] == '/': tag = tag[1:] if not tag_stack or tag_stack[-1] != tag: out.append('{{ Poredak otvorenih i zatvorenih tagova nije valjan. }}') else: out.append(tag_close[tag_stack.pop()][type]) elif tag not in tag_open: out.append('{{ Nevaljan tag "%s" }}' % xss.escape(tag)) else: # ask for close tag if there should be one if tag_close.get(tag, None) is not None: tag_stack.append(tag) open = tag_open[tag][type] # process attributes # WARNING: currently HTML and LaTeX use same attribute names and formats! extra = '' if tag in tag_attrs: for key, value in attrs.iteritems(): if key in tag_attrs[tag]: if type == TYPE_HTML: extra += ' %s="%s"' % (key, xss.escape(attrs[key])) else: extra += ',%s=%s' % (key, xss.escape(attrs[key])) if tag == 'img': if not content: open = u'{{ Slika nije dostupna u pregledu }}' elif 'attachment' not in attrs: open = u'{{ Nedostaje "attachment" atribut }}' else: try: k = int(attrs['attachment']) - 1 file = content.attachments.order_by('id')[k] if type == TYPE_HTML: extra += ' src="%s"' % xss.escape(file.get_url()) else: # type == TYPE_LATEX if attachment_path: filename = '{}/{}/{}'.format( attachment_path, k, file.get_filename()) else: filename = file.get_full_path_and_filename() extra = '[%s]{%s}' % (extra[1:], filename) except: open = u'{{ Greška pri preuzimanju img datoteke. (Nevaljan broj?) }}' elif tag == 'url': # TODO: show icon for external URLs # Manually get the URL if not given. if 'url' not in attrs: url_end = T.find('[/url]', i) if url_end == -1: open = u'{{ Nedostaje [/url] }}' else: attrs['url'] = T[i + 5:url_end] attrs['url'] = xss.escape(attrs.get('url', '')) attrs.update({'extra': extra}) open %= attrs out.append(open) i = end + 1 elif T[i] == '$': # parse $ $, $$ $$ and $$$ $$$ cnt = 0 while i < n and T[i] == '$': cnt += 1 i += 1 if cnt > 3: cnt = 3 # this should cover all weird cases with \\ and \$ latex = [] while i < n: if T[i:i+2] == '\\$' or T[i:i+2] == '\\\\': latex.append(T[i:i+2]) i += 2 elif cnt <= 2 and T[i] == '$' or cnt == 3 and T[i:i+2] == '$$': # It is possible to use $ ... $ inside inside of $$$ ... $$$. # This could be also written more strictly as # elif T[i:i+cnt] == '$' * cnt: break; else: latex.append(T[i]) i += 1 # don't care how many $ are there, just skip them while i < n and T[i] == '$': i += 1 latex = u''.join(latex) out.append(handle_latex_func(cnt, latex)) else: out.append(escape_table.get(T[i], T[i])) i += 1 if tag_stack: out.append('{{ Neki tagovi nisu zatvoreni }}') while tag_stack: out.append(tag_close[tag_stack.pop()][type]) return u''.join(out)
def grouplink(group): return mark_safe(u'<a href="/usergroup/{}/">{}</a>'.format( group.id, xss.escape(group.name)))
def append_get_parameters(context): """Generate "?a=b" part of the URL. Returns an empty string if GET is empty.""" get = context['request'].GET return '?' + escape(get.urlencode()) if get else ''
def to_html(self, token, converter): val, index, attachment = self._check(token, converter) return u'<img src="{}" alt="Attachment #{}" class="latex"{}>'.format( xss.escape(attachment.get_url()), val, img_params_to_html(token.attrs))
def get_link(self): return mark_safe(u'<a href="{}" class="{}">{}</a>'.format( self.get_absolute_url(), self.get_type_css_class(), xss.escape(self.name)))
def convert_to_html(self): tokens = self._pre_convert_to_html() if self.errors_mode == Converter.ERRORS_ENABLED: error_func = lambda token: u'<span class="mc-error">' \ u'<span class="mc-error-source">{}</span> {}</span>'.format( token.content, token.error_message) elif self.errors_mode == Converter.ERRORS_TESTING: error_func = lambda token: u"<<ERROR>>" else: error_func = lambda token: u"" class HTMLConverterState(object): def __init__(self): self.any_content_yet = False self.is_in_paragraph = False self.indent_next = False self.all_no_indent = False # List of all supported lengths. None stands for the default # value. These are the HTML values. self.lengths_html = {'\\parindent': None, '\\parskip': None} self._state_stack = [HTMLConverterState()] self.state = self._state_stack[-1] output = [] def add_content_par(content): """First check if paragraph should be added and then add content. No-op if content evaluates to False.""" if not content: return state = self.state state.any_content_yet = True if not self.paragraphs_disabled and not state.is_in_paragraph: indent = state.indent_next and not state.all_no_indent css_class = "" css_style = "" parskip = state.lengths_html['\\parskip'] if parskip is not None: # It seems to be the top, not the bottom that's affected. css_style += "margin-top:{};".format(parskip) if indent: parindent = state.lengths_html['\\parindent'] if parindent is not None: css_style += "text-indent:{};".format(parindent) else: css_class = "mc-indent" else: css_class = "mc-noindent" output.append("<p{}{}>".format( " class=\"{}\"".format(css_class) if css_class else "", " style=\"{}\"".format(css_style) if css_style else "")) output.append(content) state.is_in_paragraph = True for token in tokens: if isinstance(token, TokenComment): continue elif isinstance(token, TokenOpenCurly): self.push_state() elif isinstance(token, TokenClosedCurly): if len(self._state_stack) == 1: output.append(TokenError(_("Unexpected '}'"), '}')) else: self.pop_state() elif isinstance(token, TokenMath): element = self.maths[(token.format, token.content)] add_content_par( self.get_latex_html__func(element, token.force_inline)) elif isinstance(token, TokenText): add_content_par(xss.escape(token.text).replace('~', ' ')) elif isinstance(token, TokenSimpleWhitespace): if self.state.any_content_yet: output.append(" ") # Single whitespace is enough. elif isinstance(token, TokenMultilineWhitespace): if self.paragraphs_disabled: output.append("<br>") elif self.state.any_content_yet: self.state.is_in_paragraph = False self.state.indent_next = True elif isinstance(token, TokenError): add_content_par(error_func(token)) elif isinstance(token, TokenCommand): command = latex_commands[token.command] # TODO: \begin{equation}...\end{equation} try: if token.command in ['begin', 'end']: output.append(command.to_html(token, self)) else: add_content_par(command.to_html(token, self)) except LatexValueError as e: output.append(TokenError(e.message, '\\' + token.command)) elif isinstance(token, TokenBBCode): add_content_par(self.process_bb(token, TYPE_HTML)) else: raise NotImplementedError(repr(token)) return self.finalize_output(output, error_func)