예제 #1
0
    def page_rev_metas(request, page, metakeys, checkAccess):
        if "-gwikirevision-" in page:
            metas = get_metas(request, page, metakeys, checkAccess=checkAccess)
            page, revision = page.split("-gwikirevision-")
        else:
            metas = get_metas(request, page, metakeys, checkAccess=checkAccess)
            revision = ""

        return metas, page, revision
예제 #2
0
    def page_rev_metas(request, page, metakeys, checkAccess):
        if '-gwikirevision-' in page:
            metas = get_metas(request, page, metakeys, checkAccess=checkAccess)
            page, revision = page.split('-gwikirevision-')
        else:
            metas = get_metas(request, page, metakeys, checkAccess=checkAccess)
            revision = ''

        return metas, page, revision
예제 #3
0
def execute(macro, args):
    request = macro.request
    _ = request.getText

    if args:
        args = [x.strip() for x in args.split(',')]
    # Wrong number of arguments
    if not args or len(args) not in [1, 2]:
        return render_error(
            _("GetMetaData: Need to specify page, or page and key"))

    # Get all non-empty args
    args = [x for x in args if x]

    # If not page specified, defaulting to current page
    if len(args) == 1:
        page = request.page.page_name
        key = args[0]
    elif len(args) == 2:
        page = args[0]
        key = args[1]
    # Faulty args
    else:
        return render_error(
            _("GetMetaData: Need to specify page, or page and key"))

    vals = get_metas(request, page, [key], formatLinks=True)

    val = ', '.join(vals[key])

    return format_wikitext(request, val)
예제 #4
0
def execute(xmlrpcobj, args, keysonly=True):
    request = xmlrpcobj.request
    _ = request.getText
    args = xmlrpcobj._instr(args)

    # Expects MetaTable arguments
    pagelist, metakeys, _ = metatable_parseargs(request, args, 
                                                get_all_keys=True)
    # If we only want the keys as specified by the args
    if keysonly:
        return list(metakeys), list(pagelist)

    # Keys to the first row
    out = []
    out.append(metakeys)

    # Go through the pages, give list that has
    # the name of the page followed by the values of the keys
    for page in pagelist:
        # We're pretty sure the user has the read access to the pages,
        # so don't check again
        metas = get_metas(request, page, metakeys, checkAccess=False)
        row = [page]
        for key in metakeys:
            row.append([value for value in metas[key]])
        out.append(row)

    return out
예제 #5
0
def do_action(request, args, keysonly=True):
    # Expects MetaTable arguments
    pagelist, metakeys, _ = metatable_parseargs(request,
                                                args,
                                                get_all_keys=True)
    # If we only want the keys as specified by the args
    if keysonly:
        return list(metakeys), list(pagelist)

    # Keys to the first row
    out = []
    out.append(metakeys)

    # Go through the pages, give list that has
    # the name of the page followed by the values of the keys
    for page in pagelist:
        # We're pretty sure the user has the read access to the pages,
        # so don't check again
        metas = get_metas(request, page, metakeys, checkAccess=False)
        row = [page]
        for key in metakeys:
            row.append([value for value in metas[key]])
        out.append(row)

    return out
예제 #6
0
def execute(macro, args):
    formatter = macro.formatter
    macro.request.page.formatter = formatter
    request = macro.request

    if not args:
        return ''

    # Note, metatable_parseargs deals with permissions
    pagelist, metakeys, styles = metatable_parseargs(request, args,
                                                     get_all_keys=True)

    namekey = ''
    if metakeys and '%s||' % metakeys[0] in args:
        namekey = metakeys[0]

    out = list()

    for page in pagelist:
        text = ''
        if namekey:
            metas = get_metas(request, page, [namekey],
                              checkAccess=False, formatLinks=True)
            text = ', '.join(metas[namekey])

        if not text:
            text = page

        out.append(Page(request, page).link_to(request, text=text))

    return ', '.join(out)
예제 #7
0
def execute(macro, args):
    request = macro.request
    _ = request.getText

    if args:
        args = [x.strip() for x in args.split(',')]
    # Wrong number of arguments
    if not args or len(args) not in [1, 2]:
        return render_error( _("GetMetaData: Need to specify page, or page and key"))

    # Get all non-empty args
    args = [x for x in args if x]

    # If not page specified, defaulting to current page
    if len(args) == 1:
        page = request.page.page_name
        key = args[0]
    elif len(args) == 2:
        page = args[0]
        key = args[1]
    # Faulty args
    else:
        return render_error(_("GetMetaData: Need to specify page, or page and key"))

    vals = get_metas(request, page, [key], formatLinks=True)

    val = ', '.join(vals[key])

    return format_wikitext(request, val)
예제 #8
0
def do_action(request, args):
    # Expects MetaTable arguments
    pagelist, metakeys, _ = metatable_parseargs(request, args,
                                                get_all_keys=True)

    out = {}
    # We're pretty sure the user has the read access to the pages,
    # so don't check again
    for page in pagelist:
        metas = get_metas(request, page, metakeys, checkAccess=False)
        out[page] = dict(metas)
    return out
예제 #9
0
def do_action(request, args):
    # Expects MetaTable arguments
    pagelist, metakeys, _ = metatable_parseargs(request,
                                                args,
                                                get_all_keys=True)

    out = {}
    # We're pretty sure the user has the read access to the pages,
    # so don't check again
    for page in pagelist:
        metas = get_metas(request, page, metakeys, checkAccess=False)
        out[page] = dict(metas)
    return out
예제 #10
0
def formatMetaSelection(request, pages, keys, styles, addpagename=False):

    f = request.formatter
    divfmt = {'class': 'metaselection_area'}
    listfmt = {'class': 'metaselection_list'}
    entryfmt = {'class': 'metaselection_entry'}

    result = ''
    result = f.div(1, **divfmt)
    result += f.bullet_list(1, **listfmt)

    tmp_page = request.page

    for page in pages:

        pageobj = Page(request, page)
        request.page = pageobj
        request.formatter.page = pageobj

        metas = get_metas(request,
                          page,
                          keys,
                          checkAccess=True,
                          formatLinks=True)

        result += f.listitem(1, **entryfmt)

        args = {'class': 'metaselection_link'}

        for key in keys:
            for val in metas[key]:
                text = format_wikitext(request, val)
                result += pageobj.link_to_raw(request, text=text, **args)

        if addpagename:
            result += pageobj.link_to_raw(request,
                                          text=pageobj.page_name,
                                          **args)

        result += f.listitem(0)

    request.page = tmp_page
    request.formatter.page = tmp_page

    result += f.bullet_list(0)
    result += f.div(0)
    return result
def getPurchases(request, page, key):
    metas = get_metas(request, page, [key], checkAccess=False)
    first = 2**32
    last = 0

    values = metas[key]
    if len(values) == 0:
        return 0, 0

    for value in values:
        value = value.strip()
        ts = stringToTime(value)

        first = min(first, ts)
        last = max(last, ts)

    return first, last
예제 #12
0
def execute(macro, args):
    tset = set(['score', 'vector'])
    request = macro.request
    _ = request.getText

    if args:
        args = [x.strip() for x in args.split(',')]
    # Wrong number of arguments
    if len(args) not in [0, 1, 2]:
        return render_error(
            _("CVSS: Need to specify a page or page and " +
              "type (score|vector)."))

    # Get all non-empty args
    args = [x for x in args if x]

    # If page is not specified, defaulting to current page
    if len(args) == 0:
        page = request.page.page_name
        type = "score"
    elif len(args) == 1:
        page = args[0]
        type = "score"
    else:
        page = args[0]
        type = args[1]
        if type not in tset:
            return render_error(
                _("CVSS: The type needs to be either score " + "or vector."))

    base_metas = get_metas(request, page, [
        "Access Vector", "Access Complexity", "Authentication",
        "Confidentiality", "Integrity", "Availability"
    ])
    vector = buildVector(base_metas)
    if vector is not None:
        if type == "vector":
            return format_wikitext(request, vector)
        cvss = parse_cvss(vector)
        bscore = basescore(cvss)
        bstring = "%s" % bscore
        return format_wikitext(request, bstring)
    else:
        return render_error(_("CVSS: Invalid value(s) in Base Metrics."))
def countOwned(request, page, key):
    metas = get_metas(request, page, [key], checkAccess=False)
    total = 0

    values = metas[key]
    for value in values:
        value = value.strip().split()
        if len(value) != 2:
            continue

        ts, amount = value
        try:
            amount = int(amount)
        except ValueError:
            amount = 0

        total += amount

    return total
예제 #14
0
def formatMetaSelection(request, pages, keys, styles, addpagename=False):

    f = request.formatter
    divfmt = {'class': 'metaselection_area'}
    listfmt = {'class': 'metaselection_list'}
    entryfmt = {'class': 'metaselection_entry'}

    result = ''
    result = f.div(1, **divfmt)
    result += f.bullet_list(1, **listfmt)

    tmp_page = request.page

    for page in pages:

        pageobj = Page(request, page)
        request.page = pageobj
        request.formatter.page = pageobj

        metas = get_metas(request, page, keys,
                          checkAccess=True, formatLinks=True)

        result += f.listitem(1, **entryfmt)

        args = {'class': 'metaselection_link'}

        for key in keys:
            for val in metas[key]:
                text = format_wikitext(request, val)
                result += pageobj.link_to_raw(request, text=text, **args)

        if addpagename:
            result += pageobj.link_to_raw(request,
                                          text=pageobj.page_name, **args)

        result += f.listitem(0)

    request.page = tmp_page
    request.formatter.page = tmp_page

    result += f.bullet_list(0)
    result += f.div(0)
    return result
def countUsage(request, page, key):
    metas = get_metas(request, page, [key], checkAccess=False)
    spans = Spanner()

    values = metas[key]
    for value in values:
        value = value.strip().split()
        if len(value) != 2:
            continue

        start, end = value
        start = stringToTime(start)
        end = stringToTime(end)
        if not (start and end):
            continue

        spans.addSpan(start, end)

    total = sum(map(lambda (start, end): end-start, spans))
    total /= float(60*60*24)
    return total
