Esempio n. 1
0
def categories(req):
	(uid, uname, editable) = jotools.get_login_user(req)
	if not editable:
		joheaders.error_page(req, _(u'You are not allowed to edit data'))
		return '\n'
	db = jodb.connect()
	results = db.query("SELECT coalesce(info, ''), count(*) FROM raw_word " +
	                   "WHERE processed = FALSE " +
	                   "GROUP BY coalesce(info, '') " +
	                   "ORDER BY coalesce(info, '') ")
	if results.ntuples() == 0:
		joheaders.error_page(req, _(u'There are no words to be added'))
		return '\n'
	joheaders.page_header_navbar_level1(req, _(u"Add words"), uid, uname)
	jotools.write(req, u"<p>%s:</p>\n" \
	                   % _(u'Choose a category from which you want to add words'))
	jotools.write(req, u"<table><tr><th>%s</th><th>%s</th></tr>\n" \
	                   % (_(u'Category'), _(u'Words left')))
	for result in results.getresult():
		cat = unicode(result[0], 'UTF-8')
		if cat == u'': cats = u'(' + _(u'no category') + u')'
		else: cats = cat
		jotools.write(req, (u'<tr><td><a href="add_from_db?category=%s">%s</a></td>' +
		                    u'<td>%i</td></tr>\n') \
		  % (jotools.escape_url(result[0]), jotools.escape_html(cats), result[1]))
	jotools.write(req, u"</table>\n")
	jotools.write(req, u'<p><a href="add_from_db">%s ...</a></p>\n' % _(u'All words'))
	joheaders.page_footer_plain(req)
	return '\n'
Esempio n. 2
0
def _html(req, db, query):
	offset_s = `jotools.toint(jotools.get_param(req, 'offset', u'0'))`
	limit_s = `jotools.toint(jotools.get_param(req, 'limit', u'200'))`
	if limit_s == u'0': limit_s = u'ALL'
	
	param_s = u''
	for field in req.form.list:
		if not field.name in ['limit', 'offset'] and jotools.checkid(field.name):
			param_s = param_s + field.name + u'=' + jotools.get_param(req, field.name, u'') + u'&'
	
	results = db.query("%s LIMIT %s OFFSET %s" % (query, limit_s, offset_s))
	if results.ntuples() == 0:
		joheaders.error_page(req, _(u'No matching words were found'))
		return "\n"
	elif results.ntuples() == 1:
		joheaders.redirect_header(req, _config.WWW_ROOT_DIR + "/word/edit?wid=%i" \
		                               % results.getresult()[0][0])
		return "\n"
	else:
		(uid, uname, editable) = jotools.get_login_user(req)
		joheaders.page_header_navbar_level1(req, _('Search results'), uid, uname)
		jotools.write(req, u'<table><tr><th>%s</th><th>%s</th></tr>\n' \
		                   % (_("Word"), _("Word class")))
		for result in results.getresult():
			jotools.write(req, _print_html_line(db, result[0],
			              unicode(result[1], 'UTF-8'),
				    unicode(result[2], 'UTF-8')))
		jotools.write(req, u"</table>\n")
		if not limit_s == u'ALL' and results.ntuples() == jotools.toint(limit_s):
			jotools.write(req, (u'<p><a href="wlist?%soffset=%i&limit=%s">' +
			              u"%s ...</a></p>\n") % (param_s, int(offset_s)+int(limit_s),
				    limit_s, _(u'More results')))	
	joheaders.page_footer_plain(req)
	return '\n'
Esempio n. 3
0
def passwdform(req):
	(uid, uname, editable) = jotools.get_login_user(req)
	if uid == None:
		joheaders.error_page(req, _(u'You must be logged in to do this'))
		return '\n'
	joheaders.page_header_navbar_level1(req, _(u'Change password'), uid, uname)
	jotools.write(req, u'''
<form method="post" action="changepasswd">
<table>
<tr><td>%s</td><td><input type="password" name="oldpw" /></td></tr>
<tr><td>%s</td><td><input type="password" name="newpw" /></td></tr>
</table>
<input type="submit" value="%s" />
</form>
'''        % (_(u'Old password'), _(u'New password'), _(u'Change password')))
	joheaders.page_footer_plain(req)
	return '\n'
Esempio n. 4
0
def add_manual(req):
	(uid, uname, editable) = jotools.get_login_user(req)
	if not editable:
		joheaders.error_page(req, _(u'You are not allowed to edit data'))
		return '\n'
	if req.method != 'GET':
		joheaders.error_page(req, _(u'Only GET requests are allowed'))
		return '\n'
	db = jodb.connect()
	words_per_page = 15
	joheaders.page_header_navbar_level1(req, _(u"Add words"), uid, uname)
	jotools.write(req, u'<form method="post" action="add">\n' +
	                   u'<table class="border">\n<tr><th>%s</th><th>%s</th></tr>\n' \
	                   % (_(u'Word'), _(u'Word class')))
	_add_entry_fields(req, db, None, words_per_page)
	jotools.write(req, u'</table>\n' +
	                   u'<p><input type="submit" value="%s"></p></form>\n' % _(u"Add words"))
	joheaders.page_footer_plain(req)
	return '\n'
