changeset 753:72f6a200ed88 pytest2

merged with default
author pkumar <contactprashantat@gmail.com>
date Mon, 22 Aug 2011 19:46:03 +0530
parents 0ea1cde488dd (current diff) f21d81b793e3 (diff)
children 149ddb56416e
files MoinMoin/apps/frontend/_tests/test_frontend.py MoinMoin/items/_tests/test_Item.py MoinMoin/templates/global_index.html MoinMoin/templates/index2.html setup.py
diffstat 44 files changed, 1241 insertions(+), 304 deletions(-) [+]
line wrap: on
line diff
--- a/MoinMoin/_tests/wikiconfig.py	Mon Aug 22 15:41:27 2011 +0530
+++ b/MoinMoin/_tests/wikiconfig.py	Mon Aug 22 19:46:03 2011 +0530
@@ -24,5 +24,7 @@
     _test_items_xml = join(_here, 'testitems.xml')
     content_acl = None
     item_root = 'FrontPage'
+    interwikiname = u'MoinTest'
     interwiki_map = dict(Self='http://localhost:8080/', MoinMoin='http://moinmo.in/')
+    interwiki_map[interwikiname] = 'http://localhost:8080/'
 
--- a/MoinMoin/apps/frontend/_tests/test_frontend.py	Mon Aug 22 15:41:27 2011 +0530
+++ b/MoinMoin/apps/frontend/_tests/test_frontend.py	Mon Aug 22 19:46:03 2011 +0530
@@ -32,7 +32,7 @@
         with self.app.test_client() as c:
             rv = c.get('/favicon.ico')
             assert rv.status == '200 OK'
-            assert rv.headers['Content-Type'] == 'image/x-icon'
+            assert rv.headers['Content-Type'] in ['image/x-icon', 'image/vnd.microsoft.icon']
             assert rv.data.startswith('\x00\x00') # "reserved word, should always be 0"
 
     def test_404(self):
@@ -45,7 +45,7 @@
 
     def test_global_index(self):
         with self.app.test_client() as c:
-            rv = c.get('/+index')
+            rv = c.get('/+index/')
             assert rv.status == '200 OK'
             assert rv.headers['Content-Type'] == 'text/html; charset=utf-8'
             assert '<html>' in rv.data
--- a/MoinMoin/apps/frontend/views.py	Mon Aug 22 15:41:27 2011 +0530
+++ b/MoinMoin/apps/frontend/views.py	Mon Aug 22 19:46:03 2011 +0530
@@ -1,4 +1,5 @@
 # Copyright: 2003-2010 MoinMoin:ThomasWaldmann
+# Copyright: 2011 MoinMoin:AkashSinha
 # Copyright: 2008 MoinMoin:FlorianKrupicka
 # Copyright: 2010 MoinMoin:DiogenesAugusto
 # Copyright: 2001 Richard Jones <richard@bizarsoftware.com.au>
@@ -15,15 +16,22 @@
 import re
 import difflib
 import time
+from datetime import datetime
 from itertools import chain
+from collections import namedtuple, OrderedDict
+try:
+    import json
+except ImportError:
+    import simplejson as json
 
 from flask import request, url_for, flash, Response, redirect, session, abort, jsonify
 from flask import current_app as app
 from flask import g as flaskg
+from flaskext.babel import format_date
 from flaskext.themes import get_themes_list
 
 from flatland import Form, String, Integer, Boolean, Enum
-from flatland.validation import Validator, Present, IsEmail, ValueBetween, URLValidator, Converted
+from flatland.validation import Validator, Present, IsEmail, ValueBetween, URLValidator, Converted, ValueAtLeast
 
 from jinja2 import Markup
 
@@ -34,12 +42,12 @@
 logging = log.getLogger(__name__)
 
 from MoinMoin.i18n import _, L_, N_
-from MoinMoin.themes import render_template
+from MoinMoin.themes import render_template, get_editor_info, contenttype_to_class
 from MoinMoin.apps.frontend import frontend
 from MoinMoin.items import Item, NonExistent
 from MoinMoin.items import ROWS_META, COLS, ROWS_DATA
-from MoinMoin import config, user, wikiutil
-from MoinMoin.config import CONTENTTYPE, ITEMLINKS, ITEMTRANSCLUSIONS
+from MoinMoin import config, user, util, wikiutil
+from MoinMoin.config import ACTION, COMMENT, CONTENTTYPE, ITEMLINKS, ITEMTRANSCLUSIONS, NAME, CONTENTTYPE_GROUPS
 from MoinMoin.util import crypto
 from MoinMoin.util.interwiki import url_for_item
 from MoinMoin.security.textcha import TextCha, TextChaizedForm, TextChaValid
@@ -73,11 +81,13 @@
 Disallow: /+modify/
 Disallow: /+copy/
 Disallow: /+delete/
+Disallow: /+ajaxdelete/
+Disallow: /+ajaxdestroy/
+Disallow: /+ajaxmodify/
 Disallow: /+destroy/
 Disallow: /+rename/
 Disallow: /+revert/
 Disallow: /+index/
-Disallow: /+index2/
 Disallow: /+jfu-server/
 Disallow: /+sitemap/
 Disallow: /+similar_names/
@@ -152,6 +162,7 @@
                               )
 
 
+
 @frontend.route('/<itemname:item_name>', defaults=dict(rev=-1), methods=['GET', 'POST'])
 @frontend.route('/+show/<int:rev>/<itemname:item_name>', methods=['GET', 'POST'])
 def show_item(item_name, rev):
@@ -284,9 +295,10 @@
 def download_item(item_name, rev):
     try:
         item = Item.create(item_name, rev_no=rev)
+        mimetype = request.values.get("mimetype")
     except AccessDeniedError:
         abort(403)
-    return item.do_get(force_attachment=True)
+    return item.do_get(force_attachment=True, mimetype=mimetype)
 
 @frontend.route('/+convert/<itemname:item_name>')
 def convert_item(item_name):
@@ -356,6 +368,17 @@
 class RenameItemForm(TargetCommentForm):
     name = 'rename_item'
 
+class ContenttypeFilterForm(Form):
+    name = 'contenttype_filter'
+    markup_text_items = Boolean.using(label=L_('markup text'), optional=True, default=1)
+    other_text_items = Boolean.using(label=L_('other text'), optional=True, default=1)
+    image_items = Boolean.using(label=L_('image'), optional=True, default=1)
+    audio_items = Boolean.using(label=L_('audio'), optional=True, default=1)
+    video_items = Boolean.using(label=L_('video'), optional=True, default=1)
+    other_items = Boolean.using(label=L_('other'), optional=True, default=1)
+    unknown_items = Boolean.using(label=L_('unknown'), optional=True, default=1)
+    submit = String.using(default=L_('Filter'), optional=True)
+
 
 @frontend.route('/+revert/<int:rev>/<itemname:item_name>', methods=['GET', 'POST'])
 def revert_item(item_name, rev):
@@ -448,6 +471,68 @@
                            form=form,
                           )
 
+@frontend.route('/+ajaxdelete/<itemname:item_name>', methods=['POST'])
+@frontend.route('/+ajaxdelete', defaults=dict(item_name=''), methods=['POST'])
+def ajaxdelete(item_name):
+    if request.method == 'POST':
+        args = request.values.to_dict()
+        comment = args.get("comment")
+        itemnames = args.get("itemnames")
+        itemnames = json.loads(itemnames)
+        if item_name:
+            subitem_prefix = item_name + u'/'
+        else:
+            subitem_prefix = u''
+        response = {"itemnames": [], "status": []}
+        for itemname in itemnames:
+            response["itemnames"].append(itemname)
+            itemname = subitem_prefix + itemname
+            try:
+                item = Item.create(itemname)
+                item.delete(comment)
+                response["status"].append(True)
+            except AccessDeniedError:
+                response["status"].append(False)
+
+    return jsonify(response)
+
+@frontend.route('/+ajaxdestroy/<itemname:item_name>', methods=['POST'])
+@frontend.route('/+ajaxdestroy', defaults=dict(item_name=''), methods=['POST'])
+def ajaxdestroy(item_name):
+    if request.method == 'POST':
+        args = request.values.to_dict()
+        comment = args.get("comment")
+        itemnames = args.get("itemnames")
+        itemnames = json.loads(itemnames)
+        if item_name:
+            subitem_prefix = item_name + u'/'
+        else:
+            subitem_prefix = u''
+        response = {"itemnames": [], "status": []}
+        for itemname in itemnames:
+            response["itemnames"].append(itemname)
+            itemname = subitem_prefix + itemname
+            try:
+                item = Item.create(itemname)
+                item.destroy(comment=comment, destroy_item=True)
+                response["status"].append(True)
+            except AccessDeniedError:
+                response["status"].append(False)
+
+    return jsonify(response)
+
+
+@frontend.route('/+ajaxmodify/<itemname:item_name>', methods=['POST'])
+@frontend.route('/+ajaxmodify', methods=['POST'], defaults=dict(item_name=''))
+def ajaxmodify(item_name):
+    newitem = request.values.get("newitem")
+    if not newitem:
+        abort(404)
+    if item_name:
+        newitem = item_name + u'/' + newitem
+
+    return redirect(url_for('.modify_item', item_name=newitem))
+
 
 @frontend.route('/+destroy/<int:rev>/<itemname:item_name>', methods=['GET', 'POST'])
 @frontend.route('/+destroy/<itemname:item_name>', methods=['GET', 'POST'], defaults=dict(rev=None))
@@ -480,69 +565,76 @@
                           )
 
 
-# XXX this has some functional redundancy with "index", solve that later
-@frontend.route('/+index2/<itemname:item_name>', methods=['GET'])
-def index2(item_name):
-    # flat index using jquery-file-upload (see also jfu_server)
-    return render_template('index2.html',
-                           item_name=item_name,
-                          )
-
-@frontend.route('/+jfu-server/<itemname:item_name>', methods=['GET', 'POST'])
+@frontend.route('/+jfu-server/<itemname:item_name>', methods=['POST'])
+@frontend.route('/+jfu-server', defaults=dict(item_name=''), methods=['POST'])
 def jfu_server(item_name):
     """jquery-file-upload server component
     """
-    if request.method == 'GET':
-        try:
-            item = Item.create(item_name)
-        except AccessDeniedError:
-            abort(403)
-        files = []
-        for full_name, rel_name, mimetype in item.flat_index():
-            url = url_for_item(full_name)
-            url_download = url_for_item(full_name, endpoint='frontend.download_item')
-            files.append(dict(name=rel_name, url=url, url_download=url_download, size=0))
-        return jsonify(files=files)
-    if request.method == 'POST':
-        data_file = request.files.get('data_file')
-        subitem_name = data_file.filename
-        item_name = item_name + u'/' + subitem_name
-        try:
-            item = Item.create(item_name)
-            revno, size = item.modify()
-            item_modified.send(app._get_current_object(),
-                               item_name=item_name)
-            return jsonify(name=subitem_name,
-                           size=size,
-                           url=url_for_item(item_name, rev=revno),
-                           url_download=url_for_item(item_name, rev=revno, endpoint='frontend.download_item'),
-                          )
-        except AccessDeniedError:
-            abort(403)
+    data_file = request.files.get('data_file')
+    subitem_name = data_file.filename
+    contenttype = data_file.content_type # guess by browser, based on file name
+    if item_name:
+        subitem_prefix = item_name + u'/'
+    else:
+        subitem_prefix = u''
+    item_name = subitem_prefix + subitem_name
+    try:
+        item = Item.create(item_name)
+        revno, size = item.modify()
+        item_modified.send(app._get_current_object(),
+                           item_name=item_name)
+        return jsonify(name=subitem_name,
+                       size=size,
+                       url=url_for('.show_item', item_name=item_name, rev=revno),
+                       contenttype=contenttype_to_class(contenttype),
+                      )
+    except AccessDeniedError:
+        abort(403)
 
 
-
-@frontend.route('/+index/<itemname:item_name>')
+@frontend.route('/+index/', defaults=dict(item_name=''), methods=['GET', 'POST'])
+@frontend.route('/+index/<itemname:item_name>', methods=['GET', 'POST'])
 def index(item_name):
     try:
-        item = Item.create(item_name)
+        item = Item.create(item_name) # when item_name='', it gives toplevel index
     except AccessDeniedError:
         abort(403)
-    index = item.flat_index()
-    return render_template(item.index_template,
-                           item=item, item_name=item_name,
-                           index=index,
-                          )
-
 