예제 #16
0
def execute(macro, args):
    tset = set(['score', 'vector'])
    request = macro.request
    _ = request.getText

    if args:
        args = [x.strip() for x in args.split(',')]
    # Wrong number of arguments
    if len(args) not in [0, 1, 2]:
        return render_error(_("CVSS: Need to specify a page or page and " +
                              "type (score|vector)."))

    # Get all non-empty args
    args = [x for x in args if x]

    # If page is not specified, defaulting to current page
    if len(args) == 0:
        page = request.page.page_name
        type = "score"
    elif len(args) == 1:
        page = args[0]
        type = "score"
    else:
        page = args[0]
        type = args[1]
        if type not in tset:
            return render_error(_("CVSS: The type needs to be either score " +
                                  "or vector."))

    base_metas = get_metas(request, page, ["Access Vector", "Access Complexity", "Authentication", "Confidentiality", "Integrity", "Availability"])
    vector = buildVector(base_metas)
    if vector is not None:
        if type == "vector":
            return format_wikitext(request, vector)
        cvss = parse_cvss(vector)
        bscore = basescore(cvss)
        bstring = "%s" % bscore
        return format_wikitext(request, bstring)
    else:
        return render_error(_("CVSS: Invalid value(s) in Base Metrics."))
예제 #17
0
def inc_get_metas(request, args, handle=None):
    pages, keys, _ = metatable_parseargs(request, args, get_all_keys=True)

    current = dict()
    for page in pages:
        request.page = Page(request, page)
        # metatable_parseargs checks read permissions, no need to do it again
        metas = get_metas(request, page, keys, checkAccess=False)

        current[page] = dict()
        for key in keys:
            values = set(metas[key])
            current[page][key] = values

    cachedir = os.path.join(request.cfg.cache_dir, "getmetas")
    if not os.path.exists(cachedir):
        os.makedirs(cachedir)

    lock = WriteLock(cachedir, timeout=60.0)
    success = lock.acquire()

    path = os.path.join(cachedir, request.cfg.siteid + ".shelve")
    db = shelve.open(path)

    incremental = True
    try:
        if not handle or handle not in db:
            incremental = False
            handle = create_new_handle(db)
        previous = db.get(handle, dict())
        db[handle] = current
    finally:
        db.close()

    if lock.isLocked():
        lock.release()

    return [incremental, handle, diff(previous, current)]
예제 #18
0
def execute(pagename, request):
    metas = get_metas(request, pagename, ["Type"], checkAccess=False)
    typeValue = metas.get("Type")
    if len(typeValue) == 0:
        licenseType = "cookie"
    else:
        licenseType = typeValue[0]

    if licenseType == "traditional":
        fake = FakeXmlrpcObj()
        fake.request = request
        cookie = generateCookie(fake, str(pagename))
        if isinstance(cookie, xmlrpclib.Fault):
            request.write(cookie.faultString)
            return

        filename = "license.key"
        request.headers['Content-Type'] = 'application/octet-stream',
        request.headers['Content-Disposition'] = 'attachment; ' + \
            'filename="%s"' % filename
        request.write(cookie.data)
    else:
        GetCookie(pagename, request).render()
예제 #19
0
def execute(macro, args):
    formatter = macro.formatter
    macro.request.page.formatter = formatter
    request = macro.request
    _ = request.getText

    if not have_cairo():
        return _sysmsg % ('error', _(\
                "ERROR: Cairo Python extensions not installed. " +\
                    "Not performing layout."))

    url_args, args = radarchart_args(args)

    # For multiple radar charts per table row
    try:
        height = ''.join(url_args.get('height', list()))
        width = ''.join(url_args.get('width', list()))
        if not height:
            height = MAX_WIDTH
        if not width:
            width = MAX_WIDTH
        height, width = int(height), int(width)
    except ValueError:
        pass

    # MAX_WIDTH is the assumed max_width here
    amount = MAX_WIDTH / min(height, width)
    if amount < 1:
        amount = 1

    # Note, metatable_parseargs deals with permissions
    pagelist, metakeys, _ = metatable_parseargs(request,
                                                args,
                                                get_all_keys=True)

    values = set()
    for page in pagelist:
        metas = get_metas(request, page, metakeys)
        for key in metas:
            # Get the maximum value of each key on a page
            if metas[key]:
                numberedvals = dict()
                for i, val in enumerate(map(ordervalue, metas[key])):
                    numberedvals[val] = i
                maxval = max(numberedvals.keys())
                i = numberedvals[maxval]
                # This contraption is here because we need to deliver
                # unparsed (textual) values in urls
                values.add(metas[key][i])
    for val in values:
        if val.startswith('attachment'):
            # A bit ugly fix for a weird corner case
            val = "attachment:%s" % (val[11:])
        url_args.setdefault('value', list()).append(val)

    out = StringIO.StringIO()
    out.write(macro.formatter.linebreak() + u'<div class="metaradartable">' +
              macro.formatter.table(1))

    rowcount = (len(pagelist) / amount)
    if len(pagelist) % amount:
        rowcount += 1
    # Iterate over the number of rows
    for i in range(rowcount):

        out.write(macro.formatter.table_row(1))

        pages = pagelist[i * amount:(i + 1) * amount]

        # First enter page names to first row
        for page in pages:
            out.write(macro.formatter.table_cell(1, {'class': 'meta_page'}))
            out.write(macro.formatter.pagelink(1, page))
            out.write(macro.formatter.text(page))
            out.write(macro.formatter.pagelink(0))
            out.write(macro.formatter.linebreak())
        # Don't make extra squares for the first row
        if i:
            for j in range(amount - len(pages)):
                out.write(macro.formatter.table_cell(1))

        out.write(macro.formatter.table_row(1))

        # Chart images to the other row
        for page in pages:
            out.write(macro.formatter.table_cell(1, {'class': 'meta_radar'}))
            out.write(u'<img src="%s">' %
                      (url_construct(request, url_args, page)))
            out.write(macro.formatter.linebreak())
        if i:
            for j in range(amount - len(pages)):
                out.write(macro.formatter.table_cell(1))

    out.write(macro.formatter.table(0) + u'</div>')

    return out.getvalue()
예제 #20
0
def construct_table(macro, pagelist, metakeys,
                    legend='', checkAccess=True, styles=dict()):
    request = macro.request
    request.page.formatter = request.formatter

    row = 0

    # Start table
    request.write(macro.formatter.linebreak() +
                  u'<div class="metaselection">' +
                  macro.formatter.table(1))

    if metakeys:
        # Give a class to headers to make it customisable
        request.write(macro.formatter.table_row(1, {'rowclass':
                                                    'meta_header'}))
        # Upper left cell is empty or has the desired legend
        t_cell(macro, [legend])

    for key in metakeys:
        style = styles.get(key, dict())

        # Styles can modify key naming
        name = style.get('gwikiname', '').strip('"')

        # We don't want stuff like bullet lists in out header
        headerstyle = dict()
        for st in style:
            if not st.startswith('gwiki'):
                headerstyle[st] = style[st]

        if name:
            t_cell(macro, [name], style=headerstyle)
        else:
            t_cell(macro, [key], style=headerstyle)

    request.write(macro.formatter.table_row(0))

    tmp_page = request.page

    for page in pagelist:

        if '-gwikirevision-' in page:
            metas = get_metas(request, page, metakeys,
                              checkAccess=checkAccess, formatLinks=True)
            page, revision = page.split('-gwikirevision-')
        else:
            metas = get_metas(request, page, metakeys,
                              checkAccess=checkAccess, formatLinks=True)
            revision = ''

        pageobj = Page(request, page)
        request.page = pageobj
        request.formatter.page = pageobj

        row = row + 1

        if row % 2:
            request.write(macro.formatter.table_row(1, {'rowclass':
                                                        'metatable-odd-row'}))
        else:
            request.write(macro.formatter.table_row(1, {'rowclass':
                                                        'metatable-even-row'}))
        t_cell(macro, [page], head=1, rev=revision)

        for key in metakeys:
            style = styles.get(key, dict())
            t_cell(macro, metas[key], style=style)

        request.write(macro.formatter.table_row(0))

    request.page = tmp_page
    request.formatter.page = tmp_page

    request.write(macro.formatter.table(0))
    request.write(u'</div>')
예제 #21
0
def execute(macro, args):
    formatter = macro.formatter
    macro.request.page.formatter = formatter
    request = macro.request
    _ = request.getText

    if not have_cairo():
        return _sysmsg % ('error', _(\
                "ERROR: Cairo Python extensions not installed. " +\
                    "Not performing layout."))

    url_args, args = radarchart_args(args)

    # For multiple radar charts per table row
    try:
        height = ''.join(url_args.get('height', list()))
        width = ''.join(url_args.get('width', list()))
        if not height: 
            height = MAX_WIDTH
        if not width:
            width = MAX_WIDTH
        height, width = int(height), int(width)
    except ValueError:
        pass

    # MAX_WIDTH is the assumed max_width here
    amount = MAX_WIDTH / min(height, width)
    if amount < 1:
        amount = 1

    # Note, metatable_parseargs deals with permissions
    pagelist, metakeys, _ = metatable_parseargs(request, args,
                                                get_all_keys=True)

    values = set()
    for page in pagelist:
        metas = get_metas(request, page, metakeys)
        for key in metas:
            # Get the maximum value of each key on a page
            if metas[key]:
                numberedvals = dict()
                for i, val in enumerate(map(ordervalue, metas[key])):
                    numberedvals[val] = i
                maxval = max(numberedvals.keys())
                i = numberedvals[maxval]
                # This contraption is here because we need to deliver
                # unparsed (textual) values in urls
                values.add(metas[key][i])
    for val in values:
        if val.startswith('attachment'):
            # A bit ugly fix for a weird corner case
            val = "attachment:%s" % (val[11:])
        url_args.setdefault('value', list()).append(val)

    out = StringIO.StringIO()
    out.write(macro.formatter.linebreak() +
              u'<div class="metaradartable">' +
              macro.formatter.table(1))

    rowcount = (len(pagelist) / amount)
    if len(pagelist) % amount:
        rowcount += 1
    # Iterate over the number of rows
    for i in range(rowcount):

        out.write(macro.formatter.table_row(1))

        pages = pagelist[i*amount:(i+1)*amount]

        # First enter page names to first row
        for page in pages:
            out.write(macro.formatter.table_cell(1, {'class': 'meta_page'}))
            out.write(macro.formatter.pagelink(1, page))
            out.write(macro.formatter.text(page))
            out.write(macro.formatter.pagelink(0))
            out.write(macro.formatter.linebreak())
        # Don't make extra squares for the first row
        if i:
            for j in range(amount - len(pages)):
                out.write(macro.formatter.table_cell(1))

        out.write(macro.formatter.table_row(1))

        # Chart images to the other row
        for page in pages:
            out.write(macro.formatter.table_cell(1, {'class': 'meta_radar'}))
            out.write(u'<img src="%s">' % 
                      (url_construct(request, url_args, page)))
            out.write(macro.formatter.linebreak())
        if i:
            for j in range(amount - len(pages)):
                out.write(macro.formatter.table_cell(1))

    out.write(macro.formatter.table(0) + u'</div>')

    return out.getvalue()