Esempio n. 5
0
def _print_error_forbidden(req):
	"Print an error, if adding new words is no longer possible"
	jotools.write(req, u'''
<p>Et voi (enää) ehdottaa uusia lisättäviä sanoja. Tarkista seuraavat asiat:</p>
<ul>
<li>Oletko jo ehdottanut 20 sanaa tämän päivän aikana? Väärinkäytösten estämiseksi
rekisteröitymättömät käyttäjät eivät voi tehdä enempää ehdotuksia yhden vuorokauden
aikana. Jos sinulla on enemmän ehdotuksia lisättäviksi tai poistettaviksi sanoiksi,
yritä huomenna uudelleen, tai lähetä ehdotuksesi sähköpostitse yhteystiedoissa mainittuun
osoitteeseen.</li>
<li>Onko joku muu käyttänyt tänään tätä palvelua samalta koneelta kuin sinä, tai onko
Internet-selaimesi asetettu käyttämään välityspalvelinta? Rekisteröitymättömien käyttäjien
rajoitukset tehdään koneen ip-osoitteen perusteella, joten joku muu on
ehkä jo käyttänyt päivittäisen lisäyskiintiösi. Pahoittelemme ongelmaa, mutta meillä ei
ole mahdollisuutta käyttää älykkäämpiä rajoitusmenetelmiä. Voit lähettää lisäysehdotuksesi
sähköpostitse.</li>
</ul>
<p>Jos sinulla on käyttäjätunnus Joukahaiseen, kirjautumalla sisään pääset käyttämään
tätä palvelua rajoituksetta. Rekisteröityneiden käyttäjien tulisi kuitenkin mieluummin
lisätä sanat suoraan sanastotietokantaan.</p>''')
Esempio n. 6
0
def addform(req):
	(uid, uname, editable) = jotools.get_login_user(req)
	if not jotools.is_admin(uid):
		joheaders.error_page(req, _(u'You must be an administrator to do this'))
		return '\n'
	joheaders.page_header_navbar_level1(req, _(u'Add user'), uid, uname)
	jotools.write(req, u'''
<form method="post" action="add">
<table>
<tr><td>%s</td><td><input type="text" name="firstname" /></td></tr>
<tr><td>%s</td><td><input type="text" name="lastname" /></td></tr>
<tr><td>%s</td><td><input type="text" name="uname" /></td></tr>
<tr><td>%s</td><td><input type="text" name="email" /></td></tr>
<tr><td>%s</td><td><input type="text" name="passwd" /></td></tr>
</table>
<input type="submit" value="%s" />
</form>
'''        % (_(u'First name'), _(u'Last name'), _(u'Username'), _(u'Email address'),
              _(u'Password'), _(u'Add user')))
	joheaders.page_footer_plain(req)
	return '\n'
Esempio n. 7
0
def _page_header_internal(req, title, h1, uid, uname, wid):
	req.content_type = "text/html; charset=UTF-8"
	req.send_http_header()
	jotools.write(req, u"""<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="fi" lang="fi">
<head>
<title>%s</title>
<link rel="stylesheet" type="text/css" href="%s/style.css" />
<link rel="icon" type="image/png" href="%s/joukahainen-small.png" />
<link rel="search" type="application/opensearchdescription+xml"
 title="Joukahainen" href="%s/searchplugin-fullsearch-re.xml" />
<script type="text/javascript" src="%s/jscripts.js"></script>
</head>
<body onload="initPage()">
<div class="topbar">""" % (title, _config.WWW_ROOT_DIR, _config.WWW_ROOT_DIR,
                           _config.WWW_ROOT_DIR, _config.WWW_ROOT_DIR))
	jotools.write(req, u"\n<h1>%s</h1>" % h1)
	if uid == None:
		jotools.write(req, u"""
<div class="login">
<form method="post" action="%s/user/login"><p>
<label>%s: <input type="text" size="12" name="username" /></label>&nbsp;
<label>%s: <input type="password" size="12" name="password" /></label>&nbsp;
<input type="hidden" name="wid" value="%i" />
<input type="submit" value="%s" />
</p></form>
</div>
""" % (_config.WWW_ROOT_DIR, _(u'Username'), _(u'Password'), wid, _(u'Log in')))
	else:
		jotools.write(req, u"""
<div class="login">
<form method="post" action="%s/user/logout"><p>
<input type="hidden" name="wid" value="%i" />
<input type="submit" value="%s %s" />
</p></form>
</div>
""" % (_config.WWW_ROOT_DIR, wid, _(u'Log out user'), uname))
	jotools.write(req, u'<div class="clear"></div></div><div class="main">\n')
Esempio n. 8
0
def work(req):
	(uid, uname, editable) = jotools.get_login_user(req)
	if not editable:
		joheaders.error_page(req, _(u'You are not allowed to edit data'))
		return '\n'
	tid = jotools.toint(jotools.get_param(req, "tid", "0"))
	if tid == 0:
		joheaders.error_page(req, _(u'Parameter %s is required') % u'tid')
		return '\n'
	joheaders.frame_header(req, u"Joukahainen &gt; %s %i" % (_(u'task'), tid))
	jotools.write(req, u'<frameset cols="20%, 80%">\n')
	jotools.write(req, u'<frame name="left" src="show?tid=%i" />\n' % tid)
	jotools.write(req, u'<frame name="right" />\n')
	jotools.write(req, u'</frameset>\n')
	joheaders.frame_footer(req)
	return '\n'
Esempio n. 9
0
def index(req):
	db = jodb.connect()
	privdb = jodb.connect_private()
	(uid, uname, editable) = jotools.get_login_user(req)
	joheaders.page_header_navbar_level1(req, u"Ehdota uusia sanoja", uid, uname)
	
	word = jotools.get_param(req, "word", u"").strip()
	wtype = jotools.get_param(req, "type", u"").strip()
	comment = jotools.get_param(req, "comment", u"").strip()
	
	if word != u"":
		if not jotools.checkword(word):
			jotools.write(req, u'<p class="error">Sanassa on kiellettyjä merkkejä.</p>')
			_print_entry_form(req, db)
		else:
			db.query("BEGIN")
			error = _is_old_word(req, db, word)
			if error != None:
				jotools.write(req, u'<p class="error">%s</p>' % error)
				_print_entry_form(req, db)
			elif not (editable or _allow_new_word(req, privdb, True)):
				_print_error_forbidden(req)
			else:
				db.query("INSERT INTO raw_word(word, info, notes) " +
				         "VALUES('%s', '%s', '%s')" % \
				         (jotools.escape_sql_string(word),
				          jotools.escape_sql_string(wtype),
				          jotools.escape_sql_string(comment)))
				jotools.write(req, u'<p class="ok">Ehdotuksesi on tallennettu. ' +
				                   u'Kiitos avusta!</p>')
				_print_entry_form(req, db)
			db.query("COMMIT")
	
	elif editable or _allow_new_word(req, privdb, False):
		_print_entry_form(req, db)
	else:
		_print_error_forbidden(req)
	joheaders.page_footer_plain(req)
	return '\n'