-@frontend.route('/+index')
-def global_index():
-    item = Item.create('') # XXX hack: item_name='' gives toplevel index
-    index = item.flat_index()
-    item_name = request.values.get('item_name', '') # actions menu puts it into qs
-    return render_template('global_index.html',
-                           item_name=item_name, # XXX no item
-                           index=index,
+    if request.method == 'GET':
+        form = ContenttypeFilterForm.from_defaults()
+        selected_groups = None
+    elif request.method == "POST":
+        form = ContenttypeFilterForm.from_flat(request.form)
+        selected_groups = [gname.replace("_", " ") for gname, value in form.iteritems()
+                           if form[gname].value]
+        if u'submit' in selected_groups:
+            selected_groups.remove(u'submit')
+        if not selected_groups:
+            form = ContenttypeFilterForm.from_defaults()
+
+    startswith = request.values.get("startswith")
+    index = item.flat_index(startswith, selected_groups)
+
+    ct_groups = [(gname, ", ".join([ctlabel for ctname, ctlabel in contenttypes]))
+                 for gname, contenttypes in CONTENTTYPE_GROUPS]
+    ct_groups = dict(ct_groups)
+
+    initials = item.name_initial(item.flat_index())
+    initials = [initial.upper() for initial in initials]
+    initials = list(set(initials))
+    initials = sorted(initials)
+    detailed_index = item.get_detailed_index(index)
+    detailed_index = sorted(detailed_index, key=lambda name: name[0].lower())
+
+    item_names = item_name.split(u'/')
+    return render_template(item.index_template,
+                           item_name=item_name,
+                           item_names=item_names,
+                           index=detailed_index,
+                           initials=initials,
+                           startswith=startswith,
+                           contenttype_groups=ct_groups,
+                           form=form,
                           )
 
 
@@ -592,19 +684,159 @@
 @frontend.route('/+history/<itemname:item_name>')
 def history(item_name):
     history = flaskg.storage.history(item_name=item_name)
+
+    offset = request.values.get('offset', 0)
+    offset = max(int(offset), 0)
+
+    results_per_page = int(app.cfg.results_per_page)
+    if flaskg.user.valid:
+        results_per_page = flaskg.user.results_per_page
+    history_page = util.getPageContent(history, offset, results_per_page)
+
     return render_template('history.html',
                            item_name=item_name, # XXX no item here
-                           history=history,
+                           history_page=history_page,
                           )
 
-
 @frontend.route('/+history')
 def global_history():
     history = flaskg.storage.history(item_name='')
+    results_per_page = int(app.cfg.results_per_page)
+    if flaskg.user.valid:
+        bookmark_time = flaskg.user.getBookmark()
+        results_per_page = flaskg.user.results_per_page # if it is 0, means no paging
+    else:
+        bookmark_time = None
+    item_groups = OrderedDict()
+    for rev in history:
+        current_item_name = rev.item.name
+        if bookmark_time and rev.timestamp <= bookmark_time:
+            break
+        elif current_item_name in item_groups:
+            latest_rev = item_groups[current_item_name][0]
+            tm_latest = datetime.utcfromtimestamp(latest_rev.timestamp)
+            tm_current = datetime.utcfromtimestamp(rev.timestamp)
+            if format_date(tm_latest) == format_date(tm_current): # this change took place on the same day
+                item_groups[current_item_name].append(rev)
+        else:
+            item_groups[current_item_name] = [rev]
+
+    # Got the item dict, now doing grouping inside them
+    editor_info = namedtuple('editor_info', ['editor', 'editor_revnos'])
+    for item_name, revs in item_groups.items():
+        item_info = {}
+        editors_info = OrderedDict()
+        editors = []
+        revnos = []
+        comments = []
+        current_rev = revs[0]
+        item_info["item_name"] = item_name
+        item_info["timestamp"] = current_rev.timestamp
+        item_info["contenttype"] = current_rev.get(CONTENTTYPE)
+        item_info["action"] = current_rev.get(ACTION)
+        item_info["name"] = current_rev.get(NAME)
+
+        # Aggregating comments, authors and revno
+        for rev in revs:
+            revnos.append(rev.revno)
+            comment = rev.get(COMMENT)
+            if comment:
+                comment = "#%(revno)d %(comment)s" % {
+                          'revno': rev.revno,
+                          'comment': comment
+                          }
+                comments.append(comment)
+            editor = get_editor_info(rev)
+            editor_name = editor["name"]
+            if editor_name in editors_info:
+                editors_info[editor_name].editor_revnos.append(rev.revno)
+            else:
+                editors_info[editor_name] = editor_info(editor, [rev.revno])
+
+        if len(revnos) == 1:
+            # there is only one change for this item in the history considered
+            info, positions = editors_info[editor_name]
+            info_tuple = (info, "")
+            editors.append(info_tuple)
+        else:
+            # grouping the revision numbers into a range, which belong to a particular editor(user) for the current item
+            for info, positions in editors_info.values():
+                position_range = util.rangelist(positions)
+                position_range = "[%(position_range)s]" % {'position_range': position_range}
+                info_tuple = (info, position_range)
+                editors.append(info_tuple)
+
+        item_info["revnos"] = revnos
+        item_info["editors"] = editors
+        item_info["comments"] = comments
+        item_groups[item_name] = item_info
+
+    # Grouping on the date basis
+    offset = request.values.get('offset', 0)
+    offset = max(int(offset), 0)
+    day_count = OrderedDict()
+    revcount = 0
+    maxrev = results_per_page + offset
+    toappend = True
+    grouped_history = []
+    prev_date = '0000-00-00'
+    rev_tuple = namedtuple('rev_tuple', ['rev_date', 'item_revs'])
+    rev_tuples = rev_tuple(prev_date, [])
+    for item_group in item_groups.values():
+        tm = datetime.utcfromtimestamp(item_group["timestamp"])
+        rev_date = format_date(tm)
+        if revcount < offset:
+            revcount += len(item_group["revnos"])
+            if rev_date not in day_count:
+                day_count[rev_date] = 0
+            day_count[rev_date] += len(item_group["revnos"])
+        elif rev_date == prev_date:
+            rev_tuples.item_revs.append(item_group)
+            revcount += len(item_group["revnos"])
+        else:
+            grouped_history.append(rev_tuples)
+            if results_per_page and revcount >= maxrev:
+                toappend = False
+                break
+            else:
+                rev_tuples = rev_tuple(rev_date, [item_group])
+                prev_date = rev_date
+                revcount += len(item_group["revnos"])
+
+    if toappend:
+        grouped_history.append(rev_tuples)
+        revcount = 0 # this is the last page, no next page present
+    del grouped_history[0]  # First tuple will be a null one
+
+    # calculate offset for previous page link
+    if results_per_page:
+        previous_offset = 0
+        prev_rev_count = day_count.values()
+        prev_rev_count.reverse()
+        for numrev in prev_rev_count:
+            if previous_offset < results_per_page:
+                previous_offset += numrev
+            else:
+                break
+
+        if offset - previous_offset >= results_per_page:
+            previous_offset = offset - previous_offset
+        elif previous_offset:
+            previous_offset = 0
+        else:
+            previous_offset = -1
+    else:
+        previous_offset = -1 # no previous page
+
     item_name = request.values.get('item_name', '') # actions menu puts it into qs
+    current_timestamp = int(time.time())
     return render_template('global_history.html',
                            item_name=item_name, # XXX no item
-                           history=history,
+                           history=grouped_history,
+                           current_timestamp=current_timestamp,
+                           bookmark_time=bookmark_time,
+                           offset=revcount,
+                           previous_offset=previous_offset,
                           )
 
 @frontend.route('/+wanteds')
@@ -1155,6 +1387,7 @@
         theme_name = Enum.using(label=L_('Theme name')).with_properties(labels=dict(themes_available)).valued(*themes_keys)
         css_url = String.using(label=L_('User CSS URL'), optional=True).with_properties(placeholder=L_("Give the URL of your custom CSS (optional)")).validated_by(URLValidator())
         edit_rows = Integer.using(label=L_('Editor size')).with_properties(placeholder=L_("Editor textarea height (0=auto)")).validated_by(Converted())
+        results_per_page = Integer.using(label=L_('History results per page')).with_properties(placeholder=L_("Number of results per page (0=no paging)")).validated_by(ValueAtLeast(0))
         submit = String.using(default=L_('Save'), optional=True)
 
     dispatch = dict(
@@ -1239,7 +1472,6 @@
         flash(_("You must log in to use bookmarks."), "error")
     return redirect(url_for('.global_history'))
 
-
 @frontend.route('/+diffraw/<path:item_name>')
 def diffraw(item_name):
     # TODO get_item and get_revision calls may raise an AccessDeniedError.
--- a/MoinMoin/config/__init__.py	Mon Aug 22 15:41:27 2011 +0530
+++ b/MoinMoin/config/__init__.py	Mon Aug 22 19:46:03 2011 +0530
@@ -116,3 +116,50 @@
 # some backends may use this also for other purposes.
 HASH_ALGORITHM = 'sha1'
 
+# structure for contenttype groups
+CONTENTTYPE_GROUPS = [
+    ('markup text items', [
+        ('text/x.moin.wiki;charset=utf-8', 'Wiki (MoinMoin)'),
+        ('text/x.moin.creole;charset=utf-8', 'Wiki (Creole)'),
+        ('text/x-mediawiki;charset=utf-8', 'Wiki (MediaWiki)'),
+        ('text/x-rst;charset=utf-8', 'ReST'),
+        ('application/docbook+xml;charset=utf-8', 'DocBook'),
+        ('text/html;charset=utf-8', 'HTML'),
+    ]),
+    ('other text items', [
+        ('text/plain;charset=utf-8', 'plain text'),
+        ('text/x-diff;charset=utf-8', 'diff/patch'),
+        ('text/x-python;charset=utf-8', 'python code'),
+        ('text/csv;charset=utf-8', 'csv'),
+        ('text/x-irclog;charset=utf-8', 'IRC log'),
+    ]),
+    ('image items', [
+        ('image/jpeg', 'JPEG'),
+        ('image/png', 'PNG'),
+        ('image/svg+xml', 'SVG'),
+    ]),
+    ('audio items', [
+        ('audio/wave', 'WAV'),
+        ('audio/ogg', 'OGG'),
+        ('audio/mpeg', 'MP3'),
+        ('audio/webm', 'WebM'),
+    ]),
+    ('video items', [
+        ('video/ogg', 'OGG'),
+        ('video/webm', 'WebM'),
+        ('video/mp4', 'MP4'),
+    ]),
+    ('drawing items', [
+        ('application/x-twikidraw', 'TDRAW'),
+        ('application/x-anywikidraw', 'ADRAW'),
+        ('application/x-svgdraw', 'SVGDRAW'),
+    ]),
+    ('other items', [
+        ('application/pdf', 'PDF'),
+        ('application/zip', 'ZIP'),
+        ('application/x-tar', 'TAR'),
+        ('application/x-gtar', 'TGZ'),
+        ('application/octet-stream', 'binary file'),
+    ]),
+]
+
--- a/MoinMoin/config/default.py	Mon Aug 22 15:41:27 2011 +0530
+++ b/MoinMoin/config/default.py	Mon Aug 22 19:46:03 2011 +0530
@@ -3,6 +3,7 @@
 # Copyright: 2005-2011 MoinMoin:ThomasWaldmann
 # Copyright: 2008      MoinMoin:JohannesBerg
 # Copyright: 2010      MoinMoin:DiogenesAugusto
+# Copyright: 2011      MoinMoin:AkashSinha
 # License: GNU GPL v2 (or any later version), see LICENSE.txt for details.
 
 """
@@ -118,6 +119,9 @@
         if self.secrets is None:  # admin did not setup a real secret
             raise error.ConfigurationError("No secret configured! You need to set secrets = 'somelongsecretstring' in your wiki config.")
 
+        if self.interwikiname is None:  # admin did not setup a real interwikiname
+            raise error.ConfigurationError("No interwikiname configured! You need to set interwikiname = u'YourUniqueStableInterwikiName' in your wiki config.")
+
         secret_key_names = ['security/ticket', ]
         if self.textchas:
             secret_key_names.append('security/textcha')
@@ -321,12 +325,12 @@
   (
     ('sitename', u'Untitled Wiki',
      "Short description of your wiki site, displayed below the logo on each page, and used in RSS documents as the channel title [Unicode]"),
-    ('interwikiname', None, "unique and stable InterWiki name (prefix, moniker) of the site [Unicode], or None"),
+    ('interwikiname', None, "unique, stable and required InterWiki name (prefix, moniker) of the site [Unicode]"),
     ('html_pagetitle', None, "Allows you to set a specific HTML page title (if None, it defaults to the value of `sitename`) [Unicode]"),
     ('navi_bar', [
         ('wikilink', 'frontend.show_root', dict(), L_('Home'), L_('Home Page')),
         ('wikilink', 'frontend.global_history', dict(), L_('History'), L_('Global History')),
-        ('wikilink', 'frontend.global_index', dict(), L_('Index'), L_('Global Index')),
+        ('wikilink', 'frontend.index', dict(), L_('Index'), L_('Global Index')),
         ('wikilink', 'frontend.global_tags', dict(), L_('Tags'), L_('Global Tags Index')),
         ('wikilink', 'admin.index', dict(), L_('More'), L_('Administration & Docs')),
      ],
@@ -359,7 +363,6 @@
         ('frontend.modify_item', L_('Modify'), L_('Edit or Upload'), True, ),
         ('special.supplementation', None, None, False, ),
         ('frontend.index', L_('Index'), L_('List sub-items'), False, ),
-        ('frontend.index2', L_('Index'), L_('List sub-items'), False, ),
         ('special.comments', L_('Comments'), L_('Switch showing comments on or off'), True, ),
         ('frontend.highlight_item', L_('Highlight'), L_('Show with Syntax-Highlighting'), True, ),
         ('frontend.show_item_meta', L_('Meta'), L_('Display Metadata'), True, ),
@@ -394,6 +397,10 @@
     ('edit_ticketing', True, None),
   )),
   # ==========================================================================
+  'paging': ('Paging related', None, (
+    ('results_per_page', 50, "Number of results to be shown on a single page in pagination"),
+  )),
+  # ==========================================================================
   'data': ('Data storage', None, (
     ('data_dir', './data/', "Path to the data directory."),
     ('plugin_dirs', [], "Plugin directories."),
@@ -446,6 +453,7 @@
         ],
         theme_name=None, # None -> use cfg.theme_default
         edit_rows=0,
+        results_per_page=0,
         locale=None, # None -> do browser language detection, otherwise just use this locale
         timezone=None, # None -> use cfg.timezone_default
       ),
--- a/MoinMoin/items/__init__.py	Mon Aug 22 15:41:27 2011 +0530
+++ b/MoinMoin/items/__init__.py	Mon Aug 22 19:46:03 2011 +0530
@@ -19,6 +19,7 @@
 import tarfile
 import zipfile
 import tempfile
+import itertools
 from StringIO import StringIO
 from array import array
 
@@ -68,7 +69,7 @@
                             IS_SYSITEM, SYSITEM_VERSION,  USERGROUP, SOMEDICT, \
                             CONTENTTYPE, SIZE, LANGUAGE, ITEMLINKS, ITEMTRANSCLUSIONS, \
                             TAGS, ACTION, ADDRESS, HOSTNAME, USERID, EXTRA, COMMENT, \
-                            HASH_ALGORITHM
+                            HASH_ALGORITHM, CONTENTTYPE_GROUPS
 
 COLS = 80
 ROWS_DATA = 20
@@ -571,65 +572,91 @@
                  for item in item_iterator]
         return sorted(items)
 
-    def flat_index(self):
+    def flat_index(self, startswith=None, selected_groups=None):
+        """
+        creates an top level index of sub items of this item
+        if startswith is set, filtering is done on the basis of starting letter of item name
+        if selected_groups is set, items whose contentype belonging to the selected contenttype_groups, are filtered.
+        """
         index = self.get_index()
-        index = [(fullname, relname, contenttype)
-                 for fullname, relname, contenttype in index
-                 if u'/' not in relname]
+
+        all_ctypes = [[ctype for ctype, clabel in contenttypes]
+                      for gname, contenttypes in CONTENTTYPE_GROUPS]
+        all_ctypes_chain = itertools.chain(*all_ctypes)
+        all_contenttypes = list(all_ctypes_chain)
+        contenttypes_without_encoding = [contenttype[:contenttype.index(u';')]
+                                         for contenttype in all_contenttypes
+                                         if u';' in contenttype]
+        all_contenttypes.extend(contenttypes_without_encoding) # adding more mime-types without the encoding term
+
+        if selected_groups:
+            ctypes = [[ctype for ctype, clabel in contenttypes]
+                      for gname, contenttypes in CONTENTTYPE_GROUPS
+                      if gname in selected_groups]
+            ctypes_chain = itertools.chain(*ctypes)
+            selected_contenttypes = list(ctypes_chain)
+            contenttypes_without_encoding = [contenttype[:contenttype.index(u';')]
+                                             for contenttype in selected_contenttypes
+                                             if u';' in contenttype]
+            selected_contenttypes.extend(contenttypes_without_encoding)
+        else:
+            selected_contenttypes = all_contenttypes
+
+        unknown_item_group = "unknown items"
+        if startswith:
+            startswith = (u'%s' % startswith, u'%s' % startswith.swapcase())
+            if not selected_groups or unknown_item_group in selected_groups:
+                index = [(fullname, relname, contenttype)
+                         for fullname, relname, contenttype in index
+                         if u'/' not in relname
+                         and relname.startswith(startswith)
+                         and (contenttype not in all_contenttypes or contenttype in selected_contenttypes)]
+                         # If an item's contenttype not present in the default contenttype list,
+                         # then it will be shown without going through any filter.
+            else:
+                index = [(fullname, relname, contenttype)
+                         for fullname, relname, contenttype in index
+                         if u'/' not in relname
+                         and relname.startswith(startswith)
+                         and (contenttype in selected_contenttypes)]
+
+        else:
+            if not selected_groups or unknown_item_group in selected_groups:
+                index = [(fullname, relname, contenttype)
+                         for fullname, relname, contenttype in index
+                         if u'/' not in relname
+                         and (contenttype not in all_contenttypes or contenttype in selected_contenttypes)]
+            else:
+                index = [(fullname, relname, contenttype)
+                         for fullname, relname, contenttype in index
+                         if u'/' not in relname
+                         and contenttype in selected_contenttypes]
+
         return index
 
     index_template = 'index.html'
 
+    def get_detailed_index(self, index):
+        """ appends a flag in the index of items indicating that the parent has sub items """
+        detailed_index = []
+        all_item_index = self.get_index()
+        all_item_text = "\n".join(item_info[1] for item_info in all_item_index)
+        for fullname, relname, contenttype in index:
+            hassubitem = False
+            subitem_name_re = u"^%s/[^/]+$" % re.escape(relname)
+            regex = re.compile(subitem_name_re, re.UNICODE|re.M)
+            if regex.search(all_item_text):
+                hassubitem = True
+            detailed_index.append((fullname, relname, contenttype, hassubitem))
+        return detailed_index
+
+    def name_initial(self, names=None):
+        initials = [(name[1][0])
+                   for name in names]
+        return initials
 
 class NonExistent(Item):
-    contenttype_groups = [
-        ('markup text items', [
-            ('text/x.moin.wiki;charset=utf-8', 'Wiki (MoinMoin)'),
-            ('text/x.moin.creole;charset=utf-8', 'Wiki (Creole)'),
-            ('text/x-mediawiki;charset=utf-8', 'Wiki (MediaWiki)'),
-            ('text/x-rst;charset=utf-8', 'ReST'),
-            ('application/docbook+xml;charset=utf-8', 'DocBook'),
-            ('text/html;charset=utf-8', 'HTML'),
-        ]),
-        ('other text items', [
-            ('text/plain;charset=utf-8', 'plain text'),
-            ('text/x-diff;charset=utf-8', 'diff/patch'),
-            ('text/x-python;charset=utf-8', 'python code'),
-            ('text/csv;charset=utf-8', 'csv'),
-            ('text/x-irclog;charset=utf-8', 'IRC log'),
-        ]),
-        ('image items', [
-            ('image/jpeg', 'JPEG'),
-            ('image/png', 'PNG'),
-            ('image/svg+xml', 'SVG'),
-        ]),
-        ('audio items', [
-            ('audio/wave', 'WAV'),
-            ('audio/ogg', 'OGG'),
-            ('audio/mpeg', 'MP3'),
-            ('audio/webm', 'WebM'),
-        ]),
-        ('video items', [
-            ('video/ogg', 'OGG'),
-            ('video/webm', 'WebM'),
-            ('video/mp4', 'MP4'),
-        ]),
-        ('drawing items', [
-            ('application/x-twikidraw', 'TDRAW'),
-            ('application/x-anywikidraw', 'ADRAW'),
-            ('application/x-svgdraw', 'SVGDRAW'),
-        ]),
-
-        ('other items', [
-            ('application/pdf', 'PDF'),
-            ('application/zip', 'ZIP'),
-            ('application/x-tar', 'TAR'),
-            ('application/x-gtar', 'TGZ'),
-            ('application/octet-stream', 'binary file'),
-        ]),
-    ]
-
-    def do_get(self, force_attachment=False):
+    def do_get(self, force_attachment=False, mimetype=None):
         abort(404)
 
     def _convert(self):
@@ -639,7 +666,7 @@
         # XXX think about and add item template support
         return render_template('modify_show_type_selection.html',
                                item_name=self.name,
-                               contenttype_groups=self.contenttype_groups,
+                               contenttype_groups=CONTENTTYPE_GROUPS,
                               )
 
 item_registry.register(NonExistent._factory, Type('application/x-nonexistent'))
@@ -739,18 +766,18 @@
         return _("Impossible to convert the data to the contenttype: %(contenttype)s",
                  contenttype=request.values.get('contenttype'))
 
-    def do_get(self, force_attachment=False):
+    def do_get(self, force_attachment=False, mimetype=None):
         hash = self.rev.get(HASH_ALGORITHM)
         if is_resource_modified(request.environ, hash): # use hash as etag
-            return self._do_get_modified(hash, force_attachment=force_attachment)
+            return self._do_get_modified(hash, force_attachment=force_attachment, mimetype=mimetype)
         else:
             return Response(status=304)
 
-    def _do_get_modified(self, hash, force_attachment=False):
+    def _do_get_modified(self, hash, force_attachment=False, mimetype=None):
         member = request.values.get('member')
-        return self._do_get(hash, member, force_attachment=force_attachment)
+        return self._do_get(hash, member, force_attachment=force_attachment, mimetype=mimetype)
 
-    def _do_get(self, hash, member=None, force_attachment=False):
+    def _do_get(self, hash, member=None, force_attachment=False, mimetype=None):
         if member: # content = file contained within a archive item revision
             path, filename = os.path.split(member)
             mt = MimeType(filename=filename)
@@ -767,7 +794,10 @@
                 mt = MimeType(mimestr=mimestr)
             content_length = rev[SIZE]
             file_to_send = rev
-        content_type = mt.content_type()
+        if mimetype:
+            content_type = mimetype
+        else:
+            content_type = mt.content_type()
         as_attachment = force_attachment or mt.as_attachment(app.cfg)
         return send_file(file=file_to_send,
                          mimetype=content_type,
@@ -991,7 +1021,7 @@
         outfile.close()
         return content_type, data
 
-    def _do_get_modified(self, hash, force_attachment=False):
+    def _do_get_modified(self, hash, force_attachment=False, mimetype=None):
         try:
             width = int(request.values.get('w'))
         except (TypeError, ValueError):
@@ -1015,7 +1045,10 @@
                             width=width, height=height, transpose=transpose)
             c = app.cache.get(cid)
             if c is None:
-                content_type = self.rev[CONTENTTYPE]
+                if mimetype:
+                    content_type = mimetype
+                else:
+                    content_type = self.rev[CONTENTTYPE]
                 size = (width or 99999, height or 99999)
                 content_type, data = self._transform(content_type, size=size, transpose_op=transpose)
                 headers = wikiutil.file_headers(content_type=content_type, content_length=len(data))
@@ -1025,7 +1058,7 @@
                 headers, data = c
             return Response(data, headers=headers)
         else:
-            return self._do_get(hash, force_attachment=force_attachment)
+            return self._do_get(hash, force_attachment=force_attachment, mimetype=mimetype)
 
     def _render_data_diff(self, oldrev, newrev):
         if PIL is None:
--- a/MoinMoin/items/_tests/test_Item.py	Mon Aug 22 15:41:27 2011 +0530
+++ b/MoinMoin/items/_tests/test_Item.py	Mon Aug 22 19:46:03 2011 +0530
@@ -84,22 +84,41 @@
     def testIndex(self):
         # create a toplevel and some sub-items
         basename = u'Foo'
-        for name in ['', '/ab', '/cd/ef', '/gh', '/ij/kl', ]:
+        for name in ['', '/ab', '/cd/ef', '/gh', '/ij', '/ij/kl', ]:
             item = Item.create(basename + name)
             item._save({CONTENTTYPE: u'text/plain;charset=utf-8'}, "foo")
-
+        item = Item.create(basename + '/mn')
+        item._save({CONTENTTYPE: u'image/jpeg'}, "JPG")
         # check index
         baseitem = Item.create(basename)
         index = baseitem.get_index()
-        assert index == [(u'Foo/ab', u'ab', u'text/plain;charset=utf-8'),
-                         (u'Foo/cd/ef', u'cd/ef', u'text/plain;charset=utf-8'),
-                         (u'Foo/gh', u'gh', u'text/plain;charset=utf-8'),
-                         (u'Foo/ij/kl', u'ij/kl', u'text/plain;charset=utf-8'),
+        assert index == [(u'Foo/ab', u'ab', 'text/plain;charset=utf-8'),
+                         (u'Foo/cd/ef', u'cd/ef', 'text/plain;charset=utf-8'),
+                         (u'Foo/gh', u'gh', 'text/plain;charset=utf-8'),
+                         (u'Foo/ij', u'ij', 'text/plain;charset=utf-8'),
+                         (u'Foo/ij/kl', u'ij/kl', 'text/plain;charset=utf-8'),
+                         (u'Foo/mn', u'mn', 'image/jpeg'),
                         ]
         flat_index = baseitem.flat_index()
         assert flat_index == [(u'Foo/ab', u'ab', u'text/plain;charset=utf-8'),
                               (u'Foo/gh', u'gh', u'text/plain;charset=utf-8'),
+                              (u'Foo/ij', u'ij', u'text/plain;charset=utf-8'),
+                              (u'Foo/mn', u'mn', u'image/jpeg'),
                              ]
+        # check index when startswith param is passed
+        flat_index = baseitem.flat_index(startswith=u'a')
+        assert flat_index == [(u'Foo/ab', u'ab', 'text/plain;charset=utf-8')]
+        # check index when contenttype_groups is passed
+        ctgroups = ["image items"]
+        flat_index = baseitem.flat_index(selected_groups=ctgroups)
+        assert flat_index == [(u'Foo/mn', u'mn', 'image/jpeg')]
+        detailed_index = baseitem.get_detailed_index(baseitem.flat_index())
+        assert detailed_index == [(u'Foo/ab', u'ab', 'text/plain;charset=utf-8', False),
+                                  (u'Foo/gh', u'gh', 'text/plain;charset=utf-8', False),
+                                  (u'Foo/ij', u'ij', 'text/plain;charset=utf-8', True),
+                                  (u'Foo/mn', u'mn', 'image/jpeg', False),
+                                  ]
+
 
     def test_meta_filter(self):
         name = u'Test_item'
--- a/MoinMoin/script/maint/index.py	Mon Aug 22 15:41:27 2011 +0530
+++ b/MoinMoin/script/maint/index.py	Mon Aug 22 19:46:03 2011 +0530
@@ -214,7 +214,7 @@
 
         backend = flaskg.unprotected_storage = app.unprotected_storage
         index_object = WhooshIndex(index_dir=app.cfg.index_dir_tmp)
-        interwikiname = app.cfg.interwikiname or u''
+        interwikiname = app.cfg.interwikiname
         if os.path.samefile(app.cfg.index_dir_tmp, app.cfg.index_dir):
             raise FatalError(u"cfg.index_dir and cfg.index_dir_tmp must point to different directories.")
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MoinMoin/static/js/index_action.js	Mon Aug 22 19:46:03 2011 +0530
@@ -0,0 +1,242 @@
+/*
+ * Script for the actions performed on the items at index page.
+ * Copyright 2011, AkashSinha<akash2607@gmail.com> 
+ */
+
+var actionLoading = [];
+actionLoading["delete"] = "Deleting..";
+actionLoading["destroy"] = "Destroying..";
+
+var actionDone = [];
+actionDone["delete"] = "deleted";
+actionDone["destroy"] = "destroyed";
+
+function enablelink(downloadlink) {
+    url=downloadlink.attr("title");
+    downloadlink.attr("href",url);
+    downloadlink.addClass("active-link");
+}
+
+function disablelink(downloadlink) {
+    downloadlink.attr("href","about:blank");
+    downloadlink.removeClass("active-link");
+}
+
+function showpop(action) {
+    $(".popup-container").css("display", "none");
+    if(action == "newitem") {
+        $("#popup-for-newitem").css("display", "block");
+        $("#file_upload").appendTo("#popup-for-newitem .popup-body");
+        $(".upload-form").css("display", "block");
+    }
+    else {
+        $("#popup-for-action").css("display", "block");
+        $(".popup-comment").removeClass("blank");
+        $(".popup-comment").val("");
+        $(".popup-action").val(action);
+    }
+    $("#popup").fadeIn();
+    $("#lightbox").css("display", "block");
+}
+
+function hidepop() {
+    $("#popup").css("display", "none");
+    $("#lightbox").css("display", "none");
+}
+
+function hide(item_link) {
+   item_link.parent().remove();
+}
+
+function show_conflict(item_link) {
+   item_link.removeClass().addClass("moin-conflict");
+   item_link.parent().removeClass();
+}
+
+function do_action(comment, action) {
+    var links = [];
+    $(".selected-item").children("a.moin-item").each(function () {
+        itemname = $(this).attr("title");
+        links.push(itemname);
+    });
+    var itemnames = JSON.stringify(links);
+    var actionTrigger = "moin-" + action + "-trigger";
+    url = $("#" + actionTrigger).attr("actionurl");
+    $("#popup").css("display", "none");
+    $(".moin-index-message span").text(actionLoading[action]);
+    $(".moin-index-message").css("display", "block");
+    $.post(url, {
+            itemnames: itemnames,
+            comment: comment,
+            }, function (data) {
+                var itemnames = data.itemnames;
+                var action_status = data.status;
+                var success_item = 0;
+                var left_item = 0;
+                $.each(itemnames, function (itemindex, itemname) {
+                    if(action_status[itemindex]) {
+                        hide($('.selected-item').children('a.moin-item[title="' + itemname + '"]'));
+                        success_item++;
+                    }
+                    else {
+                        show_conflict($('.selected-item').children('a.moin-item[title="' + itemname + '"]'));
+                        left_item++;
+                   }  
+                   });
+                   var message = "Items " + actionDone[action] + ": " + success_item ;
+                   if(left_item)
+                       message += ", Items not " + actionDone[action] + ": " + left_item + ".";
+                   $(".moin-index-message span").text(message);
+                   setTimeout(function () {
+                       $(".moin-index-message").fadeOut();
+                   }, 4000);
+            }, "json");
+}
+
+$("document").ready(function () {
+
+    $(".moin-contenttypes-wrapper").children("div").click(function () {
+        var wrapper = $(this).parent();
+        if(wrapper.find("ul:visible").length) {
+            $(".moin-contenttypes-wrapper").find("ul").fadeOut(200);
+            $(this).removeClass().addClass("ct-hide");
+        }
+        else {
+            $(".moin-contenttypes-wrapper").find("ul").fadeIn(200);
+            $(this).removeClass().addClass("ct-shown");
+        }
+    });
+
+    $(".filter-toggle").click(function () {
+        $(".moin-contenttypes-wrapper form").find("input[type='checkbox']").each(function () {
+            if($(this).attr("checked"))
+                $(this).removeAttr("checked");
+            else
+                $(this).attr("checked", "checked");
+        });
+        return false;
+    });
+
+    $(".filter-more").click(function () {
+        var helper_texts = $(".moin-contenttypes-wrapper form").find(".helper-text:visible");
+        if(helper_texts.length) {
+            helper_texts.fadeOut();
+        }
+        else {
+            $(".moin-contenttypes-wrapper form").find(".helper-text").css("display", "block");
+        }
+            
+        return false;
+    });
+
+    $(".moin-select-item").click(function () {
+        if($(this).parent().hasClass("selected-item")) {
+            $(this).parent().removeClass("selected-item");
+            downloadlink=$(this).parent().children(".moin-download-link");
+            disablelink(downloadlink);
+            if($(".moin-select-allitem").hasClass("allitem-selected")) {
+                $(".moin-select-allitem").removeClass("allitem-selected").addClass("allitem-toselect");
+            }
+        }
+        else {
+            $(this).parent().addClass("selected-item");
+            downloadlink=$(this).parent().children(".moin-download-link");
+            enablelink(downloadlink);
+        }
+    });
+
+    $(".show-action").click(function () {
+        actionsDiv = $(this).parent().parent();
+         if(actionsDiv.find("ul:first").is(":visible")) {
+             actionsDiv.find("ul:first").fadeOut(200);
+             actionsDiv.removeClass("action-visible");
+         }
+         else {
+             actionsDiv.find("ul:first").fadeIn(200);
+             actionsDiv.addClass("action-visible");
+         }
+    });
+    
+    $(".moin-select-allitem").click(function () {
+        if($(this).hasClass("allitem-toselect")) {
+            $(".moin-item-index div").removeClass().addClass("selected-item");
+            $(".moin-item-index div").each(function () {
+                downloadlink=$(this).children(".moin-download-link");
+                enablelink(downloadlink);
+            });
+            $(this).removeClass("allitem-toselect").addClass("allitem-selected");
+        }
+        else {
+            $(this).removeClass("allitem-selected").addClass("allitem-toselect");
+            $(".moin-item-index div").removeClass();
+            $(".moin-item-index div").each(function () {
+                downloadlink=$(this).children(".moin-download-link");
+                disablelink(downloadlink);
+            });
+        }
+    });
+
+    $(".moin-action-tab").click(function () {
+        if(!($("div.selected-item").length)) {
+            $(".moin-index-message span").text("Nothing was selected.");
+            $(".moin-index-message").fadeIn();
+            setTimeout(function () {
+                $(".moin-index-message").fadeOut();
+            }, 4000);
+        }
+        else {
+            if(this.id == "moin-delete-trigger") 
+                showpop("delete");
+            else
+                showpop("destroy");
+        }
+        $(".show-action").trigger("click");
+    });
+
+    $("#moin-create-newitem").click(function () {
+        showpop("newitem");
+        $(".show-action").trigger("click");
+
+    });
+
+    $(".popup-cancel").click(function () {
+        if($("#popup-for-newitem:visible").length) {
+            $("#file_upload").appendTo("#moin-upload-cont");
+            $(".upload-form").css("display", "none");
+        }
+        hidepop();
+    });
+
+    $(".popup-submit").click(function () {
+        var comment = $(".popup-comment").val();
+        var action = $(".popup-action").val();
+        comment = $.trim(comment);
+        do_action(comment, action);
+        hidepop();
+    });
+
+    $("#popup-for-newitem").find("form:first").submit(function () {
+        var itembox = $(this).children("input[name='newitem']");
+        itemname = itembox.val();
+        if($.trim(itemname) == "") {
+            itembox.addClass("blank");
+            itembox.focus();
+            return false;
+       }
+    });
+
+    $("#moin-download-trigger").click(function () {
+        if(!($("a.active-link").length)) {
+           $(".moin-index-message span").text("Nothing was selected.");
+           $(".moin-index-message").fadeIn();
+           setTimeout(function () {
+               $(".moin-index-message").fadeOut();
+           }, 4000);
+        }
+        $(".show-action").trigger("click");
+    });
+
+    $('.moin-download-link').multiDownload();
+    $('#moin-download-trigger').multiDownload('click', { delay: 3000 });
+
+});
--- a/MoinMoin/static/js/jfu.js	Mon Aug 22 15:41:27 2011 +0530
+++ b/MoinMoin/static/js/jfu.js	Mon Aug 22 19:46:03 2011 +0530
@@ -4,6 +4,7 @@
  *
  * Copyright 2010, Sebastian Tschan, https://blueimp.net
  * Copyright 2011, Thomas Waldmann (adapted for MoinMoin)
+ * Copyright 2011, Akash Sinha (modified further for MoinMoin)
  *
  * Licensed under the MIT license:
  * http://creativecommons.org/licenses/MIT/
@@ -47,13 +48,14 @@
     UploadHandler = function (container, options) {
         var uploadHandler = this;
 
+        this.fileArray = new Array();
         this.url = container.find('form:first').attr('action');
-        this.dropZone = container.find('form:first');
+        this.dropZone = $("#moin-content");
         this.uploadTable = container.find('.files:first');
-        this.downloadTable = this.uploadTable;
+        this.downloadTable = $("#moin-new-index");
         this.progressAllNode = container.find('.file_upload_overall_progress div:first');
         this.uploadTemplate = this.uploadTable.find('.file_upload_template:first');
-        this.downloadTemplate = this.uploadTable.find('.file_download_template:first');
+        this.downloadTemplate = this.downloadTable.find('.file_download_template:first');
         this.multiButtons = container.find('.file_upload_buttons:first');
         
         this.formatFileName = function (name) {
@@ -73,6 +75,14 @@
             });
         };
 
+        this.fileExist = function (fileName, fileArray) {
+            for(var i=0; i<fileArray.length; i++) {
+                  if (fileArray[i] == fileName) return true;
+            }
+            fileArray.push(fileName);
+            return false;
+        };
+
         this.buildMultiUploadRow = function (files, handler) {
             var rows = $('<tbody style="display:none;"/>');
             $.each(files, function (index, file) {
@@ -98,6 +108,7 @@
                 fileName = handler.formatFileName(file.name),
                 uploadRow = handler.uploadTemplate
                     .clone().removeAttr('id');
+            if(!handler.fileExist(fileName, handler.fileArray)) {
             uploadRow.find('.file_name')
                 .text(fileName);
             uploadRow.find('.file_upload_start button')
@@ -105,10 +116,12 @@
             uploadRow.find('.file_upload_cancel button')
                 .button({icons: {primary: 'ui-icon-cancel'}, text: false});
             return uploadRow;
+            }
+            return null;
+            
         };
 
         this.buildMultiDownloadRow = function (files, handler) {
-            var rows = $('<tbody style="display:none;"/>');
             $.each(files, function (index, file) {
                 rows.append(handler.buildDownloadRow(file, handler).show());
             });
@@ -121,19 +134,16 @@
             }
             var fileName = handler.formatFileName(file.name),
                 fileUrl = file.url,
-                fileUrlDownload = file.url_download,
+                fileContenttype = file.contenttype,
                 downloadRow = handler.downloadTemplate
                     .clone().removeAttr('id');
             downloadRow.attr('data-id', file.id || file.name);
-            downloadRow.find('.file_name a')
+            downloadRow.find('a')
                 .text(fileName);
-            downloadRow.find('.file_name a')
+            downloadRow.find('a')
                 .attr('href', fileUrl || null);
-            downloadRow.find('.file_download a')
-                .text('DL');
-            downloadRow.find('.file_download a')
-                .attr('href', fileUrlDownload || null)
-                .each(handler.enableDragToDesktop);
+            downloadRow.find('a')
+                .attr('class', fileContenttype || null);
             return downloadRow;
         };
         
@@ -171,6 +181,11 @@
             if (!uploadHandler.uploadTable.find('.file_upload_progress div:visible:first').length) {
                 uploadHandler.multiButtons.find('.file_upload_start:first, .file_upload_cancel:first').fadeOut();
             }
+            if (!uploadHandler.downloadTable.find("h3:visible").length) {
+                uploadHandler.downloadTable.find("h3:first").fadeIn();
+                $(".moin-index-separator").fadeIn();
+            }
+            uploadHandler.fileArray.length = 0;
         };
 
         this.initEventHandlers = function () {
@@ -178,6 +193,7 @@
                 setTimeout(function () {
                     if (!uploadHandler.uploadTable.find('.file_upload_progress div:visible:first').length) {
                         uploadHandler.multiButtons.find('.file_upload_start:first, .file_upload_cancel:first').fadeOut();
+                        uploadHandler.fileArray.length = 0;
                     }
                 }, 500);
             });
@@ -277,13 +293,4 @@
 $(function () {
     // Initialize jQuery File Upload (Extended User Interface Version):
     $('#file_upload').fileUploadUIX();
-
-    // Load existing files:
-    $.getJSON($('#file_upload').fileUploadUIX('option', 'url'), function (files) {
-        var fileUploadOptions = $('#file_upload').fileUploadUIX('option');
-        $.each(files, function (index, file) {
-            fileUploadOptions.buildDownloadRow(file, fileUploadOptions)
-                .appendTo(fileUploadOptions.downloadTable).fadeIn();
-        });
-    });
 });
--- a/MoinMoin/storage/backends/indexing.py	Mon Aug 22 15:41:27 2011 +0530
+++ b/MoinMoin/storage/backends/indexing.py	Mon Aug 22 19:46:03 2011 +0530
@@ -202,7 +202,7 @@
     Index for Items/Revisions
     """
     def __init__(self, cfg):
-        self.wikiname = cfg.interwikiname or u''
+        self.wikiname = cfg.interwikiname
         self.index_object = WhooshIndex(cfg=cfg)
 
     def close(self):
--- a/MoinMoin/templates/forms.html	Mon Aug 22 15:41:27 2011 +0530
+++ b/MoinMoin/templates/forms.html	Mon Aug 22 19:46:03 2011 +0530
@@ -25,6 +25,17 @@
   </dd>
 {% endmacro %}
 
+{% macro render_filter_field(gen, field, field_type, helper_text) %}
+  <li>
+    {{ gen.input(field, type=field_type) }}
+    {{ render_errors(field) }}
+    {{ gen.label(field) }}
+    <span class="helper-text">
+        {{ helper_text }}
+    </span>
+  </li>
+{% endmacro %}
+
 {% macro render_select(gen, field) %}
   <dt>
     {{ gen.label(field) }}
@@ -60,3 +71,31 @@
     {{ gen.label(field) }}
     {{ render_errors(field) }}
 {% endmacro %}
+
+{% macro render_file_uploader(submit_url) %}
+    <div id="file_upload">
+        <div class="upload-form">
+        <form action="{{ submit_url }}" method="POST" enctype="multipart/form-data" class="upload_file">
+            <input type="file" name="data_file" multiple>
+            <button type="submit">{{ _("Upload") }}</button>
+            <div class="file_upload_label" style="margin: 0;">{{ _("Upload files") }}</div>
+        </form>
+        </div>
+        <div class="file_upload_overall_progress"><div style="display:none;"></div></div>
+        <div class="file_upload_buttons">
+            <button class="file_upload_start" style="display:none;">{{ _("Start All") }}</button> 
+            <button class="file_upload_cancel" style="display:none;">{{ _("Cancel All") }}</button> 
+        </div>
+        <table class="files">
+            <tr class="file_upload_template" style="display:none;">
+                <td class="file_upload_start"><button>{{ _("Start") }}</button></td>
+                <td class="file_upload_cancel"><button>{{ _("Cancel") }}</button></td>
+                <td class="file_name"></td>
+                <td class="file_upload_progress"><div></div></td>
+            </tr>
+        </table>
+    </div>
+    <link rel="stylesheet" href="{{ url_for('serve.files', name='jquery_file_upload', filename='jquery.fileupload-ui.css') }}">
+    <script src="{{ url_for('serve.files', name='jquery_file_upload', filename='jquery.fileupload.js') }}"></script>
+    <script src="{{ url_for('serve.files', name='jquery_file_upload', filename='jquery.fileupload-ui.js') }}"></script>
+{% endmacro %}
--- a/MoinMoin/templates/global_history.html	Mon Aug 22 15:41:27 2011 +0530
+++ b/MoinMoin/templates/global_history.html	Mon Aug 22 19:46:03 2011 +0530
@@ -7,32 +7,79 @@
 {% endblock %}
 
 {% block content %}
+<div class='moin-offset-links'>
+    {% if previous_offset >= 0 %}
+        <a href="{{ url_for('frontend.global_history', offset=previous_offset) }}" title="{{ _("Previous") }}">&laquo;</a>
+    {% endif %}
+    {% if offset %}
+        <a href="{{ url_for('frontend.global_history', offset=offset) }}" title="{{ _("Next") }}">&raquo;</a>
+    {% endif %}
+</div>
 <h1>{{ _("Global History") }}</h1>
-    <table id="moin-global-history">
-        <thead>
-            <tr>
-                <th>{{ _("Timestamp") }}</th>
-                <th>{{ _("Action") }}</th>
-                <th>{{ _("Name") }}</th>
-                <th>{{ _("Rev.") }}</th>
-                <th>{{ _("Content-Type") }}</th>
-                <th>{{ _("Editor") }}</th>
-                <th>{{ _("Comment") }}</th>
-            </tr>
-        </thead>
-        <tbody>
-        {% for rev in history %}
-        <tr>
-            <td>{{ rev.timestamp|datetimeformat }}</td>
-            <td class="moin-wordbreak">{{ rev.action }}</td>
-            <td class="moin-wordbreak"><a href="{{ url_for('frontend.show_item', item_name=rev.item.name) }}">{{ rev.item.name }}</a>
-                {% if rev.item.name != rev.name %} ({{ rev.name }}){% endif %}</td>
-            <td class="moin-integer">{{ rev.revno }}</td>
-            <td class="moin-wordbreak">{{ rev.contenttype }}</td>
-            <td class="moin-wordbreak">{{ utils.editor_info(rev) }}</td>
-            <td class="moin-wordbreak">{{ rev.comment }}</td>
-        </tr>
+<div class='moin-clr'></div>
+    {% if user.valid  %}
+    <div id="moin-set-bookmark">
+        {% if bookmark_time %}
+            {{ _("Bookmark (currently set to %(bookmark)s). ", bookmark=bookmark_time|datetimeformat) }} 
+            <a href="{{ url_for('frontend.bookmark', time='del') }}">{{ _("Delete bookmark") }}</a>
+        {% else %}
+            {{ _("Bookmark (not set). ") }}<a href="{{ url_for('frontend.bookmark', time=current_timestamp) }}">{{ _("Set bookmark") }}</a> 
+        {% endif %}
+    </div>
+    {% endif %}
+    <div id="moin-global-history">
+        {% for rev_date, revs in history %}
+           {% set  latest_rev = revs[0] %}
+           {% set  latest_timestamp = latest_rev.timestamp %}
+            <div class="moin-history-container"> 
+                <div class="moin-history-container-header">
+                    <span>
+                        <h2>{{ rev_date }}</h2>
+                        {% if user.valid %}
+                        <a class="bookmark-link" href="{{ url_for('frontend.bookmark', time=latest_timestamp) }}">{{ _("Set bookmark") }}</a>
+                        {% endif %}
+                   </span>
+                </div>
+                <div class="moin-history-container-body">
+                    <table>
+                    {% for rev in revs %}
+                        <tr>
+                            {% set item_latest_revno = rev.revnos[0] %}
+                            <td class="moin-action" title="{{ _("DIFF") }}">                                
+                                <a href="{{ url_for('frontend.diff', item_name=rev.item_name, rev1=item_latest_revno, rev2=0) }}" class="moin-history-{{ rev.action|lower }}"></a>
+                            </td>
+                            <td class="moin-history-item"><a class="{{ rev.contenttype|contenttype_to_class }}" href="{{ url_for('frontend.show_item', item_name=rev.item_name) }}" title="{{ rev.contenttype }}">{{ rev.item_name }}</a></td>
+                            <td class="moin-history-time">{{ rev.timestamp|timeformat }}</td>
+                            <td class="moin-history-links">
+                                {% for revno in rev.revnos %}
+                                    {% if revno %}
+                                        <a href="{{ url_for('frontend.diff', item_name=rev.item_name, rev1=revno, rev2=revno-1) }}">[{{ revno }}]</a>
+                                    {% else %}
+                                        <span>[0]</span>
+                                    {% endif %}
+                                {% endfor %}
+                            </td>
+                            <td class="moin-wordbreak moin-history-editorinfo">
+                                {% for info, position in rev.editors %}
+                                    <span class="moin-history-editortext">
+                                    {{ utils.show_editor_info(info) }}
+                                    {{ position }}
+                                    </span>
+                                {% endfor %}
+                            </td>
+                            <td class="moin-wordbreak moin-history-comment">
+                               {% for comment in rev.comments %}
+                                   <span>{{ comment }}</span>
+                               {% endfor %}
+                            </td>
+                        </tr>
+                    {% endfor %}
+                    </table>
+                </div>
+            </div>
         {% endfor %}
-        </tbody>
-    </table>
+    </div>
+   {% if bookmark_time and not offset %}
+       <div id="moin-bookmark-reached">{{ _("Bookmark reached") }}</div>
+   {% endif %}
 {% endblock %}
--- a/MoinMoin/templates/global_index.html	Mon Aug 22 15:41:27 2011 +0530
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,17 +0,0 @@
-{% extends theme("layout.html") %}
-
-{% block item %}
-    <h1>{{ _("Global Index") }}</h1>
-    {% if index %}
-        <ul>
-        {% for fullname, relname, contenttype in index %}
-            <li>
-                <a href="{{ url_for('.show_item', item_name=fullname) }}"
-                   class="{{ contenttype|contenttype_to_class }}">
-                    {{ relname }}
-                </a>
-            </li>
-        {% endfor %}
-        </ul>
-    {% endif %}
-{% endblock %}
--- a/MoinMoin/templates/history.html	Mon Aug 22 15:41:27 2011 +0530
+++ b/MoinMoin/templates/history.html	Mon Aug 22 19:46:03 2011 +0530
@@ -1,8 +1,18 @@
 {% extends theme("show.html") %}
 {% import "utils.html" as utils %}
 {% block content %}
+    {% set (history, next_offset, previous_offset) = history_page %}
     {% if history %}
+    <div class='moin-offset-links'>
+        {% if previous_offset >= 0 %}
+            <a href="{{ url_for('frontend.history', item_name=item_name, offset=previous_offset) }}" title="{{ _("Previous") }}">&laquo;</a>
+        {% endif %}
+        {% if next_offset %}
+            <a href="{{ url_for('frontend.history', item_name=item_name, offset=next_offset) }}" title="{{ _("Next") }}">&raquo;</a>
+        {% endif %}
+    </div>
     <h1>{{ _("History of '%(item_name)s'", item_name=item_name) }}</h1>
+    <div class="moin-clr"></div>
     <form action="{{ url_for('frontend.diff', item_name=item_name) }}" method="GET">
         <div id="moin-page-history">
         <table>
--- a/MoinMoin/templates/index.html	Mon Aug 22 15:41:27 2011 +0530
+++ b/MoinMoin/templates/index.html	Mon Aug 22 19:46:03 2011 +0530
@@ -1,17 +1,174 @@
 {% extends theme("show.html") %}
+{% import "forms.html" as forms %}
+{% block head_scripts %}
+{{ super() }}
+    <script src="{{ url_for('serve.files', name='jquery_multi_download', filename='jquery.multiDownload.js') }}"></script>
+    <script src="{{ url_for('static', filename='js/index_action.js') }}"></script>
+{% endblock %}
 
 {% block content %}
-    <h1>{{ _("Index of subitems of '%(item_name)s'", item_name=item_name) }}</h1>
-    {% if index %}
+    <div class="moin-index-message"><span></span></div>
+    <div class="moin-align-right">
         <ul>
-        {% for fullname, relname, contenttype in index %}
-            <li>
-                <a href="{{ url_for('.show_item', item_name=fullname) }}"
-                   class="{{ contenttype|contenttype_to_class }}">
-                    {{ relname }}
+            {% if index %}
+            <li class="action-bar"> 
+            <div class="moin-select-all">
+                <span class="moin-select-allitem allitem-toselect" title="{{ _("Select All") }}">{{ _("Select All") }}</span>
+            </div>
+            </li>
+            {% endif %}
+            <li class="action-bar">
+            <div class="moin-select-actions">
+                <div>
+                    <span class="show-action">Actions</span> 
+                </div>
+                <ul>
+                    <li id="moin-create-newitem">{{ _("New item") }}</li>
+                    <li id="moin-download-trigger">{{ _("Download") }}</li>
+                    <li class="moin-action-tab" 
+                        id="moin-delete-trigger" 
+                        actionurl="{{ url_for('frontend.ajaxdelete', item_name=item_name) }}">
+                        {{ _("Delete") }}
+                    </li>
+                    <li class="moin-action-tab" 
+                        id="moin-destroy-trigger" 
+                        actionurl="{{ url_for('frontend.ajaxdestroy', item_name=item_name) }}">
+                        {{ _("Destroy") }}
+                    </li>
+                </ul>
+            </div>
+            </li>
+            {% if index %}
+            <li class="action-bar">
+            <div class="moin-contenttypes-wrapper">
+                <div class="ct-hide">{{ _("Filter by content type") }}</div>
+                {% set unknown_items_label = _("items having unknown mime types") %}
+                {{ gen.form.open(form, method="post", action=url_for('frontend.index', item_name=item_name)) }}
+                <ul>
+                    <li>
+                        <a href="#" class="filter-toggle">&raquo; {{ _("Toggle") }}</a>
+                        <a href="#" class="filter-more">&raquo; {{ _("More") }}</a>
+                    </li>
+                    {{ forms.render_filter_field(gen, form['markup_text_items'], 'checkbox', contenttype_groups['markup text items']) }}
+                    {{ forms.render_filter_field(gen, form['other_text_items'], 'checkbox', contenttype_groups['other text items']) }}
+                    {{ forms.render_filter_field(gen, form['image_items'], 'checkbox', contenttype_groups['image items']) }}
+                    {{ forms.render_filter_field(gen, form['audio_items'], 'checkbox', contenttype_groups['audio items']) }}
+                    {{ forms.render_filter_field(gen, form['video_items'], 'checkbox', contenttype_groups['video items']) }}
+                    {{ forms.render_filter_field(gen, form['other_items'], 'checkbox', contenttype_groups['other items']) }}
+                    {{ forms.render_filter_field(gen, form['unknown_items'], 'checkbox', unknown_items_label) }}
+                    {{ gen.input(form['submit'], type='submit') }}
+                </ul>
+                {{ gen.form.close() }}
+            </div>
+            </li>
+            {% endif %}
+        </ul>
+    </div>
+    <div>
+    {% if item_name: %}
+        <h1>{{ _("Index of subitems of '%(item_name)s'", item_name=item_name) }}</h1>
+        <div class="moin-index-path">
+            <a href="{{ url_for('frontend.index') }}" title="{{ _("Global Index") }}">{{ ("..") }}</a>
+            <span class="moin-path-separator">{{ ("/") }}</span>
+            {% for i in range(0, item_names|count) %}
+                {% set fullname = item_names[:i+1]|join('/') %}
+                {% set relname = item_names[i] %}
+                <a href="{{ url_for('frontend.index', item_name=fullname) }}" title="{{ relname }}">{{ relname }}</a>
+                <span class="moin-path-separator">{{ ("/") }}</span>
+            {% endfor %}
+        </div>
+    {% else %}
+        <h1>{{ _("Global Index") }}</h1>
+    {% endif %}
+    </div>
+    <div class='moin-clr'></div>
+    <div id="moin-new-index" class="moin-item-index">
+        <h3 style="display: none;">{{ _("Recently uploaded items") }}</h3>
+        <div class="file_download_template" style="display: none;">
+            <a></a>
+        </div>
+    </div>
+    <div class="moin-index-separator"></div>
+    {% if index %}
+    <div id="moin-initials">
+        {% if not startswith %}
+            <a class="selected" href="{{ url_for('frontend.index', item_name=item_name) }}">{{ _("All") }}</a>
+        {% else %}
+            <a href="{{ url_for('frontend.index', item_name=item_name) }}">{{ _("All") }}</a>
+        {% endif %}
+        {% for initial in initials %}
+            {% if startswith == initial %}
+                <a class="selected" href="{{ url_for('frontend.index', item_name=item_name, startswith=initial) }}">{{ initial }}</a>
+            {% else %}
+                <a href="{{ url_for('frontend.index', item_name=item_name, startswith=initial) }}">{{ initial }}</a>
+            {% endif %}
+        {% endfor %}
+    </div>
+    <div class="moin-item-index">
+        {% set maxchars = 20 %}
+        {% for fullname, relname, contenttype, hassubitem in index %}
+            <div>
+                <span class="moin-select-item">&nbsp;</span>
+                {% set mimetype = "application/x.moin.download" %}
+                <a href="about:blank" title="{{ url_for('.download_item', item_name=fullname, mimetype=mimetype) }}"
+                   class="moin-download-link">
                 </a>
-            </li>
+                <a href="{{ url_for('.show_item', item_name=fullname) }}" 
+                   class="{{ contenttype|contenttype_to_class }} moin-item"
+                   title="{{ relname }}">
+                   {{ relname|truncate(maxchars, true, '..') }}
+                </a>
+                {% if hassubitem %}
+                    <a href="{{ url_for('frontend.index', item_name=fullname) }}" 
+                       title="{{ _("More") }}"
+                       class="moin-more-index">&nbsp;
+                </a>
+                {% endif %}
+            </div>
         {% endfor %}
-        </ul>
+    </div>
+    <div class="moin-clr"></div>
     {% endif %}
+    <div id="popup">
+        <div id="popup-for-action" class="popup-container">
+            <div class="popup-header">
+                <div class="popup-closer popup-cancel" title="{{ _("Close") }}">x</div>
+                <span>{{ _("Please provide comment for this action") }}</span>
+            </div>
+            <div class="popup-body">
+                <input type="text" class="popup-comment" placeholder="{{ _("Enter your comment") }}"/>
+                <input type="hidden" class="popup-action" value=""/>
+                <br/>
+                <input type="button" class="popup-submit" value="{{ _("Submit") }}"/>
+                <input type="button" class="popup-cancel" value="{{ _("Cancel") }}"/>
+            </div>
+        </div>
+        <div id="popup-for-newitem" class="popup-container">
+            <div class="popup-header">
+                <div class="popup-closer popup-cancel" title="{{ _("Close") }}">x</div>
+                <span>{{ _("Create new item") }}</span>
+            </div>
+            <div class="popup-body">
+                <form action={{ url_for('.ajaxmodify') }} method="post">
+                    <label for="newitem">{{ _("Item name") }}</label>
+                    {% if item_name %}
+                        <input type="text" name="newitem" placeholder="{{ _("Enter item name here") }}" value="{{ item_name }}/" required="true"/>
+                    {% else %}
+                        <input type="text" name="newitem" placeholder="{{ _("Enter item name here") }}" required="true"/>
+                    {% endif %}
+                    <br/>
+                    <input type="submit" value="{{ _("Create") }}"/>
+                    <input type="button" class="popup-cancel" value="{{ _("Cancel") }}"/>
+                </form>
+            </div>
+        </div>
+    </div>
+
+    <div id="moin-upload-cont">
+    {% set submit_url = url_for('.jfu_server', item_name=item_name) %}
+    {{ forms.render_file_uploader(submit_url) }}
+    </div>
+    <span class="moin-drag">{{ _("(Drag and drop multiple files to this white area to upload them.)") }}</span>
+    <script src="{{ url_for('static', filename='js/jfu.js') }}"></script>
+    <div id="lightbox">&nbsp;</div>
 {% endblock %}
--- a/MoinMoin/templates/index2.html	Mon Aug 22 15:41:27 2011 +0530
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,37 +0,0 @@
-{% extends theme("show.html") %}
-
-{% block theme_stylesheets %}
-{{ super() }}
-<link rel="stylesheet" href="{{ url_for('serve.files', name='jquery_file_upload', filename='jquery.fileupload-ui.css') }}">
-{% endblock %}
-
-{% block content %}
-    <h1>{{ _("Index of subitems of '%(item_name)s'", item_name=item_name) }}</h1>
-<div id="file_upload">
-    <form action="{{ url_for('.jfu_server', item_name=item_name) }}" method="POST" enctype="multipart/form-data">
-        <input type="file" name="data_file" multiple>
-        <button type="submit">Upload</button>
-        <div class="file_upload_label">Upload files</div>
-    </form>
-    <div class="file_upload_overall_progress"><div style="display:none;"></div></div>
-    <div class="file_upload_buttons">
-        <button class="file_upload_start" style="display:none;">Start All</button> 
-        <button class="file_upload_cancel" style="display:none;">Cancel All</button> 
-    </div>
-    <table class="files">
-        <tr class="file_upload_template" style="display:none;">
-            <td class="file_upload_start"><button>Start</button></td>
-            <td class="file_upload_cancel"><button>Cancel</button></td>
-            <td class="file_name"></td>
-            <td class="file_upload_progress"><div></div></td>
-        </tr>
-        <tr class="file_download_template" style="display:none;">
-            <td class="file_download" colspan="2"><a></a></td>
-            <td class="file_name" colspan="2"><a></a></td>
-        </tr>
-    </table>
-</div>
-<script src="{{ url_for('serve.files', name='jquery_file_upload', filename='jquery.fileupload.js') }}"></script>
-<script src="{{ url_for('serve.files', name='jquery_file_upload', filename='jquery.fileupload-ui.js') }}"></script>
-<script src="{{ url_for('static', filename='js/jfu.js') }}"></script>
-{% endblock %}
--- a/MoinMoin/templates/itemviews.html	Mon Aug 22 15:41:27 2011 +0530
+++ b/MoinMoin/templates/itemviews.html	Mon Aug 22 19:46:03 2011 +0530
@@ -2,7 +2,7 @@
 <ul class="moin-itemviews">
     {% for endpoint, label, title, check_exists in cfg.item_views if not endpoint in cfg.endpoints_excluded %}
         {% if (not check_exists or check_exists and exists) and endpoint in [
-               'frontend.show_item', 'frontend.index', 'frontend.index2',
+               'frontend.show_item', 'frontend.index',
                'frontend.highlight_item', 'frontend.show_item_meta', 'frontend.download_item',
                'frontend.history', 'frontend.backrefs', 'frontend.sitemap',
                'frontend.similar_names',
--- a/MoinMoin/templates/usersettings.html	Mon Aug 22 15:41:27 2011 +0530
+++ b/MoinMoin/templates/usersettings.html	Mon Aug 22 19:46:03 2011 +0530
@@ -64,6 +64,7 @@
     {{ forms.render_select(gen, form['theme_name']) }}
     {{ forms.render_field(gen, form['css_url'], 'url') }}
     {{ forms.render_field(gen, form['edit_rows'], 'text') }}
+    {{ forms.render_field(gen, form['results_per_page'], 'number') }}
   </dl>
   {{ gen.input(form['submit'], type='submit') }}
 {{ gen.form.close() }}
--- a/MoinMoin/templates/utils.html	Mon Aug 22 15:41:27 2011 +0530
+++ b/MoinMoin/templates/utils.html	Mon Aug 22 19:46:03 2011 +0530
@@ -1,5 +1,4 @@
-{% macro editor_info(rev) %}
-  {%- set info = get_editor_info(rev) -%}
+{% macro show_editor_info(info) %}
   {%- if info.uri -%}
       <a href="{{ info.uri }}" class="{{ info.css }}" title="{{ info.title }}">
   {%- elif info.email -%}
@@ -16,6 +15,12 @@
 {% endmacro %}
 
 
+{% macro editor_info(rev) %}
+  {%- set info = get_editor_info(rev) -%}
+  {{ show_editor_info(info) }}
+{% endmacro %}
+
+
 {% macro table(headings, rows) %}
 <table>
 <thead>
--- a/MoinMoin/themes/__init__.py	Mon Aug 22 15:41:27 2011 +0530
+++ b/MoinMoin/themes/__init__.py	Mon Aug 22 19:46:03 2011 +0530
@@ -347,6 +347,12 @@
 
 MIMETYPE_TO_CLASS = {
     'application/pdf': 'pdf',
+    'application/zip': 'package',
+    'application/x-tar': 'package',
+    'application/x-gtar': 'package',
+    'application/x-twikidraw': 'drawing',
+    'application/x-anywikidraw': 'drawing',
+    'application/x-svgdraw': 'drawing',
 }
 
 def contenttype_to_class(contenttype):
--- a/MoinMoin/themes/modernized/static/css/common.css	Mon Aug 22 15:41:27 2011 +0530
+++ b/MoinMoin/themes/modernized/static/css/common.css	Mon Aug 22 19:46:03 2011 +0530
@@ -211,13 +211,116 @@
 .moin-hist-rev { margin: 0; }
 #moin-global-history,
 #moin-page-history { font-size: 75%; }
-#moin-global-history tr,
-#moin-page-history tr { border: 1px solid #4D7DA9; }
+#moin-page-history tr { border: 1px solid #4D7DA9; } 
 #moin-global-history th,
 #moin-page-history th { background-color: #81BBF2; border: 0px; font-size: 1.12em; padding: 6px .5em; text-align: left; }
-#moin-global-history td,
+#moin-global-history td {  border: 0px; vertical-align: top;text-align: left; padding: 0.4em 0.3em; }
 #moin-page-history td { background-color: #E6EAF0; border: 0px; vertical-align: top; }
 .moin-wordbreak { word-break: break-all;  word-wrap: break-word; } /* Firefox needs javascript assistance within tables */
+.moin-history-time { width: 10%; }
+.moin-history-contenttype { width: 18%; }
+.moin-history-editorinfo { width: 17%; }
+.moin-history-comment { width: 30%; }
+.moin-action { width: 2%; }
+.moin-action a:hover { text-decoration: none; }
+.moin-history-container { border: 1px solid #4D7DA9; }
+.moin-history-container-header { background: #81BBF2; margin: 0px; padding: 4px; color: #3b3131; border-bottom: 1px solid #4D7DA9; }
+.moin-history-container-header h2 { display: inline; }
+.moin-history-container-header a.bookmark-link { margin-left: 10px; color: #3b3131; }
+.moin-history-container-body { padding: 4px; font-size: 14px; }
+.moin-history-save:before { content: url('../img/moin-edit.png'); }
+.moin-history-trash:before { content: url('../img/moin-deleted.png'); }
+.moin-history-rename:before { content: url('../img/moin-renamed.png'); }
+.moin-history-copy:before { content: url('../img/moin-new.png'); }
+.moin-integer { width: 2%; }
+.moin-history-links { width: 5%; }
+.moin-history-links a { display: block; margin-bottom: 4px; }
+.moin-history-editortext,
+.moin-history-links span,
+.moin-history-comment span { color: #544E4F; display: block; margin-bottom: 5px; }
+.moin-offset-links { float: right; margin-right: 20px; }
+.moin-offset-links a { margin-right: 10px; padding: 3px 7px; font-size: 20px; background: #FFFFFF; border: 1px groove #DDD; border-radius: 5px; }
+.moin-offset-links a:hover { box-shadow: 0px 0px 12px #81BBF2; }
+.moin-clr { clear: both; }
+
+/* item index page */
+#moin-content h1 { display: inline; }
+.moin-select-all { padding: 0.5em; color: #342D7E; background: #FFFFFF; border: 1px solid #E5E5E5; text-align: left; }
+.moin-select-actions { position: relative; margin: 0 1em; padding: 0; background: #FFFFFF; z-index: 2; white-space: nowrap; color: #342D7E; text-align: left; }
+.moin-select-actions div { margin: 0; padding: 0.5em; border: 1px groove #E5E5E5; }
+.moin-select-actions div:hover,
+.action-visible div { background: #4477FF; color: #FFFFFF; }
+.moin-select-actions .show-action { cursor: pointer; }
+.show-action:after { content: url("../img/moin-moveup.png"); margin: 0 0.2em; }
+.action-visible .show-action:after { content: url("../img/moin-movedown.png"); margin: 0 0.2em; }
+.moin-select-allitem { display: inline-block; cursor: default; text-align: left; }
+.allitem-selected:after { content: url("../img/moin-checkbox-on.png"); margin: 0 0.2em; }
+.allitem-toselect:after { content: url("../img/moin-checkbox-off.png"); margin: 0 0.2em; }
+.moin-select-actions ul { position: absolute; margin: 0; left: 0; top: 2em; padding: 0; display: none; background: #fff; border: 1px solid #E5E5E5; z-index: 1; }
+.moin-select-actions ul li { display: list-item; list-style-type: none; padding: 0.5em; min-width: 7em; cursor: pointer; }
+.moin-select-actions ul li:hover { background-color: #4477FF; color: #FFFFFF; }
+.moin-index-message { width: 50%; margin: 1em auto; text-align: center; display: none; }
+.moin-index-message span { padding: 4px; background-color: #FFFF00; color: #111111; }
+.moin-download-link { display: none; }
+#moin-initials { width: 90%; margin: 5px auto; text-align: center; }
+#moin-initials a { display: inline-block; margin: 0; padding: 4px 5px; }
+#moin-initials a:hover,
+#moin-initials a.selected { background: #4477FF; border-radius: 5px; color: #FFFFFF; text-decoration: none; }
+.moin-item-index { width: 100%; margin-left: 0.5em; }
+.moin-item-index div { float: left; width: 15em; }
+.moin-item-index div .moin-select-item { visibility: hidden; display: inline-block; width: 17px; cursor: default; background: transparent url("../img/moin-checkbox-off.png") no-repeat; }
+.moin-item-index div.selected-item .moin-select-item,
+.moin-item-index div:hover .moin-select-item { visibility: visible; }
+.moin-item-index div.selected-item .moin-select-item { background-image: url("../img/moin-checkbox-on.png"); }
+.moin-align-right { text-align: right; float: right; }
+.moin-align-right ul { margin: 0; padding: 0;  }
+.moin-align-right ul li.action-bar { list-style-type: none; display: inline-block; }
+.moin-contenttypes-wrapper { position: relative; margin: 0; color: #342D7E; background: #FFFFFF; border: 1px solid #E5E5E5; min-width: 12em; text-align: left; }
+.moin-contenttypes-wrapper div { cursor: pointer; margin: 0.1em; padding: 0.5em 1.2em 0.5em 0.5em ; height: 1em; } 
+div.ct-shown { background: #4477FF url("../img/moin-movedown.png") no-repeat center right; color: #FFFFFF; }
+div.ct-hide { background: transparent url("../img/moin-moveup.png") no-repeat center right; }
+.moin-contenttypes-wrapper ul { position: absolute; top: 1.9em; left: 0; display: none; margin: 0.3em 0; border-top: 1px solid #E5E5E5; z-index: 2; background: #FFFFFF; border: 1px solid #E5E5E5; } 
+.moin-contenttypes-wrapper ul li { list-style-type: none; padding: 0.5em; min-width: 11.5em; }
+.moin-contenttypes-wrapper ul li label { margin-left: 0.5em; }
+.moin-contenttypes-wrapper ul li .helper-text { font-size: 0.7em; color: #6E6A6B; display: none; }
+.moin-contenttypes-wrapper ul li:hover { background: #E5E5E5; }
+.moin-contenttypes-wrapper ul li:hover .helper-text { display: block; }
+.moin-contenttypes-wrapper ul li a { font-size: 80%; }
+.moin-contenttypes-wrapper form input[type="submit"] { margin: 0.4em 0.5em; }
+.moin-contenttypes-wrapper:hover div { background-color: #4477FF; color: #FFFFFF; } 
+.filter-toggle { margin: 0 0.2em; font-size: 90%; }
+.moin-more-index { background: transparent url("../img/moin-expand.png") no-repeat; display: inline-block; width: 20px; }
+.moin-more-index:hover { text-decoration: none; }
+.moin-index-path { margin-left: 0.5em; }
+.moin-index-path:before { content: url("../img/moin-parent.png"); margin: 0 0.3em; }
+.moin-path-separator { font-size: 120%; color: #4477FF; }
+.moin-index-separator { clear: both; border-top: 1px dashed #CCCCCC; width: 80%; display: none; }
+#moin-upload-cont { min-height: 10px; }
+#file_upload { margin-top: 2em; }
+form.upload_file { background-color: #4477FF; border: 1px solid #e5e5e5; color: #E5E5E5; cursor: pointer; direction: ltr; font-weight: bold; height: 2.5em; line-height: 2.5em; overflow: hidden; position: relative; text-align: center; width: 15em; box-shadow: 0px 0px 5px #4477FF; -moz-box-shadow: 0px 0px 5px #4477FF; khtml-box-shadow: 0px 0px 5px #4477FF; }
+form.upload_file:hover { color: #FFFFFF; }
+form.upload_file input { -moz-transform: translate(-800px, 0pt) scale(10); border: 300px solid transparent; cursor: pointer; height: 100%;  margin: 0; opacity: 0; position: absolute; right: 0; top: 0;}
+form.upload_file input { height: auto; }
+form.upload_file button { display: none;}
+form.upload_file { display: block; }
+.file_upload_template .file_upload_start { visibility: hidden; border-width: 0px; padding: 0px; }
+.file_upload_template .file_upload_start button { width: 0px; }
+.upload-form { display: none; }
+.moin-drag { font-size: 0.7em; color: #6C7680; }
+a.moin-conflict:before { content: url(../img/moin-conflict.png); margin: 0 0.2em; }
+
+/* popup */
+#popup { background: transparent url("../img/moin-transparent-bg.png") repeat; padding: 5px; width: 40%; position: absolute; top: 10%; left: 30%; display: none; z-index: 10; }
+.popup-header { background-color: #4477FF; color: #FFFFFF; font-size: 1em; padding: 10px; margin: 0; }
+.popup-closer { color: #FFFFFF; font-size: 1em; padding: 1px 4px; margin: 0; float: right; cursor: pointer; border: 1px solid #E5E5E5; }
+.popup-closer:hover { background-color: #F6F6F6; color: #4477FF; }
+.popup-body { clear: both; background-color: #FFFFFF; color: #111111; padding: 10px; margin: 0; }
+.popup-body label { margin: 5px; display: block; font-weight: bold; }
+.popup-body input { margin: 8px 5px; padding: 3px; border: 1px solid #E5E5E5; }
+.popup-body input[type="text"] { width: 300px; }
+.popup-body input.blank { border-color: #FF0000; border-width: 2px; }
+.popup-container { margin: 0; }
+#lightbox { background: #FFFFFF; opacity: 0.7; filter:alpha(opacity=70); position: fixed !important; position: absolute; left: 0; top: 0; width: 100%; height: 100%; z-index: 9; margin: 0; display: none; }
 
 /* diffs */
 .moin-diff { width:99%; table-layout: fixed; }
@@ -351,13 +454,15 @@
 
 /* icons for links to different mimetypes */
 /* major types */
-a.moin-mime-text:before {}
-a.moin-mime-image:before { content: url(../img/moin-ftp.png); margin: 0 0.2em; }
-a.moin-mime-audio:before { content: url(../img/moin-ftp.png); margin: 0 0.2em; }
-a.moin-mime-video:before { content: url(../img/moin-ftp.png); margin: 0 0.2em; }
-a.moin-mime-application:before { content: url(../img/moin-ftp.png); margin: 0 0.2em; }
+a.moin-mime-text:before { content: url(../img/moin-text.png); margin: 0 0.2em; }
+a.moin-mime-image:before { content: url(../img/moin-image.png); margin: 0 0.2em; }
+a.moin-mime-audio:before { content: url(../img/moin-audio.png); margin: 0 0.2em; }
+a.moin-mime-video:before { content: url(../img/moin-video.png); margin: 0 0.2em; }
+a.moin-mime-application:before { content: url(../img/moin-application.png); margin: 0 0.2em; }
 /* some common specific types */
-a.moin-mime-pdf:before { content: url(../img/moin-ftp.png); margin: 0 0.2em; }
+a.moin-mime-pdf:before { content: url(../img/moin-pdf.png); margin: 0 0.2em; }
+a.moin-mime-package:before { content: url(../img/moin-package.png); margin: 0 0.2em; }
+a.moin-mime-drawing:before { content: url(../img/moin-drawing.png); margin: 0 0.2em; }
 
 /* Flash messages used by Flask */
 .moin-flash { margin: 0; padding: 6px 6px 6px 38px; background-color: #f0f2f5;
Binary file MoinMoin/themes/modernized/static/img/moin-application.png has changed
Binary file MoinMoin/themes/modernized/static/img/moin-audio.png has changed
Binary file MoinMoin/themes/modernized/static/img/moin-checkbox-off.png has changed
Binary file MoinMoin/themes/modernized/static/img/moin-checkbox-on.png has changed
Binary file MoinMoin/themes/modernized/static/img/moin-drawing.png has changed
Binary file MoinMoin/themes/modernized/static/img/moin-expand.png has changed
Binary file MoinMoin/themes/modernized/static/img/moin-image.png has changed
Binary file MoinMoin/themes/modernized/static/img/moin-movedown.png has changed
Binary file MoinMoin/themes/modernized/static/img/moin-moveup.png has changed
Binary file MoinMoin/themes/modernized/static/img/moin-package.png has changed
Binary file MoinMoin/themes/modernized/static/img/moin-pdf.png has changed
Binary file MoinMoin/themes/modernized/static/img/moin-text.png has changed
Binary file MoinMoin/themes/modernized/static/img/moin-transparent-bg.png has changed
Binary file MoinMoin/themes/modernized/static/img/moin-video.png has changed
--- a/MoinMoin/user.py	Mon Aug 22 15:41:27 2011 +0530
+++ b/MoinMoin/user.py	Mon Aug 22 19:46:03 2011 +0530
@@ -30,7 +30,7 @@
 
 from MoinMoin import config, wikiutil
 from MoinMoin.i18n import _, L_, N_
-from MoinMoin.util.interwiki import getInterwikiHome, is_local_wiki
+from MoinMoin.util.interwiki import getInterwikiHome, getInterwikiName, is_local_wiki
 from MoinMoin.util.crypto import crypt_password, upgrade_password, valid_password, \
                                  generate_token, valid_token
 
@@ -454,8 +454,7 @@
         :param tm: timestamp
         """
         if self.valid:
-            interwikiname = self._cfg.interwikiname or u''
-            self.bookmarks[interwikiname] = int(tm)
+            self.bookmarks[self._cfg.interwikiname] = int(tm)
             self.save()
 
     def getBookmark(self):
@@ -465,10 +464,9 @@
         :returns: bookmark timestamp or None
         """
         bm = None
-        interwikiname = self._cfg.interwikiname or u''
         if self.valid:
             try:
-                bm = self.bookmarks[interwikiname]
+                bm = self.bookmarks[self._cfg.interwikiname]
             except (ValueError, KeyError):
                 pass
         return bm
@@ -479,10 +477,9 @@
         :rtype: int
         :returns: 0 on success, 1 on failure
         """
-        interwikiname = self._cfg.interwikiname or u''
         if self.valid:
             try:
-                del self.bookmarks[interwikiname]
+                del self.bookmarks[self._cfg.interwikiname]
             except KeyError:
                 return 1
             self.save()
@@ -518,9 +515,8 @@
 
         import re
         # Create a new list with both names and interwiki names.
-        pages = pagelist[:]
-        if self._cfg.interwikiname:
-            pages += [self._interWikiName(pagename) for pagename in pagelist]
+        pages = pagelist[:] # TODO: get rid of non-interwiki subscriptions?
+        pages += [getInterwikiName(pagename) for pagename in pagelist]
         # Create text for regular expression search
         text = '\n'.join(pages)
 
@@ -549,16 +545,12 @@
         :rtype: bool
         :returns: if page was subscribed
         """
-        if self._cfg.interwikiname:
-            pagename = self._interWikiName(pagename)
-
+        pagename = getInterwikiName(pagename)
         if pagename not in self.subscribed_items:
             self.subscribed_items.append(pagename)
             self.save()
-
             # XXX SubscribedToPageEvent
             return True
-
         return False
 
     def unsubscribe(self, pagename):
@@ -585,7 +577,7 @@
             self.subscribed_items.remove(pagename)
             changed = True
 
-        interWikiName = self._interWikiName(pagename)
+        interWikiName = getInterwikiName(pagename)
         if interWikiName and interWikiName in self.subscribed_items:
             self.subscribed_items.remove(interWikiName)
             changed = True
@@ -618,7 +610,7 @@
         for pagename in pagelist:
             if pagename in self.quicklinks:
                 return True
-            interWikiName = self._interWikiName(pagename)
+            interWikiName = getInterwikiName(pagename)
             if interWikiName and interWikiName in self.quicklinks:
                 return True
 
@@ -636,7 +628,7 @@
         :returns: if pagename was added
         """
         changed = False
-        interWikiName = self._interWikiName(pagename)
+        interWikiName = getInterwikiName(pagename)
         if interWikiName:
             if pagename in self.quicklinks:
                 self.quicklinks.remove(pagename)
@@ -664,7 +656,7 @@
         :returns: if pagename was removed
         """
         changed = False
-        interWikiName = self._interWikiName(pagename)
+        interWikiName = getInterwikiName(pagename)
         if interWikiName and interWikiName in self.quicklinks:
             self.quicklinks.remove(interWikiName)
             changed = True
@@ -676,17 +668,6 @@
             self.save()
         return changed
 
-    def _interWikiName(self, pagename):
-        """ Return the inter wiki name of a page name
-
-        :param pagename: page name
-        :type pagename: unicode
-        """
-        if not self._cfg.interwikiname:
-            return None
-
-        return "%s:%s" % (self._cfg.interwikiname, pagename)
-
     # -----------------------------------------------------------------
     # Trail
 
@@ -695,9 +676,7 @@
 
         :param item_name: the item name (unicode) to add to the trail
         """
-        # Save interwiki links internally
-        if self._cfg.interwikiname:
-            item_name = self._interWikiName(item_name)
+        item_name = getInterwikiName(item_name)
         trail_in_session = session.get('trail', [])
         trail = trail_in_session[:]
         trail = [i for i in trail if i != item_name] # avoid dupes
--- a/MoinMoin/util/__init__.py	Mon Aug 22 15:41:27 2011 +0530
+++ b/MoinMoin/util/__init__.py	Mon Aug 22 19:46:03 2011 +0530
@@ -82,3 +82,35 @@
         return pattern[1:-1]
     return pattern[1:]
 
+def getPageContent(results, offset, results_per_page):
+    """ Selects the content to show on a single page
+        :param results: the whole result, from which results for one page will be selected (generally a generator but could be a list also),
+        :param offset: after skipping how many results, the selection of results for that page will be done (int),
+        :param results_per_page: number of results to be shown on a single page (int)
+
+        :rtype: tuple
+        :returns: selected_result (list),
+                  offset for next page (If 0 then no next page),
+                  offset for previous page (If less than 0, then no previous page)
+    """
+    count = 0
+    maxcount = offset + results_per_page
+    nextPage = False
+    selected_result = []
+    for result in results:
+        if count < offset:
+            count += 1
+        elif results_per_page and count == maxcount:
+            nextPage = True
+            break
+        else:
+            selected_result.append(result)
+            count += 1
+    if not nextPage:
+        count = 0
+    if results_per_page and offset:
+        previous_offset = max(offset - results_per_page, 0)
+    else:
+        previous_offset = -1
+    next_offset = count
+    return (selected_result, next_offset, previous_offset)
--- a/MoinMoin/util/interwiki.py	Mon Aug 22 15:41:27 2011 +0530
+++ b/MoinMoin/util/interwiki.py	Mon Aug 22 19:46:03 2011 +0530
@@ -122,6 +122,17 @@
         return wikiurl + wikitail
 
 
+def getInterwikiName(item_name):
+    """
+    Get the (fully qualified) interwiki name of a local item name.
+
+    :param item_ame: item name (unicode)
+    :rtype: unicode
+    :returns: wiki_name:item_name
+    """
+    return "%s:%s" % (app.cfg.interwikiname, item_name)
+
+
 def getInterwikiHome(username):
     """
     Get a user's homepage.
--- a/MoinMoin/util/monkeypatch.py	Mon Aug 22 15:41:27 2011 +0530
+++ b/MoinMoin/util/monkeypatch.py	Mon Aug 22 19:46:03 2011 +0530
@@ -1,4 +1,5 @@
 # Copyright: 2010 MoinMoin:ThomasWaldmann
+# Copyright: 2011 MoinMoin:AkashSinha
 # License: the individual patches have same license as the code they are patching
 
 """
@@ -30,3 +31,9 @@
 import sys
 posixemulation.sys = sys
 
+# collections patching for the class OrderedDict for the python versions < 2.7
+import collections
+if "OrderedDict" not in dir(collections):
+    from sqlalchemy.util import OrderedDict
+    collections.OrderedDict = OrderedDict
+
--- a/quickinstall	Mon Aug 22 15:41:27 2011 +0530
+++ b/quickinstall	Mon Aug 22 19:46:03 2011 +0530
@@ -4,17 +4,18 @@
 
 DIR=env
 PYTHON=python
+DLC=dlc
 
 virtualenv --no-site-packages --python $PYTHON $DIR
 
 source $DIR/bin/activate
 
 # first install babel, moin's setup.py will emit a warning if it is not there
-pip install babel
+pip install --download-cache=$DLC babel
 
 # "install" moin2 from repo to the env, this will also install required python
 # packages from pypi. we do this LAST, so that breakage is better visible.
-pip install -e .
+pip install --download-cache=$DLC -e .
 
 # compile the translations
 python setup.py compile_catalog --statistics
--- a/quickinstall.bat	Mon Aug 22 15:41:27 2011 +0530
+++ b/quickinstall.bat	Mon Aug 22 19:46:03 2011 +0530
@@ -10,10 +10,10 @@
 call env\Scripts\activate.bat
 
 echo Installing babel first ...
-pip install babel
+pip install --download-cache=dlc babel
 
 echo Installing all required python packages from pypi ...
-pip install -e .
+pip install --download-cache=dlc -e .
 
 echo Compiling translations (not required if wiki is English only) ...
 python setup.py compile_catalog --statistics
--- a/setup.py	Mon Aug 22 15:41:27 2011 +0530
+++ b/setup.py	Mon Aug 22 19:46:03 2011 +0530
@@ -99,6 +99,7 @@
         'XStatic-TWikiDraw-moin>=2004.10.23.2',
         'XStatic-AnyWikiDraw>=0.14.2',
         'XStatic-svg-edit-moin>=2011.07.07.2',
+        'XStatic-multiDownload>=20110717.1',
     ],
     # optional features and their list of requirements
     extras_require = {
--- a/wikiconfig.py	Mon Aug 22 15:41:27 2011 +0530
+++ b/wikiconfig.py	Mon Aug 22 19:46:03 2011 +0530
@@ -12,7 +12,6 @@
     # vvv DON'T TOUCH THIS EXCEPT IF YOU KNOW WHAT YOU DO vvv
     # Directory containing THIS wikiconfig:
     wikiconfig_dir = os.path.abspath(os.path.dirname(__file__))
-    interwikiname = u'MoinMoin2'
     # We assume this structure for a simple "unpack and run" scenario:
     # wikiconfig.py
     # wiki/
@@ -46,15 +45,16 @@
                                              after=u'', ),
                             )
 
+    sitename = u'My MoinMoin'
+
+    # it is required that you set this to a unique, stable and non-empty name:
+    interwikiname = u'MyMoinMoin'
     # Load the interwiki map from intermap.txt:
     interwiki_map = InterWikiMap.from_file(os.path.join(wikiconfig_dir, 'contrib', 'interwiki', 'intermap.txt')).iwmap
     # we must add entries for 'Self' and our interwikiname:
-    #interwikiname = 'MyInterWikiName'
-    #interwiki_map[interwikiname] = 'http://localhost:8080/'
+    interwiki_map[interwikiname] = 'http://localhost:8080/'
     interwiki_map['Self'] = 'http://localhost:8080/'
 
-    sitename = u'My MoinMoin'
-
     # for now we load some 3rd party stuff from the place within moin where it is currently located,
     # but soon we'll get rid of this stuff:
     env_dir = 'env'
@@ -65,7 +65,7 @@
     # we slowly migrate all stuff from above (old) method, to xstatic (new) method,
     # see https://bitbucket.org/thomaswaldmann/xstatic for details:
     from xstatic.main import XStatic
-    mod_names = ['jquery', 'jquery_file_upload', 'ckeditor', 'svgweb', 'svgedit_moin', 'twikidraw_moin', 'anywikidraw', ]
+    mod_names = ['jquery', 'jquery_file_upload', 'ckeditor', 'svgweb', 'svgedit_moin', 'twikidraw_moin', 'anywikidraw', 'jquery_multi_download', ]
     pkg = __import__('xstatic.pkg', fromlist=mod_names)
     for mod_name in mod_names:
         mod = getattr(pkg, mod_name)