예제 #22
0
def execute(pagename, request):
    if not have_cairo():
        error = request.getText(
            "ERROR: Cairo Python extensions not installed. " +
            "Not performing layout."
        )
        request.content_type = 'text/plain'
        request.write(error)
        return

    request.content_type = "image/png"

    # Grab arguments
    args = ', '.join(x for x in request.values.getlist('arg'))

    params = {'height': 0, 'width': 0}

    # Height and Width
    for attr in ['height', 'width']:
        if request.values.has_key(attr):
            val = ''.join(request.values.getlist(attr))
            try:
                params[attr] = int(val)
            except ValueError:
                pass

    # Aggregate set of included values of a page
    values = set()
    if request.values.has_key('value'):
        values.update(map(ordervalue, request.values.getlist('value')))

    # Values that need to be included to form a complete scale, say 1-10
    scale = list()
    if request.values.has_key('scale'):
        scale = request.values['scale']

    if not params['height'] and params['width']:
        params['height'] = params['width']
    elif params['height'] and not params['width']:
        params['width'] = params['height']
    elif not params['height'] and not params['width']:
        params['width'] = params['height'] = 1000

    # calculate center and radius, leave some room for text and stuff
    center = (params['height'] / 2, params['width'] / 2)
    radius = min(center)
    if radius > 50:
        radius -= 50

    # Setup Cairo
    surface = cairo.ImageSurface(cairo.FORMAT_ARGB32,
                                 params['height'], params["width"])
    ctx = cairo.Context(surface)
    ctx.select_font_face("Times-Roman", cairo.FONT_SLANT_NORMAL,
                         cairo.FONT_WEIGHT_BOLD)
    ctx.set_font_size(12)

    ctx.set_source_rgb(1.0, 1.0, 1.0)
    ctx.rectangle(0, 0, params['width'], params['height'])
    ctx.fill()

    ctx.set_source_rgb(0.0, 0.0, 0.0)

    # Note, metatable_parseargs deals with permissions
    pagelist, metakeys, _ = metatable_parseargs(request, args,
                                                get_all_keys=True)
    metakeys = filter(lambda x: x not in SPECIAL_ATTRS, metakeys)

    # If no keys, print nothing
    if not pagelist:
        request.write(plot_error(request))
        return

    # Populate data to the radar chart
    data = dict()
    for page in pagelist:
        # On links, we want a list of page names, not their markup
        metas = get_metas(request, page, metakeys, checkAccess=False)

        # Get the maximum value of each key on a page
        for key in metakeys:
            data.setdefault(key, list())
            if metas[key]:
                scale.extend(map(ordervalue, metas[key]))
                if page == pagename:
                    data[key].append(max(map(ordervalue, metas[key])))

    # Get values for the chart axes
    data_per_axis = dict()
    for axis, key in enumerate(metakeys):
        data_per_axis[axis] = key

    if not values:
        for x in data.values():
            values.update(x)

    if scale:
        values.update(scale)

    values = sorted(values)

    # Refuse to draw if no values for any key
    if not len(values):
        request.write(plot_error(request))
        return

    no_values = len(values) + 1
    per_value = radius / no_values

    sectors = len(data)
    angle = 2*math.pi/sectors

    cur_radius = per_value
    # Make the base grid
    for x in range(1, no_values):
        ctx, gridpoints = spider_radius(ctx, center, cur_radius, sectors)
        cur_radius += per_value

    # Apply ink from strokes so far
    ctx.stroke()

    # Now start to make chart on top of the base
    ctx.set_source_rgb(50/255.0,137/255.0,37/255.0)
    ctx.set_line_width(5)

    endpoints = list()

    # Find coords for each value
    for i in range(sectors):
        val = data[data_per_axis[i]]
        if val:
            val = val.pop()
            radius = values.index(val) + 1
        else:
            # If no values exist, it's in the bottom
            radius = 0
        x, y = spider_coords(radius * per_value, i*angle)

        endpoints.append(add_to_center(center, (x, y)))

    draw_path(ctx, endpoints)

    # Draw path filling the contents
    ctx.stroke_preserve()
    ctx.set_source_rgba(150/255.0,190/255.0,13/255.0, 0.2)
    ctx.fill()

    # Write axis names on top of it all
    for point, axis in zip(gridpoints, data_per_axis.keys()):
        text = data_per_axis[axis]

        ctx.set_source_rgba(1, 1, 1, 0.9)
        width, height = ctx.text_extents(text)[2:4]

        # Move texts on the left side a bit left
        if point[0] < center[0]:
            point = (point[0] - width, point[1])

        width, height = width * 1.2, -height * 1.2
        x, y = point[0] - 0.1 * width, point[1] + 0.1 * height
        ctx.rectangle(x, y, width, height)
        ctx.fill()

        ctx.set_source_rgb(0, 0, 0)
        ctx.move_to(*point)
        ctx.show_text(text)

    request.write(cairo_surface_to_png(surface))
예제 #23
0
def execute(pagename, request):
    if not have_cairo():
        error = request.getText(
            "ERROR: Cairo Python extensions not installed. " +
            "Not performing layout.")
        request.content_type = 'text/plain'
        request.write(error)
        return

    request.content_type = "image/png"

    # Grab arguments
    args = ', '.join(x for x in request.values.getlist('arg'))

    params = {'height': 0, 'width': 0}

    # Height and Width
    for attr in ['height', 'width']:
        if request.values.has_key(attr):
            val = ''.join(request.values.getlist(attr))
            try:
                params[attr] = int(val)
            except ValueError:
                pass

    # Aggregate set of included values of a page
    values = set()
    if request.values.has_key('value'):
        values.update(map(ordervalue, request.values.getlist('value')))

    # Values that need to be included to form a complete scale, say 1-10
    scale = list()
    if request.values.has_key('scale'):
        scale = request.values['scale']

    if not params['height'] and params['width']:
        params['height'] = params['width']
    elif params['height'] and not params['width']:
        params['width'] = params['height']
    elif not params['height'] and not params['width']:
        params['width'] = params['height'] = 1000

    # calculate center and radius, leave some room for text and stuff
    center = (params['height'] / 2, params['width'] / 2)
    radius = min(center)
    if radius > 50:
        radius -= 50

    # Setup Cairo
    surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, params['height'],
                                 params["width"])
    ctx = cairo.Context(surface)
    ctx.select_font_face("Times-Roman", cairo.FONT_SLANT_NORMAL,
                         cairo.FONT_WEIGHT_BOLD)
    ctx.set_font_size(12)

    ctx.set_source_rgb(1.0, 1.0, 1.0)
    ctx.rectangle(0, 0, params['width'], params['height'])
    ctx.fill()

    ctx.set_source_rgb(0.0, 0.0, 0.0)

    # Note, metatable_parseargs deals with permissions
    pagelist, metakeys, _ = metatable_parseargs(request,
                                                args,
                                                get_all_keys=True)
    metakeys = filter(lambda x: x not in SPECIAL_ATTRS, metakeys)

    # If no keys, print nothing
    if not pagelist:
        request.write(plot_error(request))
        return

    # Populate data to the radar chart
    data = dict()
    for page in pagelist:
        # On links, we want a list of page names, not their markup
        metas = get_metas(request, page, metakeys, checkAccess=False)

        # Get the maximum value of each key on a page
        for key in metakeys:
            data.setdefault(key, list())
            if metas[key]:
                scale.extend(map(ordervalue, metas[key]))
                if page == pagename:
                    data[key].append(max(map(ordervalue, metas[key])))

    # Get values for the chart axes
    data_per_axis = dict()
    for axis, key in enumerate(metakeys):
        data_per_axis[axis] = key

    if not values:
        for x in data.values():
            values.update(x)

    if scale:
        values.update(scale)

    values = sorted(values)

    # Refuse to draw if no values for any key
    if not len(values):
        request.write(plot_error(request))
        return

    no_values = len(values) + 1
    per_value = radius / no_values

    sectors = len(data)
    angle = 2 * math.pi / sectors

    cur_radius = per_value
    # Make the base grid
    for x in range(1, no_values):
        ctx, gridpoints = spider_radius(ctx, center, cur_radius, sectors)
        cur_radius += per_value

    # Apply ink from strokes so far
    ctx.stroke()

    # Now start to make chart on top of the base
    ctx.set_source_rgb(50 / 255.0, 137 / 255.0, 37 / 255.0)
    ctx.set_line_width(5)

    endpoints = list()

    # Find coords for each value
    for i in range(sectors):
        val = data[data_per_axis[i]]
        if val:
            val = val.pop()
            radius = values.index(val) + 1
        else:
            # If no values exist, it's in the bottom
            radius = 0
        x, y = spider_coords(radius * per_value, i * angle)

        endpoints.append(add_to_center(center, (x, y)))

    draw_path(ctx, endpoints)

    # Draw path filling the contents
    ctx.stroke_preserve()
    ctx.set_source_rgba(150 / 255.0, 190 / 255.0, 13 / 255.0, 0.2)
    ctx.fill()

    # Write axis names on top of it all
    for point, axis in zip(gridpoints, data_per_axis.keys()):
        text = data_per_axis[axis]

        ctx.set_source_rgba(1, 1, 1, 0.9)
        width, height = ctx.text_extents(text)[2:4]

        # Move texts on the left side a bit left
        if point[0] < center[0]:
            point = (point[0] - width, point[1])

        width, height = width * 1.2, -height * 1.2
        x, y = point[0] - 0.1 * width, point[1] + 0.1 * height
        ctx.rectangle(x, y, width, height)
        ctx.fill()

        ctx.set_source_rgb(0, 0, 0)
        ctx.move_to(*point)
        ctx.show_text(text)

    request.write(cairo_surface_to_png(surface))