Esempio n. 10
0
def _print_entry_form(req, db):
	"Prints an entry form for word suggestions"
	jotools.write(req, u'''<p>Joukahainen on Voikko-oikolukuohjelmiston kehittäjien
yhteinen sanastotietokanta. Sen avulla myös Voikon käyttäjät voivat auttaa kehittäjiä tekemään ohjelmasta
entistäkin paremman. Esimerkiksi LibreOfficea käyttäessäsi saatat joskus huomata, että
oikolukutoiminto ei hyväksy jotain kirjoittamaasi sanaa, vaikka se on oikein. Voit ilmoittaa meille
näistä sanoista tämän lomakkeen kautta.</p>

<form method="post" action="ehdotasanoja">

<p><label>Lisättävä sana: <input type="text" name="word" size="30" /></label><br />
<i>Lisättävä sana on parasta kirjoittaa perusmuodossaan. Tämä ei kuitenkaan ole välttämätöntä,
jos olet epävarma sanan oikeasta perusmuodosta.</i></p>

<p><label>Sanan tyyppi: <select name="type">
<option selected="selected" value="yleiskieltä">yleiskielinen sana</option>''')
	for sv in _get_special_vocabularies(db):
		jotools.write(req, u'<option value="%s">%s</option>' % (sv, sv))
	jotools.write(req, u'''
<option value="virheellinen">virheellinen sana (poistettava sanastosta)</option>
</select></label><br />
<i>Valitse lisättävän sanan tyyppi. Vaihtoehtoisesti voit valita kohdan "virheellinen sana",
jos Voikko hyväksyy virheellisen sanan.</i></p>

<p><label>Lisätietoja: <input type="text" name="comment" size="60" /></label><br />
<i>Tähän voit kirjoittaa sanaan liittyviä lisätietoja. Jos sana on jonkin
erikoisalan termi tai muuten harvinainen, kirjoita tähän sille lyhyt selitys.</i></p>

<p><input type="submit" value="Lähetä ehdotus" /></p>
</form>
<hr />
<p>Ehdotukset käsitellään yleensä parin päivän kuluessa niiden lähettämisestä. Päivitettyjä
versioita Voikon sanastosta julkaistaan puolestaan noin puolen vuoden välein.
Jos sinulla on paljon ehdotuksia sanastoon lisättäviksi sanoiksi tai haluat auttaa
jonkin erikoisalan sanaston kehityksessä, voit myös lähettää ehdotuksesi sähköpostitse Harri Pitkäselle
(<a href="mailto:[email protected]">[email protected]</a>).</p>

<p>Voikkoa kehitetään pääasiassa vapaaehtoisvoimin. Lisää tietoa Voikosta löytyy
osoitteesta <a href="http://voikko.puimula.org">voikko.puimula.org</a>.</p>''')
Esempio n. 11
0
def show(req):
	(uid, uname, editable) = jotools.get_login_user(req)
	if not editable:
		joheaders.error_page(req, _(u'You are not allowed to edit data'))
		return '\n'
	tid = jotools.toint(jotools.get_param(req, "tid", "0"))
	if tid == 0:
		joheaders.error_page(req, _(u'Parameter %s is required') % u'tid')
		return '\n'
	words_per_page = 20
	db = jodb.connect()
	taskq = db.query("SELECT sql, orderby FROM task WHERE tid = %i" % tid)
	if taskq.ntuples() != 1:
		joheaders.error_page(req, u'Parameter %s is wrong' % u'tid')
		return '\n'
	tasksql = taskq.getresult()[0][0]
	taskorder = taskq.getresult()[0][1]
	results = db.query(("SELECT w.wid, w.word FROM word w, (%s) t " +
	                    "WHERE t.wid = w.wid AND w.wid NOT IN " +
		          "(SELECT tw.wid FROM task_word tw WHERE tw.tid = %i)" +
			"ORDER BY %s") % (tasksql, tid, taskorder))
	joheaders.page_header_nonavbar(req, u"%s %i" % (_(u'task'), tid))
	jotools.write(req, u'<form method="post" action="save">\n')
	jotools.write(req, u'<table class="border">\n<tr><th>%s</th><th>%s</th></tr>\n' \
	                   % (_(u'OK'), _(u'Word')))
	firstword = random.randint(0, max(results.ntuples() - words_per_page, 0))
	restuples = results.getresult()
	for i in range(firstword, min(firstword + words_per_page, results.ntuples())):
		word = restuples[i]
		jotools.write(req, u'<tr><td><input type="checkbox" name="checked%i" /></td>' \
		                   % word[0])
		jotools.write(req, (u'<td><a href="../word/edit?wid=%i" target="right">%s' +
		                    u'</a></td></tr>\n') \
				% (word[0], jotools.escape_html(unicode(word[1], 'UTF-8'))))
	jotools.write(req, u'</table>')
	jotools.write(req, u'<p><input type="hidden" name="tid" value="%i" />' % tid)
	jotools.write(req, u'<input type="submit" value="%s"></form></p>' % _(u'Save checked'))
	jotools.write(req, u'<p><a href="../" target="_top">%s</a></p>\n' \
	                   %_(u'Back to main page'))
	joheaders.page_footer_plain(req)
	return '\n'
Esempio n. 12
0
def list(req):
	(uid, uname, editable) = jotools.get_login_user(req)
	db = jodb.connect()
	tasks = db.query("SELECT t.tid, t.descr, t.sql, COUNT(DISTINCT tw.wid) FROM task t " +
	                 "LEFT JOIN task_word tw ON (t.tid = tw.tid) " +
		       "GROUP BY t.tid, t.descr, t.sql ORDER BY t.tid")
	if tasks.ntuples() == 0:
		joheaders.error_page(req, _(u'There are no tasks.'))
		return '\n'
	joheaders.page_header_navbar_level1(req, _(u"tasks"), uid, uname)
	jotools.write(req, u"<p>%s:</p>\n" % _(u'Choose a task'))
	jotools.write(req, (u'<table class="border"><tr><th>%s</th><th>%s</th>' +
	                   u'<th>%s *</th><th>%s *</th></tr>\n') \
		         % (_(u'Task'), _(u'Total words'), _(u'Words left'), _(u'Completed')))
	for task in tasks.getresult():
		wordcount = db.query("SELECT COUNT(*) FROM (%s) AS q" % task[2]).getresult()[0][0]
		jotools.write(req, u'<tr><td><a href="work?tid=%i">' % task[0])
		jotools.write(req, u'%s</a></td>' % jotools.escape_html(unicode(task[1],'UTF-8')))
		jotools.write(req, u'<td>%i</td>' % wordcount)
		jotools.write(req, u'<td>%i</td>' % (wordcount - task[3]))
		if wordcount == 0: pleft = u'-'
		else: pleft = task[3] * 100 / wordcount
		jotools.write(req, u'<td>%s %%</td></tr>\n' % pleft)
	jotools.write(req, u"</table>\n")
	# "Words left" is an approximation, because all of the checked words may not belong to
	# this task any more. Calculating the exact numbers is too slow to do here.
	jotools.write(req, u"<p>*) %s.</p>" % _(u'Number of words left is an estimate'))
	joheaders.page_footer_plain(req)
	return '\n'
