def execute(hdf, args, env): authname = hdf.getValue("trac.authname", "anonymous") db = env.get_db_cnx() perm = trac.perm.PermissionCache(db, authname) pagename = hdf.getValue("args.page", "WikiStart") page = WikiPage(pagename, None, perm, db) wikipreview = hdf.getValue("args.preview", "") appendonly = (args == 'appendonly') readonlypage = int(hdf.getValue("wiki.readonly", "0")) # Can this user add a comment to this page? cancomment = not readonlypage # Is this an "append-only" comment or are we an administrator? if perm.has_permission(trac.perm.WIKI_ADMIN) or appendonly: cancomment = True if not cancomment: raise TracError('Error: Insufficient privileges to AddComment') disabled = '' comment = hdf.getValue("args.addcomment", "") preview = hdf.getValue("args.previewaddcomment", "") cancel = hdf.getValue("args.canceladdcomment", "") submit = hdf.getValue("args.submitaddcomment", "") if not cancel: authname = hdf.getValue("args.authoraddcomment", authname) # Ensure [[AddComment]] is not present in comment, so that infinite # recursion does not occur. comment = re.sub('(^|[^!])(\[\[AddComment)', '\\1!\\2', comment) out = StringIO() if wikipreview or not (perm.has_permission(trac.perm.WIKI_MODIFY) or appendonly): disabled = ' disabled="disabled"' # If we are submitting or previewing, inject comment as it should look if cancomment and comment and (preview or submit): if preview: out.write("<div class='wikipage' id='preview'>\n") out.write("<h4 id='commentpreview'>Comment by %s on %s</h4>\n<p>\n%s\n</p>\n" % (authname, time.strftime('%c', time.localtime()), wiki_to_html(comment, hdf, env, db))) if preview: out.write("</div>\n") # When submitting, inject comment before macro if comment and submit: submitted = False newtext = StringIO() for line in page.text.splitlines(): if line.find('[[AddComment') == 0: newtext.write("==== Comment by %s on %s ====\n%s\n\n" % (authname, time.strftime('%c', time.localtime()), comment)) submitted = True newtext.write(line + "\n") if submitted: # XXX Is this the dodigest hack ever? This is needed in # "appendonly" mode when the page is readonly. XXX if appendonly: perm.expand_meta_permission('WIKI_ADMIN'); page.set_content(newtext.getvalue()) # TODO: How do we get remote_addr from a macro? page.commit(authname, 'Comment added', None) comment = "" else: out.write("<div class='system-message'><strong>ERROR: [[AddComment]] macro call must be the only content on its line. Could not add comment.</strong></div>\n") out.write("<form action='%s#commentpreview' method='post'>\n" % env.href.wiki(pagename)) out.write("<fieldset>\n<legend>Add comment</legend>\n") out.write("<div class='field'>\n<textarea id='addcomment' name='addcomment' cols='80' rows='5'%s>" % disabled) if wikipreview: out.write("Page preview...") elif not cancel: out.write(comment) out.write("</textarea>\n") out.write("</div>\n") out.write('<div class="field">\n<label for="authoraddcomment">Your email or username:</label>\n<br/><input id="authoraddcomment" type="text" name="authoraddcomment" size="30" value="%s" />\n</div>' % authname) out.write("<div class='field'>\n<input size='30' type='submit' name='submitaddcomment' value='Add comment'%s/>\n" % disabled) out.write("<input type='submit' name='previewaddcomment' value='Preview comment'%s/>\n" % disabled) out.write("<input type='submit' name='canceladdcomment' value='Cancel'%s/>\n</div>\n" % disabled) out.write("<script type='text/javascript'>\naddWikiFormattingToolbar(document.getElementById('addcomment'));\n</script>\n") out.write("</fieldset>\n</form>\n") return out.getvalue()# + "<pre>" + hdf.dump() + "</pre>"
def execute(hdf, template, env): out = StringIO() errors = [] authname = hdf.getValue("trac.authname", "anonymous") if not template: raise TracError("No template page supplied") if authname == "anonymous": errors.append( 'You need to <a href="%s">register</a> then <a href="%s">login</a> in order to create a new hack.' % (hdf.getValue("trac.href.registration", ""), hdf.getValue("trac.href.login", ""))) db = env.get_db_cnx() cursor = db.cursor() # Fetch meta-data from tags META_TAGS = [] cursor.execute("SELECT name FROM wiki_namespace WHERE namespace=%s", 'metatag') for tag in cursor.fetchall(): tag = tag[0] cursor.execute("SELECT name FROM wiki_namespace WHERE namespace=%s", tag) META_TAGS += [x[0] for x in cursor.fetchall()] cursor.execute("SELECT name FROM wiki_namespace WHERE namespace=%s", 'type') TYPES = [x[0] for x in cursor.fetchall()] cursor.execute("SELECT name FROM wiki_namespace WHERE namespace=%s", 'release') RELEASES = [x[0] for x in cursor.fetchall()] page_name = hdf.getValue('args.name', '') if not page_name.lower().endswith(hdf.getValue('args.type', '')): page_name += hdf.getValue('args.type', '').title() page_title = hdf.getValue('args.title', '') page_description = hdf.getValue('args.description', '') page_example = hdf.getValue('args.example', '') page_type = hdf.getValue('args.type', 'macro') page_tags = get_branch_values(hdf, 'args.tags') page_releases = get_branch_values(hdf, 'args.releases') page_preview = hdf.getValue('args.previewhack', '') page_create = hdf.getValue('args.createhack', '') def write_tags(out, tags, checked=(), name="tags", type="checkbox"): count = 0 for tag in sorted(tags): if tag[0].isupper(): continue (linktext, title, desc) = getInfo(db, tag) link = env.href.wiki(tag) check = "" if tag in checked: check = " checked" out.write( '<input type="%s" name="%s" value="%s"%s/> <a href="%s" title="%s">%s</a> \n' % (type, name, tag, check, link, title, tag)) count += 1 if count % 8 == 0: out.write("<br/>\n") return count # Validation if page_preview or page_create: try: fetch_page(cursor, page_name) except: pass else: errors.append("Page name %s already exists" % page_name) if not re.match('^([A-Z][a-z]+){2,}$', page_name): errors.append( 'Invalid WikiName, only alpha characters are accepted and must be CamelCase' ) if not page_name: errors.append("No WikiName provided") if not page_title: errors.append("No page title provided") if not page_type: errors.append('No page type selected') if not page_description: errors.append("No description provided") if not page_example: errors.append("No example provided") if not page_releases: errors.append("No releases selected") if page_create and not errors: repos_dir = env.get_config('trac', 'repository_dir') pool, rep, fs_ptr = open_svn_repos(repos_dir) rev = svn.fs.youngest_rev(fs_ptr, pool) root = svn.fs.revision_root(fs_ptr, rev, pool) node_type = svn.fs.check_path(root, page_name.lower(), pool) cursor.execute("SELECT name FROM component WHERE name='%s'" % page_name) row = cursor.fetchone() if row: errors.append("Component '%s' already exists" % page_name) if node_type: errors.append("Repository path '%s' already exists" % page_name.lower()) if not os.access(SVN_PERMISSIONS, os.W_OK): errors.append("Can't write to Subversion permissions file") lockfile = open("/var/tmp/newhack.lock", "w") try: rv = fcntl.flock(lockfile, fcntl.LOCK_EX | fcntl.LOCK_NB) if rv: errors.append( 'Failed to acquire lock, received error code %i' % rv) except IOError: errors.append( 'A hack is currently being created by another user. Try again later.' ) if not errors: try: # Insert component cursor.execute( 'INSERT INTO component (name, owner) VALUES (%s, %s)', page_name, authname) # Create page perm = trac.perm.PermissionCache(db, authname) page = WikiPage(page_name, None, perm, db) page.set_content( expand_vars(fetch_page(cursor, template), generate_vars(hdf))) out.write('Created wiki page.<br>\n') # Creating SVN paths paths = ['%s%s' % (SVN_LOCAL_PATH, page_name.lower())] for release in page_releases: paths.append("%s%s/%s" % (SVN_LOCAL_PATH, page_name.lower(), release)) output = os.popen( 'umask 775; /usr/bin/op create-hack %s "New hack %s, created by %s" %s 2>&1' % (authname, page_name, authname, ' '.join(paths))).readlines() if output: raise Exception( "Failed to create Subversion paths:\n<blockquote>%s</blockquote>" % ''.join(output)) out.write("Created SVN layout.<br>\n") # Add SVN permissions perms = open(SVN_PERMISSIONS, "a") perms.write("\n[/%s]\n%s = rw\n" % (page_name.lower(), authname)) out.write('Added SVN write permission.<br>\n') out.write('\nFinished.<p><h1>Hack Details</h1>\n') for release in page_releases: svnpath = "%s%s/%s" % (SVN_URL, page_name.lower(), release) out.write( 'The Subversion repository path for %s is <a href="%s">%s</a>.<br>\n' % (release, svnpath, svnpath)) out.write( 'The page for your hack is <a href="%s">%s</a>.<br>\n' % (env.href.wiki(page_name), page_name)) page.commit( authname, 'New hack %s, created by %s' % (page_name, authname), None) rv = fcntl.flock(lockfile, fcntl.LOCK_UN) return out.getvalue() except Exception, e: # TODO Roll back changes to SVN_PERMISSIONS file cursor.execute("ROLLBACK") rv = fcntl.flock(lockfile, fcntl.LOCK_UN) raise TracError(e)
def execute(hdf, template, env): out = StringIO() errors = [] authname = hdf.getValue("trac.authname", "anonymous") if not template: raise TracError("No template page supplied") if authname == "anonymous": errors.append('You need to <a href="%s">register</a> then <a href="%s">login</a> in order to create a new hack.' % (hdf.getValue("trac.href.registration", ""), hdf.getValue("trac.href.login", ""))) db = env.get_db_cnx() cursor = db.cursor() # Fetch meta-data from tags META_TAGS = [] cursor.execute("SELECT name FROM wiki_namespace WHERE namespace=%s", 'metatag') for tag in cursor.fetchall(): tag = tag[0] cursor.execute("SELECT name FROM wiki_namespace WHERE namespace=%s", tag) META_TAGS += [x[0] for x in cursor.fetchall()] cursor.execute("SELECT name FROM wiki_namespace WHERE namespace=%s", 'type') TYPES = [x[0] for x in cursor.fetchall()] cursor.execute("SELECT name FROM wiki_namespace WHERE namespace=%s", 'release') RELEASES = [x[0] for x in cursor.fetchall()] page_name = hdf.getValue('args.name', '') if not page_name.lower().endswith(hdf.getValue('args.type', '')): page_name += hdf.getValue('args.type', '').title() page_title = hdf.getValue('args.title', '') page_description = hdf.getValue('args.description', '') page_example = hdf.getValue('args.example', '') page_type = hdf.getValue('args.type', 'macro') page_tags = get_branch_values(hdf, 'args.tags') page_releases = get_branch_values(hdf, 'args.releases') page_preview = hdf.getValue('args.previewhack', '') page_create = hdf.getValue('args.createhack', '') def write_tags(out, tags, checked = (), name = "tags", type="checkbox"): count = 0 for tag in sorted(tags): if tag[0].isupper(): continue (linktext,title,desc) = getInfo(db,tag) link = env.href.wiki(tag) check = "" if tag in checked: check = " checked" out.write('<input type="%s" name="%s" value="%s"%s/> <a href="%s" title="%s">%s</a> \n' % (type, name, tag, check, link, title, tag)) count += 1 if count % 8 == 0: out.write("<br/>\n") return count # Validation if page_preview or page_create: try: fetch_page(cursor, page_name) except: pass else: errors.append("Page name %s already exists" % page_name) if not re.match('^([A-Z][a-z]+){2,}$', page_name): errors.append('Invalid WikiName, only alpha characters are accepted and must be CamelCase') if not page_name: errors.append("No WikiName provided") if not page_title: errors.append("No page title provided") if not page_type: errors.append('No page type selected') if not page_description: errors.append("No description provided") if not page_example: errors.append("No example provided") if not page_releases: errors.append("No releases selected") if page_create and not errors: repos_dir = env.get_config('trac', 'repository_dir') pool, rep, fs_ptr = open_svn_repos(repos_dir) rev = svn.fs.youngest_rev(fs_ptr, pool) root = svn.fs.revision_root(fs_ptr, rev, pool) node_type = svn.fs.check_path(root, page_name.lower(), pool) cursor.execute("SELECT name FROM component WHERE name='%s'" % page_name) row = cursor.fetchone() if row: errors.append("Component '%s' already exists" % page_name) if node_type: errors.append("Repository path '%s' already exists" % page_name.lower()) if not os.access(SVN_PERMISSIONS, os.W_OK): errors.append("Can't write to Subversion permissions file") lockfile = open("/var/tmp/newhack.lock", "w") try: rv = fcntl.flock(lockfile, fcntl.LOCK_EX | fcntl.LOCK_NB) if rv: errors.append('Failed to acquire lock, received error code %i' % rv) except IOError: errors.append('A hack is currently being created by another user. Try again later.') if not errors: try: # Insert component cursor.execute('INSERT INTO component (name, owner) VALUES (%s, %s)', page_name, authname) # Create page perm = trac.perm.PermissionCache(db, authname) page = WikiPage(page_name, None, perm, db) page.set_content(expand_vars(fetch_page(cursor, template), generate_vars(hdf))) out.write('Created wiki page.<br>\n') # Creating SVN paths paths = ['%s%s' % (SVN_LOCAL_PATH, page_name.lower())] for release in page_releases: paths.append("%s%s/%s" % (SVN_LOCAL_PATH, page_name.lower(), release)) output = os.popen('umask 775; /usr/bin/op create-hack %s "New hack %s, created by %s" %s 2>&1' % (authname, page_name, authname, ' '.join(paths))).readlines() if output: raise Exception("Failed to create Subversion paths:\n<blockquote>%s</blockquote>" % ''.join(output)) out.write("Created SVN layout.<br>\n") # Add SVN permissions perms = open(SVN_PERMISSIONS, "a") perms.write("\n[/%s]\n%s = rw\n" % (page_name.lower(), authname)) out.write('Added SVN write permission.<br>\n') out.write('\nFinished.<p><h1>Hack Details</h1>\n') for release in page_releases: svnpath = "%s%s/%s" % (SVN_URL, page_name.lower(), release) out.write('The Subversion repository path for %s is <a href="%s">%s</a>.<br>\n' % (release, svnpath, svnpath)) out.write('The page for your hack is <a href="%s">%s</a>.<br>\n' % (env.href.wiki(page_name), page_name)) page.commit(authname, 'New hack %s, created by %s' % (page_name, authname), None) rv = fcntl.flock(lockfile, fcntl.LOCK_UN) return out.getvalue() except Exception, e: # TODO Roll back changes to SVN_PERMISSIONS file cursor.execute("ROLLBACK"); rv = fcntl.flock(lockfile, fcntl.LOCK_UN) raise TracError(e)