def construct_table(macro, pagelist, key, sort_order):
    request = macro.request
    request.page.formatter = request.formatter

    count = dict()

    orginalPage = request.page

    for page in pagelist:
        pageobj = Page(request, page)
        request.page = pageobj
        request.formatter.page = pageobj

        # WARNING: Skipping access check because we know that metatable_parseargs
        #          already  checked  them. If you plan to use this code elsewhere
        #          you should make sure that you check for access.
        metas = get_metas(request, page, [key], checkAccess=False)

        for value in metas[key]:
            current = count.get(value, 0)
            count[value] = current + 1

    request.write(macro.formatter.linebreak() +
                  u'<div class="metatable">' +
                  macro.formatter.table(1))
    request.write(macro.formatter.table_row(1, {'rowclass':
                                                'meta_header'}))
    t_cell(macro, key)
    t_cell(macro, "Count")
    request.write(macro.formatter.table_row(0))

    row = 0

    tmp = list()

    for value, count in count.iteritems():
        tmp.append((count, value))

    if sort_order == "value":
        tmp.sort(key=lambda (x, y): y)
    elif sort_order == "count":
        tmp.sort(key=lambda (x, y): x, reverse=True)

    s = sum(map(lambda (x, y): x, tmp))

    tmp.append((s, "Sum"))

    for value, key in tmp:
        row = row + 1

        if row % 2:
            request.write(macro.formatter.table_row(1, {'rowclass':
                                                        'metatable-odd-row'}))
        else:
            request.write(macro.formatter.table_row(1, {'rowclass':
                                                        'metatable-even-row'}))

        t_cell(macro, key)
        t_cell(macro, u"%d" % value)
        request.write(macro.formatter.table_row(0))

    request.page = orginalPage
    request.formatter.page = orginalPage

    request.write(macro.formatter.table(0))
    request.write(u'</div>')
예제 #25
0
def parse_editform(request, form):
    r"""
    >>> from MoinMoin.metadata.util import doctest_request
    >>> request = doctest_request()

    >>> parse_editform(request, {"Test-gwikiseparator-" : ["1", "2"], ":: " : ["a"]})
    {'Test': ({}, {'a': ['1', '2']})}

    >>> request = doctest_request({"Test" : {"meta" : {"a" : ["x"]}}})
    >>> parse_editform(request, {"Test-gwikiseparator-a" : ["1", "2"], ":: a" : ["a"]})
    {'Test': ({'a': ['x']}, {'a': ['1', '2']})}

    >>> request = doctest_request({"Test" : {"meta" : {"a" : ["x"]}}})
    >>> parse_editform(request, {"Test-gwikiseparator-a" : ["x"], ":: a" : [""]})
    {'Test': ({'a': ['x']}, {'a': ['']})}

    >>> request = doctest_request({"Test" : {"meta" : {"a" : ["1", "2"]}}})
    >>> parse_editform(request, {"Test-gwikiseparator-a" : ["1"], ":: a" : ["a"]})
    {'Test': ({'a': ['1', '2']}, {'a': ['1', '']})}
    """
    _ = request.getText

    msgs = list()
    keys = dict()
    pages = dict()
    files = dict()

    for key in request.files:
        f = request.files[key]
        if not f.filename:
            continue

        fileobj = f.stream

        page, key = key.split(SEPARATOR, 1)
        files.setdefault(page, dict())[key] = (f.filename, fileobj)

    # Key changes
    for oldKey, newKeys in form.iteritems():

        if not newKeys or not oldKey.startswith(':: '):
            continue

        newKey = newKeys[0].strip()
        oldKey = oldKey[3:].strip()
        if oldKey == newKey:
            continue

        keys[oldKey] = newKey

    # Value changes
    for pageAndKey, newValues in form.iteritems():
        if pageAndKey.endswith("__filename__"):
            continue

        # At least the key 'save' may be there and should be ignored
        if not SEPARATOR in pageAndKey:
            continue

        # Form keys not autodecoded from utf-8
        page, oldKey = pageAndKey.split(SEPARATOR, 1)

        # Decoding pagename
        page = url_unquote(page)
        newKey = keys.get(oldKey, oldKey)

        if not request.user.may.write(page):
            err = '%s: ' % page + _('You are not allowed to edit this page.')
            if not err in msgs:
                msgs.append(err)
            continue

        oldMeta, newMeta = pages.setdefault(page, (dict(), dict()))

        if oldKey:
            oldMetas = get_metas(request,
                                 page, [oldKey],
                                 abs_attach=False,
                                 includeGenerated=False)
            oldValues = oldMetas[oldKey]

            oldMeta.setdefault(oldKey, list()).extend(oldValues)

            if newKey != oldKey:
                # Remove the corresponding values
                newMeta.setdefault(oldKey,
                                   list()).extend([""] * len(oldValues))

        if newKey:
            missing = 0
            if oldKey:
                missing = len(oldValues) - len(newValues)

            newMeta.setdefault(newKey, list()).extend(newValues)
            newMeta.setdefault(newKey, list()).extend([""] * missing)

    # Prune
    for page, (oldMeta, newMeta) in list(pages.iteritems()):
        for key in list(newMeta):
            if key not in oldMeta:
                continue
            if oldMeta[key] != newMeta[key]:
                continue
            del oldMeta[key]
            del newMeta[key]

        if not (oldMeta or newMeta):
            del pages[page]

    for page in files:
        metas = pages.get(page, (dict(), dict()))[1]
        for key in files[page]:
            filename, descriptor = files[page][key]
            values = metas.get(key, list())
            try:
                index = values.index(descriptor)
                values[index] = "[[attachment:%s]]" % filename
            except ValueError:
                values.append("[[attachment:%s]]" % filename)

    return pages, msgs, files
예제 #26
0
def construct_table(macro, pagelist, metakeys,
                    legend='', checkAccess=True, styles=dict(),
                    addpagename=False):
    request = macro.request
    request.page.formatter = request.formatter
    out = str()

    row = 0

    entryfmt = {'class': 'metamatrix_entry'}

    # Start table
    out += macro.formatter.linebreak() + u'<div class="metamatrix">' + \
        macro.formatter.table(1)

    # Give a class to headers to make it customisable
    out += macro.formatter.table_row(1, {'rowclass': 'meta_head'})
    # Upper left cell is empty or has the desired legend
    out += t_cell(macro, [legend])

    x_key, y_key = metakeys[:2]

    x_values, y_values = set(), set()

    page_vals = dict()

    for page in pagelist:
        page_vals[page] = get_metas(request, page, metakeys,
                                    checkAccess=False, formatLinks=True)

        x_val = page_vals[page].get(x_key, set())
        y_val = page_vals[page].get(y_key, set())
        x_values.update([(page, x) for x in x_val])
        y_values.update([(page, y) for y in y_val])

    metakeys = metakeys[2:]

    header_cells = list()
    # Make header row
    for oval, value, page in sorted((ordervalue(y), y, page)
                                    for page, y in y_values):

        style = styles.get(y_key, dict())

        # Styles can modify key naming
        name = style.get('gwikiname', '').strip('"')

        # We don't want stuff like bullet lists in out header
        headerstyle = dict()
        for st in style:
            if not st.startswith('gwiki'):
                headerstyle[st] = style[st]

        if name:
            if not (value, name) in header_cells:
                header_cells.append((value, name))
        else:
            showvalue = metas_to_abs_links(request, page, [value])
            if not (value, showvalue[0]) in header_cells:
                header_cells.append((value, showvalue[0]))

    for value, showvalue in header_cells:
        out += t_cell(macro, [showvalue], style=headerstyle)

    out += macro.formatter.table_row(0)

    tmp_page = request.page

    f = macro.formatter

    # Table
    row_cells = list()
    row_values = list()
    for oval, x_value, page in sorted((ordervalue(x), x, page)
                                      for page, x in x_values):
        if not (oval, x_value) in row_values:
            row_cells.append((oval, x_value, page))
            row_values.append((oval, x_value))

    for oval, x_value, page in row_cells:
        row = row + 1

        if row % 2:
            out += f.table_row(1, {'rowclass': 'metamatrix-odd-row'})
        else:
            out += f.table_row(1, {'rowclass': 'metamatrix-even-row'})
        value = metas_to_abs_links(request, page, [x_value])
        out += t_cell(macro, value)

        for y_value, showvalue in header_cells:
            style = styles.get(y_value, dict())

            if not 'class' in style:
                style['class'] = 'meta_cell'

            out += f.table_cell(1, attrs=style)

            for page in pagelist:
                pageobj = Page(request, page)

                if (x_value in page_vals[page].get(x_key, set()) and
                        y_value in page_vals[page].get(y_key, set())):

                    result = ''

                    args = {'class': 'metamatrix_link'}

                    for key in metakeys:
                        for val in page_vals[page].get(key, list()):

                            # Strip ugly brackets from bracketed links
                            val = val.lstrip('[').strip(']')

                            result += f.listitem(1, **entryfmt)

                            result += pageobj.link_to(request,
                                                      text=val, **args)
                            result += f.listitem(0)

                    if addpagename:
                        result += f.listitem(1, **entryfmt)
                        result += pageobj.link_to(request, **args)
                        result += f.listitem(0)

                    out += result

        out += macro.formatter.table_row(0)

    request.page = tmp_page
    request.formatter.page = tmp_page

    out += macro.formatter.table(0)
    out += u'</div>'

    return out