Esempio n. 13
0
def flags(req, wid = None):
	(uid, uname, editable) = jotools.get_login_user(req)
	if not editable:
		joheaders.error_page(req, _(u'You are not allowed to edit data'))
		return '\n'
	if wid == None:
		joheaders.error_page(req, _(u'Parameter %s is required') % u'wid')
		return '\n'
	wid_n = jotools.toint(wid)
	db = jodb.connect()
	results = db.query("select word, class from word where wid = %i" % wid_n)
	if results.ntuples() == 0:
		joheaders.error_page(req, _(u'Word %i does not exist') % wid_n)
		return '\n'
	wordinfo = results.getresult()[0]
	if req.method == 'GET': # show editor
		word = unicode(wordinfo[0], 'UTF-8')
		classid = wordinfo[1]
		title1 = _(u'Word') + u': ' + word
		link1 = u'edit?wid=%i' % wid_n
		title2 = _(u'flags')
		joheaders.page_header_navbar_level2(req, title1, link1, title2, uid, uname, wid_n)
		jotools.write(req, u'<p>%s</p>\n' % joeditors.call(db, u'word_class', [classid]))
		jotools.write(req, joeditors.call(db, u'flag_edit_form', [wid_n, classid]))
		joheaders.page_footer_plain(req)
		return '\n'
	if req.method != 'POST':
		joheaders.error_page(req, _(u'Only GET and POST requests are allowed'))
		return '\n'
	db.query("begin")
	edfield_results = db.query(("SELECT a.aid, a.descr, CASE WHEN fav.wid IS NULL THEN 'f' ELSE 't' END " +
	                    "FROM attribute_class ac, attribute a " +
	                    "LEFT OUTER JOIN flag_attribute_value fav ON (a.aid = fav.aid and fav.wid = %i) " +
	                    "WHERE a.aid = ac.aid AND ac.classid = %i AND a.type = 2" +
	                    "ORDER BY a.descr") % (wid_n, wordinfo[1]))
	eid = db.query("select nextval('event_eid_seq')").getresult()[0][0]
	event_inserted = False
	messages = []
	
	for attribute in edfield_results.getresult():
		html_att = 'attr%i' % attribute[0]
		if jotools.get_param(req, html_att, u'') == u'on': newval = True
		else: newval = False
		
		if attribute[2] == 't': oldval = True
		else: oldval = False
		
		if oldval == newval: continue
		if not event_inserted:
			db.query("insert into event(eid, eword, euser) values(%i, %i, %i)" % \
			         (eid, wid_n, uid))
			event_inserted = True
		if newval == False:
			db.query(("delete from flag_attribute_value where wid = %i " +
			          "and aid = %i") % (wid_n, attribute[0]))
			messages.append(_(u"Flag removed: '%s'") % unicode(attribute[1], 'UTF-8'))
		if newval == True:
			db.query(("insert into flag_attribute_value(wid, aid, eevent) " +
			          "values(%i, %i, %i)") % (wid_n, attribute[0], eid))
			messages.append(_(u"Flag added: '%s'") % unicode(attribute[1], 'UTF-8'))
	
	comment = jotools.get_param(req, 'comment', u'')
	
	if comment != u'':
		if not event_inserted:
			db.query("insert into event(eid, eword, euser) values(%i, %i, %i)" % \
			         (eid, wid_n, uid))
			event_inserted = True
		db.query("update event set comment = '%s' where eid = %i" \
		         % (jotools.escape_sql_string(comment), eid))
	if event_inserted and len(messages) > 0:
		mess_str = jotools.escape_sql_string(reduce(lambda x, y: x + u"\n" + y, messages, u""))
		db.query("update event set message = '%s' where eid = %i" % (mess_str, eid))
	db.query("commit")
	joheaders.redirect_header(req, u'edit?wid=%i' % wid_n)
	return '\n'
Esempio n. 14
0
def form(req):
	db = jodb.connect()
	(uid, uname, editable) = jotools.get_login_user(req)
	joheaders.page_header_navbar_level1(req, _(u'Search database'), uid, uname)
	jotools.write(req, u'<form method="get" action="wlist">\n<p>')
	jotools.write(req, u'<label>%s: <input type="text" name="word" /></label></p>\n' % _(u'Word'))
	jotools.write(req, u'<p><label><input type="checkbox" name="wordre" /> %s</label>\n' \
	              % _(u'Use regular expression'))
	jotools.write(req, u' <b>%s</b> <label><input type="checkbox" name="wordsimplere" /> %s</label><br />\n' \
	              % (_(u'or'), _(u'Case insensitive search')))
	jotools.write(req, u'<label><input type="checkbox" name="altforms" /> %s</label></p>\n' \
	              % _(u'Search from alternative spellings'))
	
	wclasses = db.query("SELECT classid, name FROM wordclass ORDER BY classid").getresult()
	jotools.write(req, u'<h2>%s</h2>\n' % _(u'Word class'))
	jotools.write(req, u'<p>%s ' % _(u'Word class is'))
	jotools.write(req, u'<select name="wordclass">\n')
	jotools.write(req, u'<option selected="selected" value="">(%s)</option>\n' % _(u'any'))
	for (classid, name) in wclasses:
		jotools.write(req, u'<option value="%i">%s</option>\n' % (classid, unicode(name, 'UTF-8')))
	jotools.write(req, u'</select></p>\n')
	
	textattrs = db.query("SELECT aid, descr FROM attribute WHERE type = 1 ORDER BY descr, aid").getresult()
	jotools.write(req, u'<h2>%s</h2>\n' % _(u'Text attributes'))
	jotools.write(req, u'<p><select name="textaid">\n')
	jotools.write(req, u'<option selected="selected" value="">(%s)</option>\n' % _(u'select attribute'))
	for (aid, dsc) in textattrs:
		jotools.write(req, u'<option value="%i">%s</option>\n' % (aid, unicode(dsc, 'UTF-8')))
	jotools.write(req, u'</select> %s <input type="text" name="textvalue" /><br />\n' % _(u'is'))
	
	flagattrs = db.query("SELECT aid, descr FROM attribute WHERE type = 2 ORDER BY descr, aid").getresult()
	jotools.write(req, u'</p><h2>%s</h2>' % _(u'Flags set'))
	jotools.write(req, u'<ul class="cblist">')
	for (aid, dsc) in flagattrs:
		jotools.write(req, u'<li><label><input type="checkbox" name="flagon%i" />%s</label></li>\n' \
		              % (aid, unicode(dsc, 'UTF-8')))
	jotools.write(req, u'</ul>\n')
	jotools.write(req, u'<h2>%s</h2>' % _(u'Flags not set'))
	jotools.write(req, u'<ul class="cblist">')
	for (aid, dsc) in flagattrs:
		jotools.write(req, u'<li><label><input type="checkbox" name="flagoff%i" />%s</label></li>\n' \
		              % (aid, unicode(dsc, 'UTF-8')))
	jotools.write(req, u'</ul>\n')
	
	jotools.write(req, u'<h2>%s</h2>\n<p>' % _(u'Output type'))
	for (tname, tdesc) in jooutput.list_supported_types():
		if tname == 'html': selected = u'checked="checked"'
		else: selected = u''
		jotools.write(req, (u'<label><input type="radio" name="listtype" value="%s" %s />' +
		                    u'%s</label><br />\n') % (tname, selected, tdesc))
	jotools.write(req, u'</p><p><input type="submit" value="%s" /><input type="reset" value="%s" /></p>\n' \
	              % (_(u'Search'), _(u'Reset')))
	jotools.write(req, u'</form>\n')
	joheaders.page_footer_plain(req)
	return '\n'
Esempio n. 15
0
def add_from_db(req):
	(uid, uname, editable) = jotools.get_login_user(req)
	if not editable:
		joheaders.error_page(req, _(u'You are not allowed to edit data'))
		return '\n'
	if req.method != 'GET':
		joheaders.error_page(req, _(u'Only GET requests are allowed'))
		return '\n'
	db = jodb.connect()
	words_per_page = 15
	category = jotools.get_param(req, 'category', None)
	if category == None: condition = ""
	else: condition = "AND coalesce(info, '') = '%s'" \
	                  % jotools.escape_sql_string(category)
	results = db.query("SELECT count(*) FROM raw_word WHERE processed = FALSE %s" \
	                   % condition)
	nwords = results.getresult()[0][0]
	if nwords <= words_per_page: limit = ""
	else: limit = "LIMIT %i OFFSET %i" % (words_per_page,
	              random.randint(0, nwords - words_per_page))
	results = db.query(("SELECT word, coalesce(notes, '') FROM raw_word " +
	                    "WHERE processed = FALSE %s " +
	                    "ORDER BY word %s") % (condition, limit))
	if results.ntuples() == 0 and category == None:
		joheaders.error_page(req, _(u'There are no words to be added'))
		return '\n'
	if results.ntuples() == 0 and category != None:
		joheaders.error_page(req, _(u'There are no words to be added') + u' ' +
		          _(u'in category %s') % jotools.escape_html(category))
		return '\n'
	class_res = db.query("select classid, name from wordclass").getresult()
	joheaders.page_header_navbar_level1(req, _(u"Add words"), uid, uname)
	jotools.write(req, u'<form method="post" action="add">\n')
	jotools.write(req, u'<table class="border">\n')
	jotools.write(req, u'<tr><th>%s</th><th>%s</th><th>%s</th></tr>\n' \
	                   % (_(u'Word'), _(u'Word class'), _(u'Notes')))
	i = 0
	for result in results.getresult():
		word = unicode(result[0], 'UTF-8')
		notes = unicode(result[1], 'UTF-8')
		jotools.write(req, u'<tr><td><input type="hidden" name="origword%i" value=%s />' \
			                   % (i, jotools.escape_form_value(word)))
		jotools.write(req, u'<input type="text" name="word%i" value=%s /></td><td>' \
		                   % (i, jotools.escape_form_value(word)))
		jotools.write(req, _get_class_selector(class_res, None, i, True))
		jotools.write(req, u'</td><td>')
		jotools.write(req, jotools.escape_html(notes))
		jotools.write(req, u'</td></tr>\n')
		i = i + 1
	jotools.write(req, u'</table>\n' +
	                   u'<p><input type="submit" value="%s"></p></form>\n' % _(u"Add words"))
	joheaders.page_footer_plain(req)
	return '\n'
Esempio n. 16
0
def _add_entry_fields(req, db, words = None, count = 1):
	class_res = db.query("select classid, name from wordclass").getresult()
	if words == None:
		for i in range(count):
			jotools.write(req, u'<tr><td><input type="text" name="word%i" /></td><td>' % i)
			for res in class_res:
				jotools.write(req, (u'<label><input type="radio" name="class%i" ' +
				                     'value="%i">%s</input></label>\n') \
				            % (i, res[0], jotools.escape_html(unicode(res[1], 'UTF-8'))))
			jotools.write(req, u'</td></tr>\n')
		return
	confirm_column = False
	for word in words:
		if word['try_again'] == True:
			confirm_column = True
			break
	i = 0
	for word in words:
		jotools.write(req, u'<tr><td>')
		if word['try_again']:
			if word['oword'] != None:
				jotools.write(req, u'<input type="hidden" name="origword%i" value=%s />' \
				                   % (i, jotools.escape_form_value(word['oword'])))
			jotools.write(req, u'<input type="hidden" name="word%i" value=%s />%s</td><td>' \
			                   % (i, jotools.escape_form_value(word['word']), 
				               jotools.escape_html(word['word'])))
			incnocls = word['oword'] != None
			jotools.write(req, _get_class_selector(class_res, word['cid'], i, incnocls))
			jotools.write(req, u'<td><input type="checkbox" name="confirm%i"></td><td>' % i)
			jotools.write(req, word['error'])
			jotools.write(req, u'</td>')
			i = i + 1
		else:
			jotools.write(req, jotools.escape_html(word['word']))
			jotools.write(req, u'</td><td>')
			jotools.write(req, _get_class_selector(class_res, word['cid'], -1, False))
			jotools.write(req, u'</td><td>')
			if confirm_column: jotools.write(req, u'&nbsp;</td><td>')
			jotools.write(req, word['error'])
			jotools.write(req, u'</td>')
		jotools.write(req, u'</tr>\n')