def execute(xmlrpcobj, page, ttl=None, version=""):
    request = xmlrpcobj.request

    cfg = dict()
    for key, value in DEFAULTS.iteritems():
        cfg[key] = getattr(request.cfg, "cookie_" + key, value)

    if ttl is None:
        ttl = cfg["min_ttl"] * SECONDS_IN_DAY

    # Check if user has right to read page
    if not request.user.may.read(page):
        return xmlrpclib.Fault(1, "You are not allowed get this license.")

    # Encode the pagename and username properly (?)
    username = request.user.name
    pagename = page

    if not username:
        return xmlrpclib.Fault(1, "Unknown user")

    pagelist, metakeys, _ = metatable_parseargs(request, page, get_all_keys=True)
    metas = get_metas(request, page, metakeys, checkAccess=False)

    typeValue = metas.get("Type", [])
    if len(typeValue) == 0:
        licenseType = "cookie"
    else:
        licenseType = typeValue[0]

    if licenseType == "capped":
        usedCookies = countUsage(request, username + "/Bookkeeping", page)
        ownedCookies = countOwned(request, username + "/Shopkeeping", page)
        availableCookies = ownedCookies - usedCookies

    minTTL = getIntMeta(metas, "Minimum check-out period (days)", cfg["min_ttl"])
    maxTTL = getIntMeta(metas, "Maximum check-out period (days)", cfg["max_ttl"])

    minTTL *= SECONDS_IN_DAY
    maxTTL *= SECONDS_IN_DAY

    # Cap the cookie ttl between minTTL and maxTTL
    ttl = min(max(ttl, minTTL), maxTTL)

    if licenseType == "capped":
        ttl = min(ttl, availableCookies * SECONDS_IN_DAY)
        availableCookies -= ttl / SECONDS_IN_DAY

    if ttl <= 0:
        return xmlrpclib.Fault(1, "You don't have any cookies left!")

    if licenseType == "traditional":
        first, last = getPurchases(request, username + "/Shopkeeping", page)
        if first == 0 and last == 0:
            return xmlrpclib.Fault(1, "No purchased licenses found!")

        duration = getIntMeta(metas, "Duration (days)", cfg["default_duration"])
        issued = first
        expires = last + duration * SECONDS_IN_DAY
    else:
        # Start and end times for the cookie
        issued = int(time.time())
        expires = issued + ttl

    cookieData = reformatMetaDict(metas)
    cookieData["collabname"] = request.cfg.interwikiname
    cookieData["pagename"] = pagename
    cookieData["username"] = username
    cookieData["issued"] = int(issued)
    cookieData["expires"] = int(expires)

    if licenseType == "capped":
        cookieData["availableCookies"] = "%.02f" % availableCookies

    cookie = createCookieString(cookieData)

    failure = logCookieRequest(request, cfg, username, (issued, expires, pagename), version)
    if failure:
        return failure

    return signCookie(cfg, cookie)
예제 #28
0
def set_metas(request, cleared, discarded, added):
    pages = set(cleared) | set(discarded) | set(added)

    # Discard empties and junk
    pages = [wikiutil.normalize_pagename(x, request.cfg) for x in pages]
    pages = [x for x in pages if x]

    msg = list()

    # We don't have to check whether the user is allowed to read
    # the page, as we don't send any info on the pages out. Only
    # check that we can write to the requested pages.
    for page in pages:
        if not request.user.may.write(page):
            message = "You are not allowed to edit page '%s'" % page
            return False, request.getText(message)

    for page in pages:
        pageCleared = cleared.get(page, set())
        pageDiscarded = discarded.get(page, dict())
        pageAdded = added.get(page, dict())
        
        # Template clears might make sense at some point, not implemented
        if TEMPLATE_KEY in pageCleared:
            pageCleared.remove(TEMPLATE_KEY)
        # Template changes might make sense at some point, not implemented
        if TEMPLATE_KEY in pageDiscarded:
            del pageDiscarded[TEMPLATE_KEY]
        # Save templates for empty pages
        if TEMPLATE_KEY in pageAdded:
            save_template(request, page, ''.join(pageAdded[TEMPLATE_KEY]))
            del pageAdded[TEMPLATE_KEY]

        metakeys = set(pageCleared) | set(pageDiscarded) | set(pageAdded)
        # Filter out uneditables, such as inlinks
        metakeys = editable_p(metakeys)

        old = get_metas(request, page, metakeys, 
                        checkAccess=False, includeGenerated=False)

        new = dict()
        for key in old:
            values = old.pop(key)
            old[key] = values
            new[key] = set(values)
        for key in pageCleared:
            new[key] = set()
        for key, values in pageDiscarded.iteritems():
            for v in values:
                new[key].difference_update(values) 

        for key, values in pageAdded.iteritems():
            new[key].update(values)

        for key, values in new.iteritems():
            ordered = copy.copy(old[key])
            
            for index, value in enumerate(ordered):
                if value not in values:
                    ordered[index] = u""

            values.difference_update(ordered)
            ordered.extend(values)
            new[key] = ordered

        msg.append(edit_meta(request, page, old, new))

    return True, msg
예제 #29
0
def construct_table(macro, pagelist, metakeys, 
                    legend='', checkAccess=True, styles={}):
    request = macro.request
    request.page.formatter = request.formatter

    days = dict()
    times = dict()

    orginalPage = request.page

    for page in pagelist:
        pageobj = Page(request, url_unquote(page))
        request.page = pageobj
        request.formatter.page = pageobj

        metas = get_metas(request, page,
                          metakeys, checkAccess=checkAccess)

        spans = days.setdefault(page, spanner.Spanner())
        count = times.get(page, 0)

        for key in metakeys:
            values = metas[key]
            key = url_unquote(key)
            style = styles.get(key, {})
            for value in values:
                value = value.strip().split()
                if len(value) != 2:
                    continue

                start, end = value
                start = stringToTime(start)
                end = stringToTime(end)
                if not (start and end):
                    continue

                count += 1
                spans.addSpan(start, end)

        times[page] = count


    request.write(macro.formatter.linebreak() +
                  u'<div class="metatable">' +
                  macro.formatter.table(1))
    request.write(macro.formatter.table_row(1, {'rowclass':
                                                'meta_header'}))
    t_cell(macro, "User")
    t_cell(macro, "Used (days)")
    t_cell(macro, "Used (times)")
    request.write(macro.formatter.table_row(0))

    tmp = list()

    for key in days:
        value = days[key]
        total = sum(map(lambda (start, end): end-start, value))
        total /= float(60*60*24)

        count = times.get(key, 0)

        if count == 0:
            continue

        tmp.append((total, count, key))

    tmp.sort(reverse=True)

    row = 0
    for (days, times, user) in tmp:
        row = row + 1

        if row % 2:
            request.write(macro.formatter.table_row(1, {'rowclass':
                                                        'metatable-odd-row'}))
        else:
            request.write(macro.formatter.table_row(1, {'rowclass':
                                                        'metatable-even-row'}))
        t_cell(macro, url_unquote(user), head=1)
        t_cell(macro, u"%.02f" % days)
        t_cell(macro, u"%d" % times)
        request.write(macro.formatter.table_row(0))


    request.page = orginalPage 
    request.formatter.page = orginalPage 

    request.write(macro.formatter.table(0))
    request.write(u'</div>')
예제 #30
0
def construct_table(macro,
                    pagelist,
                    metakeys,
                    legend='',
                    checkAccess=True,
                    styles=dict()):
    request = macro.request
    request.page.formatter = request.formatter

    row = 0

    # Start table
    request.write(macro.formatter.linebreak() +
                  u'<div class="metaselection">' + macro.formatter.table(1))

    if metakeys:
        # Give a class to headers to make it customisable
        request.write(macro.formatter.table_row(1,
                                                {'rowclass': 'meta_header'}))
        # Upper left cell is empty or has the desired legend
        t_cell(macro, [legend])

    for key in metakeys:
        style = styles.get(key, dict())

        # Styles can modify key naming
        name = style.get('gwikiname', '').strip('"')

        # We don't want stuff like bullet lists in out header
        headerstyle = dict()
        for st in style:
            if not st.startswith('gwiki'):
                headerstyle[st] = style[st]

        if name:
            t_cell(macro, [name], style=headerstyle)
        else:
            t_cell(macro, [key], style=headerstyle)

    request.write(macro.formatter.table_row(0))

    tmp_page = request.page

    for page in pagelist:

        if '-gwikirevision-' in page:
            metas = get_metas(request,
                              page,
                              metakeys,
                              checkAccess=checkAccess,
                              formatLinks=True)
            page, revision = page.split('-gwikirevision-')
        else:
            metas = get_metas(request,
                              page,
                              metakeys,
                              checkAccess=checkAccess,
                              formatLinks=True)
            revision = ''

        pageobj = Page(request, page)
        request.page = pageobj
        request.formatter.page = pageobj

        row = row + 1

        if row % 2:
            request.write(
                macro.formatter.table_row(1,
                                          {'rowclass': 'metatable-odd-row'}))
        else:
            request.write(
                macro.formatter.table_row(1,
                                          {'rowclass': 'metatable-even-row'}))
        t_cell(macro, [page], head=1, rev=revision)

        for key in metakeys:
            style = styles.get(key, dict())
            t_cell(macro, metas[key], style=style)

        request.write(macro.formatter.table_row(0))

    request.page = tmp_page
    request.formatter.page = tmp_page

    request.write(macro.formatter.table(0))
    request.write(u'</div>')
def construct_table(macro, pagelist, key, sort_order):
    request = macro.request
    request.page.formatter = request.formatter

    count = dict()

    orginalPage = request.page

    for page in pagelist:
        pageobj = Page(request, page)
        request.page = pageobj
        request.formatter.page = pageobj

        # WARNING: Skipping access check because we know that metatable_parseargs
        #          already  checked  them. If you plan to use this code elsewhere
        #          you should make sure that you check for access.
        metas = get_metas(request, page, [key], checkAccess=False)

        for value in metas[key]:
            current = count.get(value, 0)
            count[value] = current + 1

    request.write(macro.formatter.linebreak() + u'<div class="metatable">' +
                  macro.formatter.table(1))
    request.write(macro.formatter.table_row(1, {'rowclass': 'meta_header'}))
    t_cell(macro, key)
    t_cell(macro, "Count")
    request.write(macro.formatter.table_row(0))

    row = 0

    tmp = list()

    for value, count in count.iteritems():
        tmp.append((count, value))

    if sort_order == "value":
        tmp.sort(key=lambda (x, y): y)
    elif sort_order == "count":
        tmp.sort(key=lambda (x, y): x, reverse=True)

    s = sum(map(lambda (x, y): x, tmp))

    tmp.append((s, "Sum"))

    for value, key in tmp:
        row = row + 1

        if row % 2:
            request.write(
                macro.formatter.table_row(1,
                                          {'rowclass': 'metatable-odd-row'}))
        else:
            request.write(
                macro.formatter.table_row(1,
                                          {'rowclass': 'metatable-even-row'}))

        t_cell(macro, key)
        t_cell(macro, u"%d" % value)
        request.write(macro.formatter.table_row(0))

    request.page = orginalPage
    request.formatter.page = orginalPage

    request.write(macro.formatter.table(0))
    request.write(u'</div>')
def draw_topology(request, args, key):
    args = [x.strip() for x in args.split(',')]

    topology, flowfile, color = '', '', ''
    rotate, width = '', ''
    graph = GraphShower(request.page.page_name, request)

    # take flow file specification from arguments as flow=k.csv,
    # otherwise assume that the argument specifies the topology
    for arg in args:
        if '=' in arg:
            key, val = [x.strip() for x in arg.split('=', 1)]
            if key == 'color':
                color = val
            if key == 'flow':
                flowfile = val
            if key == 'rotate':
                rotate = True
            if key == 'width':
                try:
                    width = float(val)
                except ValueError:
                    pass
        else:
            topology = arg

    _ = request.getText

    # Get all containers
    args = 'CategoryContainer, %s=/.+/' % (topology)

    # Note, metatable_parseargs deals with permissions
    pagelist, metakeys, styles = metatable_parseargs(request, args,
                                                     get_all_keys=True)

    if not pagelist:
        return (False, "", render_error("%s: %s" %
                (_("No such topology or empty topology"), topology)))

    coords = dict()
    images = dict()
    aliases = dict()
    areas = dict()
    colors = dict()

    # Make a context to calculate font sizes with
    # There must be a better way to do this, I just don't know it!
    surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, 0, 0)

    ctx = cairo.Context(surface)
    ctx.select_font_face("Times-Roman", cairo.FONT_SLANT_NORMAL,
                         cairo.FONT_WEIGHT_BOLD)
    ctx.set_font_size(12)

    allcoords = list()
    for page in pagelist:
        data = get_metas(request, page,
                         [topology, 'gwikishapefile', 'tia-name', color],
                         checkAccess=False, formatLinks=True)

        crds = [x.split(',') for x in data.get(topology, list)]

        if not crds:
            continue
        crds = [x.strip() for x in crds[0]]
        if not len(crds) == 2:
            continue

        try:
            start_x, start_y = int(crds[0]), int(crds[1])
        except ValueError:
            continue

        coords[page] = start_x, start_y
        allcoords.append((start_x, start_y))

        img = data.get('gwikishapefile', list())
        if color:
            clr = data.get(color, list())
            if clr:
                colors[page] = clr[0]

        alias = data.get('tia-name', list())
        # Newer versions of analyzer do not use aliases anymore
        if not alias:
            alias = [page]

        aliases[page] = alias[0]

        if img:
            # Get attachment name, name of the page it's on, strip
            # link artifacts, find filesys name
            img = img[0].split(':')[1]
            pname = '/'.join(img.split('/')[:-1])
            img = img.split('/')[-1]
            img = img.split('|')[0]
            img = img.rstrip('}').rstrip(']]')
            imgname = AttachFile.getFilename(request, pname, img)
            try:
                images[page] = cairo.ImageSurface.create_from_png(imgname)
                end_x = start_x + images[page].get_width()
                end_y = start_y + images[page].get_height()
            except cairo.Error:
                end_x = start_x
                end_y = start_y
                pass

        text_len = ctx.text_extents(aliases[page])[4]
        text_end = start_x + text_len
        if text_end > end_x:
            end_x = text_end

        # If there was no image or a problem with loading the image
        if page not in images:
            # Lack of image -> black 10x10 rectangle is drawn
            end_x, end_y = start_x + 10, start_y + 10

        allcoords.append((end_x, end_y))

    if flowfile:
        flowcoords = list()
        flowname = AttachFile.getFilename(request, topology, flowfile)
        try:
            flows = csv.reader(file(flowname, 'r').readlines(), delimiter=';')
        except IOError:
            return (False, "", render_error("%s: %s" %
                    (_("No such flowfile as attachment on topology page"),
                     flowfile)))

        flows.next()
        for line in flows:
            if not line:
                continue
            try:
                flowcoords.append((line[0], line[6]))
            except IndexError:
                # Pasted broken lines?
                pass

    max_x = max([x[0] for x in allcoords])
    min_x = min([x[0] for x in allcoords])
    max_y = max([x[1] for x in allcoords])
    min_y = min([x[1] for x in allcoords])

    # Make room for text under pictures
    if rotate:
        surface_y = max_y - min_y
        surface_x = max_x - min_x + 25
    else:
        surface_y = max_y - min_y + 25
        surface_x = max_x - min_x

    try:
        # Get background image, if any
        toponame = AttachFile.getFilename(request, topology, 'shapefile.png')
        background = cairo.ImageSurface.create_from_png(toponame)

        h = background.get_height()
        w = background.get_width()
        diff_x = w - surface_x
        diff_y = h - surface_y

        if diff_x > 0:
            surface_x = w
        else:
            diff_x = 0

        if diff_y > 0:
            surface_y = h
        else:
            diff_y = 0

    except cairo.Error:
        background = None
        diff_x = 0
        diff_y = 0
        pass

    # Setup Cairo
    surface = cairo.ImageSurface(cairo.FORMAT_ARGB32,
                                 int(surface_x), int(surface_y))

    # request.write(repr([surface_x, surface_y]))
    ctx = cairo.Context(surface)
    ctx.select_font_face("Times-Roman", cairo.FONT_SLANT_NORMAL,
                         cairo.FONT_WEIGHT_BOLD)
    ctx.set_font_size(12)

    ctx.set_source_rgb(1.0, 1.0, 1.0)
    ctx.rectangle(0, 0, surface_x, surface_y)
    ctx.fill()

    if background:
        # Center background if not large. Again, I'm just guessing
        # where the background image should be, and trying to mimic
        # analyzer.
        h = background.get_height()
        w = background.get_width()
        start_x, start_y = 0, 0
        if w < surface_x:
            start_x = start_x - min_x - w/2
        if h < surface_y:
            start_y = start_y - min_y - h/2
        ctx.set_source_surface(background, start_x, start_y)
        ctx.rectangle(start_x, start_y, w, h)
        ctx.fill()

    midcoords = dict()
    for page in pagelist:
        if page not in coords:
            continue

        x, y = coords[page]

        # FIXME need more data to align different backgrounds
        # correctly, this is just guessing
        start_x = x - min_x + (diff_x / 2)
        start_y = y - min_y + (diff_y / 3)

        w, h = 10, 10
        if page not in images:
            ctx.set_source_rgb(0, 0, 0)
        else:
            h = images[page].get_height()
            w = images[page].get_width()
            if page in colors:
                clr = graph.hashcolor(colors[page])
                r, g, b = [int(''.join(i), 16) / 255.0 for i in
                           zip(clr[1::2], clr[2::2])]
                ctx.set_source_rgb(r, g, b)
            else:
                ctx.set_source_rgb(1, 1, 1)

        midcoords[page] = (start_x + w / 2, start_y + h / 2)
        ctx.rectangle(start_x, start_y, w, h)
        ctx.fill()

        if page in images:
            ctx.set_source_surface(images[page], start_x, start_y)
            ctx.rectangle(start_x, start_y, w, h)
            ctx.fill()

        text = make_tooltip(request, page)

        areas["%s,%s,%s,%s" % (start_x, start_y, start_x + w, start_y + h)] = \
            [page, text, 'rect']

        if page in aliases:
            ctx.set_source_rgb(0, 0, 0)
            if rotate:
                ctx.move_to(start_x + w + 10, start_y + h)
            else:
                ctx.move_to(start_x, start_y + h + 10)

            # FIXME, should parse links more nicely, now just removes
            # square brackets
            text = aliases[page].lstrip('[').rstrip(']')

            if rotate:
                ctx.rotate(-90.0*math.pi/180.0)

            ctx.show_text(text)

            if rotate:
                ctx.rotate(90.0*math.pi/180.0)

    if flowfile:
        ctx.set_line_width(1)
        ctx.set_source_rgb(0, 0, 0)
        for start, end in flowcoords:
            if (start not in midcoords) or (end not in midcoords):
                continue

            sx, sy = midcoords[start]
            ex, ey = midcoords[end]
            ctx.move_to(sx, sy)
            ctx.line_to(ex, ey)
            ctx.stroke()

    s2 = surface

    if width:
        # For scaling
        new_surface_y = width
        factor = surface_y/new_surface_y
        new_surface_x = surface_x / factor

        # Recalculate image map data
        newareas = dict()
        for coords, data in areas.iteritems():
            corners = [float(i) for i in coords.split(',')]
            corners = tuple(i / factor for i in corners)
            newareas['%s,%s,%s,%s' % corners] = data
        areas = newareas
    else:
        new_surface_y = surface_y
        new_surface_x = surface_x

    if rotate:
        temp = new_surface_x
        new_surface_x = new_surface_y
        new_surface_y = temp
        temp = surface_x
        surface_x = surface_y
        surface_y = temp

    s2 = cairo.ImageSurface(cairo.FORMAT_ARGB32,
                            int(new_surface_x), int(new_surface_y))

    ctx = cairo.Context(s2)

    if rotate:
        ctx.rotate(90.0*math.pi/180.0)

        # Recalculate image map data
        newareas = dict()
        for coords, data in areas.iteritems():
            corners = coords.split(',')
            corners = [float(i) for i in coords.split(',')]
            corners = tuple([new_surface_x - corners[1], corners[0],
                             new_surface_x - corners[3], corners[2]])
            newareas['%s,%s,%s,%s' % corners] = data
        areas = newareas

    if width:
        ctx.scale(new_surface_x/surface_x, new_surface_y/surface_y)

    if rotate:
        ctx.translate(0, -surface_x)

    ctx.set_source_surface(surface, 0, 0)
    ctx.paint()

    data = cairo_surface_to_png(s2)

    map = ''
    for coords in areas:
        name, text, shape = areas[coords]
        pagelink = request.script_root + u'/' + name

        tooltip = "%s\n%s" % (name, text)

        map += u'<area href="%s" shape="%s" coords="%s" title="%s">\n' % \
            (form_escape(pagelink), shape, coords, tooltip)

    return True, data, map