Esempio n. 17
0
def listchanges(req, sdate = None, edate = None):
	db = jodb.connect()
	(uid, uname, editable) = jotools.get_login_user(req)
	joheaders.page_header_navbar_level1(req, _(u'List changes'), uid, uname)
	
	edt = datetime.datetime.now()
	sdt = edt - datetime.timedelta(days=1)
	if sdate != None:
		try:
			stime = time.strptime(sdate, u'%Y-%m-%d')
			sdt = datetime.datetime(*stime[0:5])
		except:
			jotools.write(req, "<p>%s</p>\n" % _("Invalid start date"))
	if edate != None:
		try:
			etime = time.strptime(edate, u'%Y-%m-%d')
			edt = datetime.datetime(*etime[0:5])
		except:
			jotools.write(req, "<p>%s</p>\n" % _("Invalid end date"))
	sdate_s = sdt.strftime('%Y-%m-%d')
	edate_s = edt.strftime('%Y-%m-%d')
	
	jotools.write(req, u"""
<form method="get" action="listchanges">
<label>%s <input type="text" name="sdate" value="%s"/></label><br />
<label>%s <input type="text" name="edate" value="%s"/></label><br />
<input type="submit" /> <input type="reset" />
</form>
	""" % (_(u'Start date'), sdate_s, _(u'End date'), edate_s))
	
	# Increase edt by one day to make the the SQL between operator act on timestamps
	# in a more intuitive way.
	edt = edt + datetime.timedelta(days=1)
	edate_s = edt.strftime('%Y-%m-%d')
	
	results = db.query("""
	SELECT u.uname, to_char(w.ctime, 'YYYY-MM-DD HH24:MI:SS'),
	       coalesce(u.firstname, ''), coalesce(u.lastname, ''),
	       '%s', NULL, w.wid, w.word
	FROM word w, appuser u WHERE w.cuser = u.uid AND w.ctime BETWEEN '%s' AND '%s'
	UNION
	SELECT u.uname, to_char(e.etime, 'YYYY-MM-DD HH24:MI:SS'),
	       coalesce(u.firstname, ''), coalesce(u.lastname, ''),
	       e.message, e.comment, w.wid, w.word
	FROM appuser u, event e, word w WHERE u.uid = e.euser AND e.eword = w.wid
	AND e.etime BETWEEN '%s' AND '%s'
	ORDER BY 2 DESC""" % (_(u'Word created').encode('UTF-8'), sdate_s, edate_s, sdate_s, edate_s));
	
	if results.ntuples() > 1000:
		jotools.write(req, u'<p>%s</p>' % _(u'Too many changes, use narrower date interval.'))
		joheaders.page_footer_plain(req)
		return '\n'
	retstr = u''
	for result in results.getresult():
		wordlink = u'<a href="../word/edit?wid=%i">%s</a>' \
		           % (result[6], jotools.escape_html(unicode(result[7], 'UTF-8')))
		date = result[1]
		user = jotools.escape_html(unicode(result[2], 'UTF-8')) + u" " + \
		       jotools.escape_html(unicode(result[3], 'UTF-8')) + u" (" + \
		       jotools.escape_html(unicode(result[0], 'UTF-8')) + u")"
		retstr = retstr + (u'<div class="logitem"><p class="date">%s %s %s</p>\n' \
		                   % (wordlink, user, date))
		if result[4] != None:
			msg = jotools.escape_html(unicode(result[4], 'UTF-8')).strip()
			msg = msg.replace(u'\n', u'<br />\n')
			retstr = retstr + u'<p class="logmsg">%s</p>\n' % msg
		if result[5] != None:
			comment = jotools.escape_html(unicode(result[5], 'UTF-8')).strip()
			comment = comment.replace(u'\n', u'<br />\n')
			comment = jotools.comment_links(comment)
			retstr = retstr + u'<p class="comment">%s</p>\n' % comment
		retstr = retstr + u"</div>\n"
	
	jotools.write(req, retstr)
	joheaders.page_footer_plain(req)
	return '\n'
Esempio n. 18
0
def ok_page(req, message):
	page_header_nonavbar(req, u'Joukahainen: %s' % _(u'operation succeeded'))
	jotools.write(req, u'<h1>%s</h1><p>%s</p>\n' % (_(u'operation succeeded'), message))
	jotools.write(req, u'<p><a href="%s">%s ...</a></p>\n' \
	           % (_config.WWW_ROOT_DIR + '/', _(u'Back to front page')))
	page_footer_plain(req)
Esempio n. 19
0
def error_page(req, errortext):
	page_header_nonavbar(req, u'Joukahainen: %s' % _(u'error'))
	jotools.write(req, u'<h1>%s</h1><p>%s</p>\n' % (_(u'Error'), errortext))
	page_footer_plain(req)
Esempio n. 20
0
def redirect_header(req, location):
	location_s = location.encode('UTF-8')
	req.headers_out['location'] = location_s
	req.status = mod_python.apache.HTTP_MOVED_TEMPORARILY
	req.send_http_header()
	jotools.write(req, _(u"Redirecting to %s") % location_s)
Esempio n. 21
0
def classlist(req):
	(uid, uname, editable) = jotools.get_login_user(req)
	joheaders.page_header_navbar_level1(req, u'Etsi sanalle taivutusluokka', uid, uname)
	
	word = jotools.get_param(req, 'word', u'')
	if not jotools.checkword(word):
		joheaders.error_page(req, u'Sanassa on kiellettyjä merkkejä')
		return '\n'
	
	# Sanaa ei annettu, joten näytetään pelkkä lomake
	if len(word) == 0:
		_display_form(req, 1, u'-', u'')
		joheaders.page_footer_plain(req)
		return '\n'
	
	classid = jotools.toint(jotools.get_param(req, 'class', u'0'))
	if classid == 1:
		classdatafile = VOIKKO_DATA + "/subst.aff"
	elif classid == 3:
		classdatafile = VOIKKO_DATA + "/verb.aff"
	elif classid == 0:
		joheaders.page_footer_plain(req)
		return '\n'
	else:
		joheaders.error_page(req, u'Sanaluokkaa ei ole olemassa')
		return '\n'
	
	grad_type = jotools.get_param(req, 'gclass', u'-')
	if not grad_type in [u'-', u'av1', u'av2', u'av3', u'av4', u'av5', u'av6']:
		joheaders.error_page(req, u'Taivutusluokkaa ei ole olemassa')
		return '\n'
	if grad_type == u'-':
		grad_type_s = u''
	else:
		grad_type_s = u'-' + grad_type
	
	_display_form(req, classid, grad_type, word)
	
	word_classes = voikkoinfl.readInflectionTypes(classdatafile)
	
	for word_class in word_classes:
		if len(word_class.joukahainenClasses) == 0: continue
		infclass_main = word_class.joukahainenClasses[0]
		inflected_words = voikkoinfl.inflectWordWithType(word, word_class, infclass_main, grad_type)
		if inflected_words == []: continue
		
		previous_inflected = voikkoinfl.InflectedWord()
		inflist = []
		inflected_words.append(voikkoinfl.InflectedWord())
		jotools.write(req, '<hr /><h2 class="infclass">' + infclass_main + grad_type_s + '</h2>')
		if word_class.note != u'':
			jotools.write(req, u'<p>%s</p>\n' % word_class.note)
		jotools.write(req, u'<p>Kotus-luokka: %s</p>' % \
		              reduce(lambda x, y: u"%s, %s" % (x, y), word_class.kotusClasses))
		
		jotools.write(req, u'<table class="border">\n')
		for inflected_word in inflected_words:
			if previous_inflected.formName != inflected_word.formName:
				if previous_inflected.formName != u"" and len(inflist) > 0:
					if previous_inflected.isCharacteristic:
						infs = reduce(lambda x, y: u"%s, %s" % (x, y), inflist)
						jotools.write(req, (u"<tr><td>%s</td><td>%s</td></tr>\n" %
						          (previous_inflected.formName, infs)))
				inflist = []
				previous_inflected = inflected_word
			if not inflected_word.inflectedWord in inflist:
				inflist.append(inflected_word.inflectedWord)
		jotools.write(req, u'</table>\n')
	joheaders.page_footer_plain(req)
	return '\n'
Esempio n. 22
0
def rwords(req, wid = None):
	(uid, uname, editable) = jotools.get_login_user(req)
	if not editable:
		joheaders.error_page(req, _(u'You are not allowed to edit data'))
		return '\n'
	if wid == None:
		joheaders.error_page(req, _(u'Parameter %s is required') % u'wid')
		return '\n'
	wid_n = jotools.toint(wid)
	db = jodb.connect()
	results = db.query("select word, class from word where wid = %i" % wid_n)
	if results.ntuples() == 0:
		joheaders.error_page(req, _(u'Word %i does not exist') % wid_n)
		return '\n'
	wordinfo = results.getresult()[0]
	if req.method == 'GET': # show editor
		word = unicode(wordinfo[0], 'UTF-8')
		classid = wordinfo[1]
		title1 = _(u'Word') + u': ' + word
		link1 = u'edit?wid=%i' % wid_n
		title2 = _(u'related words')
		joheaders.page_header_navbar_level2(req, title1, link1, title2, uid, uname, wid_n)
		jotools.write(req, u'<p>%s</p>\n' % joeditors.call(db, u'word_class', [classid]))
		jotools.write(req, joeditors.call(db, u'rwords_edit_form', [wid_n]))
		joheaders.page_footer_plain(req)
		return '\n'
	if req.method != 'POST':
		joheaders.error_page(req, _(u'Only GET and POST requests are allowed'))
		return '\n'
	db.query("begin")
	rword_results = db.query("SELECT rwid, related_word FROM related_word WHERE wid = %i" % wid_n)
	rword_res = rword_results.getresult()
	eid = db.query("select nextval('event_eid_seq')").getresult()[0][0]
	event_inserted = False
	messages = []
	
	for attribute in rword_res:
		html_att = 'rword%i' % attribute[0]
		if jotools.get_param(req, html_att, u'') == u'on': remove = True
		else: remove = False
		
		if not remove: continue
		if not event_inserted:
			db.query("insert into event(eid, eword, euser) values(%i, %i, %i)" % \
			         (eid, wid_n, uid))
			event_inserted = True
		db.query("delete from related_word where wid = %i and rwid = %i" \
		         % (wid_n, attribute[0]))
		messages.append(_(u"Alternative spelling removed: '%s'") \
		                % jotools.escape_html(unicode(attribute[1], 'UTF-8')))
	
	newwords = jotools.get_param(req, 'add', u'')
	for word in jotools.unique(newwords.split()):
		if not jotools.checkword(word): continue
		already_listed = False
		for attribute in rword_res:
			if word == unicode(attribute[1], 'UTF-8'): 
				already_listed = True
				break
		if already_listed: continue
		if not event_inserted:
			db.query("insert into event(eid, eword, euser) values(%i, %i, %i)" % \
			         (eid, wid_n, uid))
			event_inserted = True
		db.query("insert into related_word(wid, eevent, related_word) values(%i, %i, '%s')" \
		         % (wid_n, eid, jotools.escape_sql_string(word)))
		messages.append(_(u"Alternative spelling added: '%s'") % jotools.escape_html(word))
	
	comment = jotools.get_param(req, 'comment', u'')
	
	if comment != u'':
		if not event_inserted:
			db.query("insert into event(eid, eword, euser) values(%i, %i, %i)" % \
			         (eid, wid_n, uid))
			event_inserted = True
		db.query("update event set comment = '%s' where eid = %i" \
		         % (jotools.escape_sql_string(comment), eid))
	if event_inserted and len(messages) > 0:
		mess_str = jotools.escape_sql_string(reduce(lambda x, y: x + u"\n" + y, messages, u""))
		db.query("update event set message = '%s' where eid = %i" % (mess_str, eid))
	db.query("commit")
	joheaders.redirect_header(req, u'edit?wid=%i' % wid_n)
	return '\n'