예제 #33
0
def show_editform(wr, request, pagename, args):
    formatter = request.formatter

    # Note that metatable_parseargs handles read permission checks
    pagelist, metakeys, _ = metatable_parseargs(request,
                                                args,
                                                get_all_keys=True)

    uneditable_pages = list()
    # See that the user can write each page
    for page in pagelist:
        if not request.user.may.write(page):
            uneditable_pages.append(page)
    for page in uneditable_pages:
        pagelist.remove(page)

    _ = request.getText

    if uneditable_pages:
        reason = _("No save permission to some pages (%s)" %
                   ','.join(uneditable_pages))
        request.write(render_warning(reason))

    if not pagelist:
        reason = _("No pages to edit.")
        request.write(render_error(reason))
        return

    wr(u'<form method="POST" action="%s" enctype="multipart/form-data">\n',
       actionname(request))
    wr(u'<input type="hidden" name="action" value="%s">\n', action_name)
    wr(formatter.table(1))
    wr(formatter.table_row(1, {'rowclass': 'meta_header'}))
    wr(formatter.table_cell(1, {'class': 'meta_page'}))

    form = values_to_form(request.values)

    template = form.get('template', [''])[0]
    if template:
        wr('<input type="hidden" name="template" value="%s">', template)

    # Filter out uneditables, such as inlinks
    metakeys = editable_p(metakeys)

    _ = request.getText

    for key in metakeys + ['']:
        wr(formatter.table_cell(1, {'class': 'meta_header'}))
        wr(u'<input class="metakey" type="text" name="%s" value="%s">',
           u':: %s' % key, key)
    wr(formatter.table_row(0))

    values = dict()
    valnos = dict()

    for frompage in pagelist:
        values[frompage] = dict()

        for key in metakeys + ['']:
            values[frompage][key] = list()
            # If the page has no values for this key, it'll
            # have one in the table to add a value
            if not valnos.has_key(frompage):
                valnos[frompage] = 1

            keydata = get_metas(request,
                                frompage, [key],
                                abs_attach=False,
                                includeGenerated=False)

            for i, val in enumerate(keydata[key]):
                values[frompage][key].append(val)
                # Enumerate starts from 0: #values++
                # One to add a value: #values++
                if valnos[frompage] < i + 2:
                    valnos[frompage] = i + 2

            values[frompage][key].append('')

    for frompage in pagelist:
        wr(formatter.table_row(1))
        wr(
            formatter.table_cell(1, {
                'class': 'meta_page',
                'rowspan': str(valnos[frompage])
            }))
        wr(u'%s', frompage)

        for i in range(valnos[frompage]):
            # Add <tr>:s for additional values also
            if i > 0:
                wr(formatter.table_row(1))

            for key in metakeys + ['']:
                inputname = frompage + SEPARATOR + key

                if len(values[frompage][key]) >= (i + 1):
                    val = values[frompage][key][i]
                else:
                    val = ''

                # Skip default labels
                if key == 'label' and val == frompage:
                    val = ''

                wr(formatter.table_cell(1, {'class': 'meta_cell'}))
                wr(
                    u'<textarea class="metavalue dynamic"  rows="1" name="%s">%s</textarea>',
                    inputname, val)

                #print frompage, key, inputname, values, '<br>'
            wr(formatter.table_row(0))

        wr(formatter.table_row(1))
        wr(formatter.table_cell(1, {'class': 'meta_cell'}))
        for key in metakeys + ['']:
            inputname = frompage + SEPARATOR + key

            if len(values[frompage][key]) >= (i + 1):
                val = values[frompage][key][i]
            else:
                val = ''

            # Skip default labels
            if key == 'label' and val == frompage:
                val = ''

            wr(formatter.table_cell(1))
            wr(u'<input class="metavalue" type="file" name="%s">\n', inputname)

        wr(formatter.table_row(0))


# Proto JS code to warn on leaving an empty key name
# <script language="JavaScript" type="text/javascript">
#    function myvalid(me) {
#      if (me.form.subject.value == "") {
#        if (confirm("Empty subject, send anyway?"))
#          return true;
#        else
#          return false;
#      }
#      return true;
#    }
# </script>
# <input type="submit" name="send" value="Send" class="button1"tabindex="7"
# onClick="return myvalid(this);" />

    wr(formatter.table(0))
    wr(u'<input type="submit" name="save" value="%s">\n', _('Save'))
    wr(u'<input type="submit" name="cancel" value="%s">\n', _('Cancel'))
    wr(u'</form>\n')
예제 #34
0
def execute(pagename, request):
    pagename_header = '%s-%s.zip' % (pagename, datetime.now().isoformat()[:10])
    pagename_header = pagename_header.encode('ascii', 'ignore')

    request.content_type = 'application/zip'
    request.headers['Content-Disposition'] = \
        'attachment; filename="%s"' % pagename_header

    args = values_to_form(request.values)

    try:
        args = args['args'][0]
    except (KeyError, IndexError):
        args = u''

    pagelist, metakeys, _ = metatable_parseargs(request,
                                                args,
                                                get_all_keys=True)

    renameDict = dict()

    for page in pagelist:
        metas = get_metas(request,
                          page, ["gwikirename"],
                          abs_attach=False,
                          checkAccess=False)
        renameList = metas["gwikirename"]
        if renameList:
            renameDict[page] = renameList

    output = StringIO()
    zip = zipfile.ZipFile(output, "w", zipfile.ZIP_DEFLATED)

    userid = user.getUserIdentification(request)
    script = [
        packLine(['MoinMoinPackage', '1']),
    ]
    counter = 0

    for pagename in pagelist:
        counter += 1
        page = Page(request, pagename)
        timestamp = wikiutil.version2timestamp(page.mtime_usecs())
        # Underlay pages are in epoch 0, zipfile in python 2.7 does
        # not support this.
        if not timestamp:
            pagefile, rev, exists = page.get_rev()
            if rev == 99999999:
                # We should never get here
                log.error("Page %s neither in pages or underlay, skipping." %
                          (pagename))
                continue
            timestamp = os.path.getctime(pagefile)
        pagetext = page.get_raw_body().encode("utf-8")
        filename = str(counter)
        zinfo = zipfile.ZipInfo(
            filename=filename,
            date_time=datetime.fromtimestamp(timestamp).timetuple()[:6])
        zinfo.compress_type = zipfile.ZIP_DEFLATED
        zip.writestr(zinfo, pagetext)

        targetNameList = renameDict.get(pagename, [pagename])
        for targetName in targetNameList:
            script.append(
                packLine(["AddRevision", filename, targetName, userid, ""]))

        for attachment in _get_files(request, pagename):
            counter += 1
            sourcefile = AttachFile.getFilename(request, pagename, attachment)
            filename = str(counter) + "-attachment"
            zip.write(sourcefile, filename)
            script.append(
                packLine([
                    "AddAttachment", filename, attachment, pagename, userid, ""
                ]))

    zip.writestr(MOIN_PACKAGE_FILE, u"\n".join(script).encode("utf-8"))
    zip.close()

    request.write(output.getvalue())
예제 #35
0
def show_editform(wr, request, pagename, args):
    formatter = request.formatter

    # Note that metatable_parseargs handles read permission checks
    pagelist, metakeys, _ = metatable_parseargs(request, args,
                                                get_all_keys=True)

    uneditable_pages = list()
    # See that the user can write each page
    for page in pagelist:
        if not request.user.may.write(page):
            uneditable_pages.append(page)
    for page in uneditable_pages:
        pagelist.remove(page)

    _ = request.getText

    if uneditable_pages:
        reason = _("No save permission to some pages (%s)" %
                   ','.join(uneditable_pages))
        request.write(render_warning(reason))

    if not pagelist:
        reason = _("No pages to edit.")
        request.write(render_error(reason))
        return

    wr(u'<form method="POST" action="%s" enctype="multipart/form-data">\n',
       actionname(request))
    wr(u'<input type="hidden" name="action" value="%s">\n', action_name)
    wr(formatter.table(1))
    wr(formatter.table_row(1, {'rowclass': 'meta_header'}))
    wr(formatter.table_cell(1, {'class': 'meta_page'}))

    form = values_to_form(request.values)

    template = form.get('template', [''])[0]
    if template:
        wr('<input type="hidden" name="template" value="%s">', template)

    # Filter out uneditables, such as inlinks
    metakeys = editable_p(metakeys)

    _ = request.getText

    for key in metakeys + ['']:
        wr(formatter.table_cell(1, {'class': 'meta_header'}))
        wr(u'<input class="metakey" type="text" name="%s" value="%s">',
           u':: %s' % key, key)
    wr(formatter.table_row(0))

    values = dict()
    valnos = dict()

    for frompage in pagelist:
        values[frompage] = dict()

        for key in metakeys + ['']:
            values[frompage][key] = list()
            # If the page has no values for this key, it'll
            # have one in the table to add a value
            if not valnos.has_key(frompage):
                valnos[frompage] = 1

            keydata = get_metas(request, frompage, [key],
                                abs_attach=False, includeGenerated=False)

            for i, val in enumerate(keydata[key]):
                values[frompage][key].append(val)
                # Enumerate starts from 0: #values++
                # One to add a value: #values++
                if valnos[frompage] < i + 2:
                    valnos[frompage] = i + 2

            values[frompage][key].append('')


    for frompage in pagelist:
        wr(formatter.table_row(1))
        wr(formatter.table_cell(1, {'class': 'meta_page',
                                    'rowspan': str(valnos[frompage])}))
        wr(u'%s', frompage)

        for i in range(valnos[frompage]):
            # Add <tr>:s for additional values also
            if i > 0:
                wr(formatter.table_row(1))

            for key in metakeys + ['']:
                inputname = frompage + SEPARATOR + key

                if len(values[frompage][key]) >= (i + 1):
                    val = values[frompage][key][i]
                else:
                    val = ''

                # Skip default labels
                if key == 'label' and val == frompage:
                    val = ''

                wr(formatter.table_cell(1, {'class': 'meta_cell'}))
                wr(u'<textarea class="metavalue dynamic"  rows="1" name="%s">%s</textarea>',
                   inputname, val)

                #print frompage, key, inputname, values, '<br>'
            wr(formatter.table_row(0))

        wr(formatter.table_row(1))
        wr(formatter.table_cell(1, {'class': 'meta_cell'}))
        for key in metakeys + ['']:
            inputname = frompage + SEPARATOR + key

            if len(values[frompage][key]) >= (i + 1):
                val = values[frompage][key][i]
            else:
                val = ''

            # Skip default labels
            if key == 'label' and val == frompage:
                val = ''

            wr(formatter.table_cell(1))
            wr(u'<input class="metavalue" type="file" name="%s">\n', inputname)

        wr(formatter.table_row(0))