Esempio n. 23
0
def _display_form(req, classid, grad_type, word):
	jotools.write(req, u'''
<div class="rightinfo">
<h2>Astevaihteluluokat</h2>
<p>Vastaavat Kotus-astevaihteluluokat suluissa luokan nimen perässä. Joukahaisen
  astevaihteluluokista parittomissa sanan perusmuoto on vahva-asteinen, parillisissa
  heikkoasteinen.</p>
<dl>
<dt>av1 (A, B, C, E, F, G, H, I, J, K, M)</dt><dd>
  tt->t: ma<em>tt</em>o->ma<em>t</em>on<br />

  pp->p: kaa<em>pp</em>i->kaa<em>p</em>in<br />
  kk->k: ruu<em>kk</em>u->ruu<em>k</em>un<br />
  mp->mm: so<em>mp</em>a->so<em>mm</em>an<br />

  p->v: ta<em>p</em>a->ta<em>v</em>an<br />
  nt->nn: ku<em>nt</em>a->ku<em>nn</em>an<br />
  lt->ll: ki<em>lt</em>a->ki<em>ll</em>an<br />

  rt->rr: ke<em>rt</em>a->ke<em>rr</em>an<br />
  t->d: pöy<em>t</em>ä->pöy<em>d</em>än<br />
  nk->ng: ha<em>nk</em>o->ha<em>ng</em>on<br />

  uku->uvu: p<em>uku</em>->p<em>uvu</em>n<br />
  yky->yvy: k<em>yky</em>->k<em>yvy</em>n
</dd>
<dt>av2 (A, B, C, E, F, G, H, I, J, K)</dt><dd>
  t->tt: rii<em>t</em>e->rii<em>tt</em>een<br />

  p->pp: o<em>p</em>as->o<em>pp</em>aan<br />
  k->kk: lii<em>k</em>e->lii<em>kk</em>een<br />
  mm->mp: lu<em>mm</em>e->lu<em>mp</em>een<br />

  v->p: tar<em>v</em>e->tar<em>p</em>een<br />
  nn->nt: ra<em>nn</em>e->ra<em>nt</em>een<br />
  ll->lt: sive<em>ll</em>in->sive<em>lt</em>imen<br />

  rr->rt: va<em>rr</em>as->va<em>rt</em>aan<br />
  d->t: sa<em>d</em>e->sa<em>t</em>een<br />
  ng->nk: ka<em>ng</em>as->ka<em>nk</em>aan<br />

  b->bb: lo<em>b</em>ata->lo<em>bb</em>aan<br />
  g->gg: di<em>g</em>ata->di<em>gg</em>aan
</dd>
<dt>av3 (L)</dt><dd>
  k->j: jär<em>k</em>i->jär<em>j</em>en
</dd>
<dt>av4 (L)</dt><dd>
  j->k: pal<em>j</em>e->pal<em>k</em>een

</dd>
<dt>av5 (D)</dt><dd>
  k->&empty;: vuo<em>k</em>a->vuoan
</dd>
<dt>av6 (D)</dt><dd>
  &empty;->k: säie->säi<em>k</em>een
</dd>
</dl>

</div>
<form method="get" action="classlist"><p>
<label>Sana: <input type="text" name="word" value="%s"/></label><br />
<label>Sanaluokka: <select name="class">''' % word)
	if classid == 3:
		jotools.write(req, u'''
<option value="1">Nomini</option>
<option selected="selected" value="3">Verbi</option>''')
	else:
		jotools.write(req, u'''
<option selected="selected" value="1">Nomini</option>
<option value="3">Verbi</option>''')
	jotools.write(req, u'''
</select></label><br />
<label>Astevaihteluluokka: <select name="gclass">''')
	if grad_type == u'-':
		jotools.write(req, u'<option selected="selected" value="-">ei astevaihtelua</option>')
	else:
		jotools.write(req, u'<option value="-">ei astevaihtelua</option>')
	for i in range(1, 7):
		if grad_type == (u'av%i' % i):
			jotools.write(req, u'<option selected="selected" ' \
			              + (u'value="av%i">av%i</option>' % (i, i)))
		else:
			jotools.write(req, u'<option value="av%i">av%i</option>' % (i, i))
	jotools.write(req, u'''
</select></label><br />
<input type="submit" value="Hae mahdolliset taivutukset" /></p>
</form>''')
Esempio n. 24
0
def add(req):
	(uid, uname, editable) = jotools.get_login_user(req)
	if not editable:
		joheaders.error_page(req, _(u'You are not allowed to edit data'))
		return '\n'
	db = jodb.connect()
	if req.method != 'POST':
		joheaders.error_page(req, _(u'Only POST requests are allowed'))
		return '\n'
	db.query("BEGIN")
	if jotools.get_param(req, 'confirm', u'') == u'on': confirm = True
	else: confirm = False
	nwordlist = []
	added_count = 0
	need_confirm_count = 0
	i = -1
	while True:
		i = i + 1
		nword = jotools.get_param(req, 'word%i' % i, u'')
		if nword == u'': break
		word = {'word': nword, 'try_again': True, 'confirmed': False, 'wid': None}
		word['oword'] = jotools.get_param(req, 'origword%i' % i, None)
		nclass = jotools.get_param(req, 'class%i' % i, None)
		if not nclass in [None, u'']: nclass = jotools.toint(nclass)
		else: nclass = None
		word['cid'] = nclass
		if confirm and nclass != 0 and jotools.get_param(req, 'confirm%i' % i, u'') != u'on':
			word['error'] = _(u'Word was not added')
			word['try_again'] = False
		if jotools.get_param(req, 'confirm%i' % i, u'') == u'on': word['confirmed'] = True
		stored_word = _store_word(db, word, uid)
		if stored_word['wid'] != None: added_count = added_count + 1
		if stored_word['try_again']: need_confirm_count = need_confirm_count + 1
		nwordlist.append(stored_word)
	db.query("COMMIT")
	if added_count == 1 and len(nwordlist) == 1:
		# No confirmation screen if exactly 1 word was successfully added
		joheaders.redirect_header(req, "edit?wid=%i" % nwordlist[0]['wid'])
		return '\n'
	joheaders.page_header_navbar_level1(req, _(u"Add words"), uid, uname)
	if need_confirm_count > 0:
		jotools.write(req, u'<p>' + _(u'''Adding some words failed or requires confirmation.
Make the required changes and mark the words that you still want to add.''') + u'</p>')
		jotools.write(req, u'<form method="post" action="add">\n')
		jotools.write(req,
		  u'<table class="border"><tr><th>%s</th><th>%s</th><th>%s</th><th>%s</th></tr>\n' \
		  % (_(u'Word'), _(u'Word class'), _(u'Confirm addition'), _(u'Notes')))
		_add_entry_fields(req, db, nwordlist, None)
		jotools.write(req, u'</table>\n<p>' +
		                   u'<input type="hidden" name="confirm" value="on">' +
		                   u'<input type="submit" value="%s"></p></form>\n' % _(u'Continue'))
		joheaders.page_footer_plain(req)
		return '\n'
	else:
		jotools.write(req, u'<p>%s:</p>' % _(u'The following changes were made'))
		jotools.write(req,
		  u'<table class="border"><tr><th>%s</th><th>%s</th><th>%s</th></tr>\n' \
		  % (_(u'Word'), _(u'Word class'), _(u'Notes')))
		_add_entry_fields(req, db, nwordlist, None)
		jotools.write(req, u'</table>\n')
		jotools.write(req, u'<p><a href="../">%s ...</a></p>\n' \
		                   % _(u'Back to main page'))
		joheaders.page_footer_plain(req)
		return '\n'