# Proto JS code to warn on leaving an empty key name
# <script language="JavaScript" type="text/javascript">
#    function myvalid(me) {
#      if (me.form.subject.value == "") {
#        if (confirm("Empty subject, send anyway?"))
#          return true;
#        else
#          return false;
#      }
#      return true;
#    }
# </script>
# <input type="submit" name="send" value="Send" class="button1"tabindex="7"
# onClick="return myvalid(this);" />

    wr(formatter.table(0))
    wr(u'<input type="submit" name="save" value="%s">\n', _('Save'))
    wr(u'<input type="submit" name="cancel" value="%s">\n', _('Cancel'))
    wr(u'</form>\n')
예제 #36
0
def parse_editform(request, form):
    r"""
    >>> from MoinMoin.metadata.util import doctest_request
    >>> request = doctest_request()

    >>> parse_editform(request, {"Test-gwikiseparator-" : ["1", "2"], ":: " : ["a"]})
    {'Test': ({}, {'a': ['1', '2']})}

    >>> request = doctest_request({"Test" : {"meta" : {"a" : ["x"]}}})
    >>> parse_editform(request, {"Test-gwikiseparator-a" : ["1", "2"], ":: a" : ["a"]})
    {'Test': ({'a': ['x']}, {'a': ['1', '2']})}

    >>> request = doctest_request({"Test" : {"meta" : {"a" : ["x"]}}})
    >>> parse_editform(request, {"Test-gwikiseparator-a" : ["x"], ":: a" : [""]})
    {'Test': ({'a': ['x']}, {'a': ['']})}

    >>> request = doctest_request({"Test" : {"meta" : {"a" : ["1", "2"]}}})
    >>> parse_editform(request, {"Test-gwikiseparator-a" : ["1"], ":: a" : ["a"]})
    {'Test': ({'a': ['1', '2']}, {'a': ['1', '']})}
    """
    _ = request.getText

    msgs = list()
    keys = dict()
    pages = dict()
    files = dict()

    for key in request.files:
        f = request.files[key]
        if not f.filename:
            continue

        fileobj = f.stream

        page, key = key.split(SEPARATOR, 1)
        files.setdefault(page, dict())[key] = (f.filename, fileobj)

    # Key changes
    for oldKey, newKeys in form.iteritems():

        if not newKeys or not oldKey.startswith(':: '):
            continue

        newKey = newKeys[0].strip()
        oldKey = oldKey[3:].strip()
        if oldKey == newKey:
            continue

        keys[oldKey] = newKey

    # Value changes
    for pageAndKey, newValues in form.iteritems():
        if pageAndKey.endswith("__filename__"):
            continue

        # At least the key 'save' may be there and should be ignored
        if not SEPARATOR in pageAndKey:
            continue

        # Form keys not autodecoded from utf-8
        page, oldKey = pageAndKey.split(SEPARATOR, 1)

        # Decoding pagename
        page = url_unquote(page)
        newKey = keys.get(oldKey, oldKey)

        if not request.user.may.write(page):
            err = '%s: ' % page + _('You are not allowed to edit this page.')
            if not err in msgs:
                msgs.append(err)
            continue

        oldMeta, newMeta = pages.setdefault(page, (dict(), dict()))

        if oldKey:
            oldMetas = get_metas(request, page, [oldKey],
                                 abs_attach=False, includeGenerated=False)
            oldValues = oldMetas[oldKey]

            oldMeta.setdefault(oldKey, list()).extend(oldValues)

            if newKey != oldKey:
                # Remove the corresponding values
                newMeta.setdefault(oldKey, list()).extend([""] * len(oldValues))

        if newKey:
            missing = 0
            if oldKey:
                missing = len(oldValues) - len(newValues)

            newMeta.setdefault(newKey, list()).extend(newValues)
            newMeta.setdefault(newKey, list()).extend([""] * missing)

    # Prune
    for page, (oldMeta, newMeta) in list(pages.iteritems()):
        for key in list(newMeta):
            if key not in oldMeta:
                continue
            if oldMeta[key] != newMeta[key]:
                continue
            del oldMeta[key]
            del newMeta[key]

        if not (oldMeta or newMeta):
            del pages[page]

    for page in files:
        metas = pages.get(page, (dict(), dict()))[1]
        for key in files[page]:
            filename, descriptor = files[page][key]
            values = metas.get(key, list())
            try:
                index = values.index(descriptor)
                values[index] = "[[attachment:%s]]" % filename
            except ValueError:
                values.append("[[attachment:%s]]" % filename)

    return pages, msgs, files
예제 #37
0
def construct_table(macro,
                    pagelist,
                    metakeys,
                    legend='',
                    checkAccess=True,
                    styles=dict(),
                    addpagename=False):
    request = macro.request
    request.page.formatter = request.formatter
    out = str()

    row = 0

    entryfmt = {'class': 'metamatrix_entry'}

    # Start table
    out += macro.formatter.linebreak() + u'<div class="metamatrix">' + \
        macro.formatter.table(1)

    # Give a class to headers to make it customisable
    out += macro.formatter.table_row(1, {'rowclass': 'meta_head'})
    # Upper left cell is empty or has the desired legend
    out += t_cell(macro, [legend])

    x_key, y_key = metakeys[:2]

    x_values, y_values = set(), set()

    page_vals = dict()

    for page in pagelist:
        page_vals[page] = get_metas(request,
                                    page,
                                    metakeys,
                                    checkAccess=False,
                                    formatLinks=True)

        x_val = page_vals[page].get(x_key, set())
        y_val = page_vals[page].get(y_key, set())
        x_values.update([(page, x) for x in x_val])
        y_values.update([(page, y) for y in y_val])

    metakeys = metakeys[2:]

    header_cells = list()
    # Make header row
    for oval, value, page in sorted(
        (ordervalue(y), y, page) for page, y in y_values):

        style = styles.get(y_key, dict())

        # Styles can modify key naming
        name = style.get('gwikiname', '').strip('"')

        # We don't want stuff like bullet lists in out header
        headerstyle = dict()
        for st in style:
            if not st.startswith('gwiki'):
                headerstyle[st] = style[st]

        if name:
            if not (value, name) in header_cells:
                header_cells.append((value, name))
        else:
            showvalue = metas_to_abs_links(request, page, [value])
            if not (value, showvalue[0]) in header_cells:
                header_cells.append((value, showvalue[0]))

    for value, showvalue in header_cells:
        out += t_cell(macro, [showvalue], style=headerstyle)

    out += macro.formatter.table_row(0)

    tmp_page = request.page

    f = macro.formatter

    # Table
    row_cells = list()
    row_values = list()
    for oval, x_value, page in sorted(
        (ordervalue(x), x, page) for page, x in x_values):
        if not (oval, x_value) in row_values:
            row_cells.append((oval, x_value, page))
            row_values.append((oval, x_value))

    for oval, x_value, page in row_cells:
        row = row + 1

        if row % 2:
            out += f.table_row(1, {'rowclass': 'metamatrix-odd-row'})
        else:
            out += f.table_row(1, {'rowclass': 'metamatrix-even-row'})
        value = metas_to_abs_links(request, page, [x_value])
        out += t_cell(macro, value)

        for y_value, showvalue in header_cells:
            style = styles.get(y_value, dict())

            if not 'class' in style:
                style['class'] = 'meta_cell'

            out += f.table_cell(1, attrs=style)

            for page in pagelist:
                pageobj = Page(request, page)

                if (x_value in page_vals[page].get(x_key, set())
                        and y_value in page_vals[page].get(y_key, set())):

                    result = ''

                    args = {'class': 'metamatrix_link'}

                    for key in metakeys:
                        for val in page_vals[page].get(key, list()):

                            # Strip ugly brackets from bracketed links
                            val = val.lstrip('[').strip(']')

                            result += f.listitem(1, **entryfmt)

                            result += pageobj.link_to(request,
                                                      text=val,
                                                      **args)
                            result += f.listitem(0)

                    if addpagename:
                        result += f.listitem(1, **entryfmt)
                        result += pageobj.link_to(request, **args)
                        result += f.listitem(0)

                    out += result

        out += macro.formatter.table_row(0)

    request.page = tmp_page
    request.formatter.page = tmp_page

    out += macro.formatter.table(0)
    out += u'</div>'

    return out