Ejemplo n.º 1
0
def main(args, opts):
    jdb.reset_encoding(sys.stdout, 'utf-8')
    errs = []
    chklist = {}
    try:
        form, svc, dbg, cur, sid, sess, parms, cfg = jmcgi.parseform()
    except Exception as e:
        jmcgi.err_page([str(e)])
    fv = form.getfirst
    fl = form.getlist

    if not sess or sess.priv != 'A': users = []
    else:
        sql = "SELECT * FROM users ORDER BY userid"
        sesscur = jdb.dbOpenSvc(cfg, svc, session=True, nokw=True)
        users = jdb.dbread(sesscur, sql)
        L('cgi.users').debug('read %d rows from table "user"' % (len(users), ))
    jmcgi.jinja_page("users.jinja",
                     users=users,
                     session=sess,
                     cfg=cfg,
                     parms=parms,
                     svc=svc,
                     dbg=dbg,
                     sid=sid,
                     this_page='user.py',
                     result=fv('result'))
Ejemplo n.º 2
0
def main(args, opts):
    jdb.reset_encoding(sys.stdout, 'utf-8')
    errs = []
    try:
        form, svc, dbg, cur, sid, sess, parms, cfg = jmcgi.parseform()
    except Exception as e:
        jmcgi.err_page([str(e)])

    # The filesystem path of the directory containing editdata files.
    filesdir = cfg['web']['EDITDATA_DIR']
    # The URL for the directory containing editdata files.
    httpdir = cfg['web']['EDITDATA_URL']

    fv = lambda x: (form.getfirst(x) or '').decode(Enc)
    is_editor = jmcgi.is_editor(sess)

    allfiles = sorted(os.listdir(filesdir))
    editfiles = [x for x in allfiles if re.search(r'[0-9]{5}\.dat$', x)]
    logfiles = [x for x in allfiles if re.search(r'((ok)|(bad))\.log$', x)]

    jmcgi.jinja_page('jbedits.jinja',
                     parms=parms,
                     filesdir=filesdir,
                     httpdir=httpdir,
                     editfiles=editfiles,
                     logfiles=logfiles,
                     svc=svc,
                     dbg=dbg,
                     sid=sid,
                     session=sess,
                     cfg=cfg,
                     this_page='jbedits.py')
Ejemplo n.º 3
0
def main (args, opts):
        jdb.reset_encoding (sys.stdout, 'utf-8')
        errs = []
        try: form, svc, dbg, cur, sid, sess, parms, cfg = jmcgi.parseform()
        except Exception as e: jmcgi.err_page ([str (e)])

          # The filesystem path of the directory containing editdata files.
        filesdir = cfg['web']['EDITDATA_DIR']
          # The URL for the directory containing editdata files.
        httpdir  = cfg['web']['EDITDATA_URL']

        fv = lambda x:(form.getfirst(x) or '').decode(Enc)
        is_editor = jmcgi.is_editor (sess)
        srcs = sorted (jdb.KW.recs('SRC'), key=lambda x: x.kw.lower())

          # Get the filename url parameter, and validate it.
        fn = fv ('fn')
        if not re.search (r'[0-9]{5}\.dat$', fn) or '/' in fn:
            err_page (["Bad 'fn' url parameter"])
        fullname = os.path.join (filesdir, fn)
          # Open the file, get the data.
        try: e, ref, comment, name, email = read_editdata (cur, fullname)
        except Exception as e:
            err_page (["Bad file data, unable to unserialize: %s" % str(e)])
        extra = {'ref':ref, 'comment':comment, 'name':name, 'email':email}
        e.NOCORPOPT = ''  # This seems to be required by template, see edform.py
        jmcgi.jinja_page ('edform.jinja', parms=parms,
                        entrs=[e], extra=extra, srcs=srcs, is_editor=is_editor,
                        svc=svc, dbg=dbg, sid=sid, session=sess, cfg=cfg,
                        this_page='jbedit.py')
Ejemplo n.º 4
0
def main(args, opts):
    jdb.reset_encoding(sys.stdout, 'utf-8')
    errs = []
    try:
        form, svc, dbg, cur, sid, sess, parms, cfg = jmcgi.parseform()
    except Exception as e:
        jmcgi.err_page([str(e)])

    fv = form.getfirst
    fl = form.getlist
    orderby = "k.id,s.kw,e.src"
    sql = "SELECT k.id, k.kw, k.descr, s.kw AS corpus, count(*) AS cnt " \
            "FROM kwgrp k " \
            "LEFT JOIN grp g ON g.kw=k.id " \
            "LEFT JOIN entr e ON e.id=g.entr " \
            "LEFT JOIN kwsrc s ON s.id=e.src " \
            "GROUP BY k.id, k.kw, k.descr, e.src, s.kw " \
            "ORDER BY %s" % orderby

    rs = jdb.dbread(cur, sql)
    jmcgi.jinja_page("groups.jinja",
                     results=rs,
                     parms=parms,
                     svc=svc,
                     dbg=dbg,
                     sid=sid,
                     session=sess,
                     cfg=cfg,
                     this_page='goups.py')
Ejemplo n.º 5
0
def main(args, opts):
    jdb.reset_encoding(sys.stdout, 'utf-8')
    try:
        form, svc, dbg, cur, sid, sess, parms, cfg = jmcgi.parseform()
    except Exception as e:
        jmcgi.err_page([str(e)])
    formvalues = form, svc, dbg, cur, sid, sess, parms, cfg
    fv = form.getfirst
    fl = form.getlist
    t = datetime.date.today()  # Will supply default value of y, m, d.
    # y, m, and d below are used to construct sql string and *must*
    # be forced to int()'s to eliminate possibiliy of sql injection.
    try:
        y = int(fv('y') or t.year)
    except Exception as e:
        jmcgi.err_page("Bad 'y' url parameter.")
        return

    show_index = bool(fv('i'))
    if show_index:
        render_year_index(y, formvalues)
    else:
        try:
            m = int(fv('m') or t.month)
            d = int(fv('d') or t.day)
            n = int(fv('n') or 0)
        except Exception as e:
            jmcgi.err_page("Bad 'm', 'd' or 'n' url parameter.")
            return
        render_day_updates(y, m, d, n, formvalues)
Ejemplo n.º 6
0
def main(args, opts):
    jdb.reset_encoding(sys.stdout, 'utf-8')
    try:
        form, svc, dbg, cur, sid, sess, parms, cfg = jmcgi.parseform()
    except Exception as e:
        jmcgi.err_page([str(e)])
    jmcgi.jinja_page("edhelpq.jinja", cfg=cfg, svc=svc, dbg=dbg)
Ejemplo n.º 7
0
def main(args, opts):
    jdb.reset_encoding(sys.stdout, 'utf-8')
    try:
        form, svc, dbg, cur, sid, sess, parms, cfg = jmcgi.parseform()
    except Exception as e:
        jmcgi.err_page([str(e)])

    qs = jmcgi.form2qs(form)
    # reshapes()'s last argument is the maximum number of checkboxes
    # to put on a line, and is ajusted empirically to make the total
    # widths for all the sections approximately equal.
    pos = reshape(sorted(jdb.KW.recs('POS'), key=lambda x: x.kw.lower()), 10)
    misc = reshape(sorted(jdb.KW.recs('MISC'), key=lambda x: x.kw.lower()), 8)
    stat = reshape(sorted(jdb.KW.recs('STAT'), key=lambda x: x.kw.lower()), 10)
    fld = reshape(sorted(jdb.KW.recs('FLD'), key=lambda x: x.kw.lower()), 10)
    dial = reshape(sorted(jdb.KW.recs('DIAL'), key=lambda x: x.kw.lower()), 12)
    kinf = reshape(sorted(jdb.KW.recs('KINF'), key=lambda x: x.kw.lower()), 5)
    # FIXME: restricting 'rinf' kwds to values less that 100 causes
    #  the searchj form not to show the the kanjidic-related ones.
    #  This is really too hackish.  See IS-190 for fix.
    rinf = reshape(
        sorted([x for x in jdb.KW.recs('RINF') if x.id < 100],
               key=lambda x: x.kw.lower()), 5)
    # FIXME: Filter out the kanjidic corpus for now.  Will figure
    #  out how to integrate it later.  This too is pre- IS-190 hack.
    corp = reshape(
        sorted([x for x in jdb.KW.recs('SRC') if x.kw != 'xxkanjidic'],
               key=lambda x: x.kw.lower()), 10)
    freq = []
    for x in sorted(jdb.KW.recs('FREQ'), key=lambda x: x.kw.lower()):
        # Build list of Kwfreq keywords for populating the webpage Freq
        # checkboxes.  Since the 'kwfreq' table does not include the
        # values (the "1", "2", in "ichi1" etc), we create the expanded
        # values here.  We also supply the "descr" value which will provide
        # tool tips on web page.
        if x.kw != 'nf' and x.kw != 'gA':
            freq.extend(
                [Kwfreq(x.kw + '1', x.descr),
                 Kwfreq(x.kw + '2', x.descr)])

    jmcgi.jinja_page("srchform.jinja",
                     KW=jdb.KW,
                     pos=pos,
                     misc=misc,
                     stat=stat,
                     src=corp,
                     freq=freq,
                     fld=fld,
                     kinf=kinf,
                     rinf=rinf,
                     dial=dial,
                     parms=parms,
                     svc=svc,
                     dbg=dbg,
                     sid=sid,
                     session=sess,
                     cfg=cfg,
                     this_page='srchform.py')
Ejemplo n.º 8
0
def main(args, opts):
    # The following call creates a database "cursor" that will
    # be used for subsequent database operations.  It also, as
    # a side-effect, create a global variable in module 'jdb'
    # named 'KW' which contains data read from all the keyword
    # database tables (tables with names matchingthe pattern
    # "kw*".  We read this data once at program startup to avoid
    # multiple hi-cost trips to the database later.
    try:
        cur = jdb.dbOpen(opts.database, **jdb.dbopts(opts))
    except jdb.dbapi.OperationalError as e:
        print("Error, unable to connect to database, do you need -u or -p?\n",
              str(e),
              file=sys.stderr)
        sys.exit(1)

    enc = opts.encoding or sys.stdout.encoding or 'utf-8'
    jdb.reset_encoding(sys.stdout, encoding=enc)

    # Get the command line options and convert them into a sql
    # statement that will find the desired entries.
    sql, sqlargs = opts2sql(args, opts)
    if opts.debug:
        print(("%s  %s" % (sql, repr(sqlargs))))

    # Retrieve the entries from the database.  'entrs' will be
    # set to a list on entry objects.  'raw' is set to dictionary,
    # keyed by table name, and with values consisting of all the
    # rows retrieved from that table.
    entrs, raw = jdb.entrList(cur, sql, sqlargs, ret_tuple=True)

    # Any xrefs in the retrieved entry objects contain contain only
    # the entry id numbers of the referenced entries.  We want to be
    # able to show the refernced entriy's kanji, glosses, etc so we
    # call "augment_xrefs" to get this extra information.  Same for
    # any reverse refrerences.
    jdb.augment_xrefs(cur, raw['xref'])
    jdb.augment_xrefs(cur, raw['xrer'], rev=1)
    jdb.add_xsens_lists(raw['xref'])
    jdb.mark_seq_xrefs(cur, raw['xref'])

    # Now all we have to do is print the entries.
    first = True
    for e in entrs:
        # Format the entry for printing, according to the
        # kind of out put the user requested.
        if opts.jel: txt = fmtjel.entr(e)
        else: txt = fmt.entr(e)

        # Print the formatted entry using the requested encoding
        # and inserting a blank line between entries.
        if not first: print()
        print(txt)
        first = False

    if len(entrs) == 0: print("No entries found")
Ejemplo n.º 9
0
def main( args, opts ):
        jdb.reset_encoding (sys.stdout, 'utf-8')
        try: form, svc, dbg, cur, sid, sess, parms, cfg = jmcgi.parseform()
        except Exception as e: jmcgi.err_page ([str (e)])

        qs = jmcgi.form2qs (form)
        corp = reshape (sorted (jdb.KW.recs('SRC'),
                                key=lambda x:x.kw.lower()), 10)
        jmcgi.jinja_page ("srchformq.jinja",
                        src=corp, parms=parms,
                        svc=svc, dbg=dbg, sid=sid, session=sess, cfg=cfg,
                        this_page='srchformq.py')
Ejemplo n.º 10
0
def main (args, opts):
        jdb.reset_encoding (sys.stdout, opts.encoding)
          # Open the database.  jdb.dbopts() extracts the db-related
          # options from the command line options in 'opts'.
        cur = jdb.dbOpen (opts.database, **jdb.dbopts (opts))
        for f in args:
            fname, ldata = getlabels (cur, f)
            if not fname: print ("No data for sound file '%s'" % str(f), file=sys.stderr)
            else:
                print (fname)
                for r in ldata:
                    strt = r.strt/100.0
                    print ("%f\t%f\t%s" % (strt, strt + r.leng/100.0, r.trns))
Ejemplo n.º 11
0
def main(args, opts):
    jdb.reset_encoding(sys.stdout, 'utf-8')
    try:
        form, svc, dbg, cur, sid, sess, parms, cfg = jmcgi.parseform()
    except Exception as e:
        jmcgi.err_page([str(e)])
    kwhash = {}
    for t in 'RINF KINF FREQ MISC POS FLD DIAL GINF SRC STAT XREF'.split():
        kw = jdb.KW.recs(t)
        kwset = [t.capitalize(), sorted(kw, key=lambda x: x.kw.lower())]
        kwhash[t] = kwset[1]
    kwhash['LANG'] = get_langs(cur)
    jmcgi.jinja_page("edhelp.jinja", svc=svc, dbg=dbg, cfg=cfg, kwhash=kwhash)
Ejemplo n.º 12
0
def main(args, opts):
    jdb.reset_encoding(sys.stdout, 'utf-8')
    errs = []
    try:
        form, svc, dbg, cur, sid, sess, parms, cfg = jmcgi.parseform()
    except Exception as e:
        jmcgi.err_page([str(e)])

    entries = jmcgi.get_entrs(cur, form.getlist('e'), form.getlist('q'), errs)
    if not entries:
        jmcgi.err_page("No entries found")
        return

    ids = [e.id for e in entries]
    sql, args = "SELECT * FROM vinflxt WHERE id IN %s", (tuple(ids), )
    results = jdb.dbread(cur, sql, args)
    poses = set([p.kw for e in entries for s in e._sens for p in s._pos])
    poskws = sorted([jdb.KW.POS[p].kw for p in poses])
    if not results:
        if poskws:
            msg = "Unable to conjugate any of the following parts-of-speech: %s." % (
                ', '.join(poskws))
        else:
            msg = "Word does not have a part-of-speech tag."
        jmcgi.err_page(msg)
        return

    sql, args = "SELECT DISTINCT id,txt FROM vconotes WHERE pos IN %s ORDER BY id", (
        tuple(poses), )
    notes = jdb.dbread(cur, sql, args)

    cur.close()
    # Make notes links, replace '\n's with <br/>s.
    htmlify_conjs(results)
    # Divide the conjugations table up into sections, one for each word (by id).
    sections = partition_conjs(results)
    # Make each note a link target.
    htmlify_notes(notes)

    if errs: jmcgi.err_page(errs)

    jmcgi.jinja_page('conj.jinja',
                     sections=sections,
                     notes=notes,
                     svc=svc,
                     dbg=dbg,
                     sid=sid,
                     session=sess,
                     cfg=cfg,
                     parms=parms,
                     this_page='conj.py')
Ejemplo n.º 13
0
def main(args, opts):
    jdb.reset_encoding(sys.stdout, 'utf-8')
    errs = []
    chklist = {}
    try:
        form, svc, dbg, cur, sid, sess, parms, cfg = jmcgi.parseform()
    except Exception as e:
        jmcgi.err_page([str(e)])
    fv = form.getfirst
    fl = form.getlist
    L('cgi.user').debug("sess=%r" % sess)
    L('cgi.user').debug("u=%r, new=%r" % (fv('u'), fv('new')))
    # If 'sess' evaluates false, user is not logged in in which
    # case we go directly to the "user" page which will say that
    # one has to be logged in.  We do this instead of using jmcgi.-
    # err_page() because the notes on the users.jinja page inform
    # the user about the requirements for access.
    # If user is logged in but is not an Admin user, we ignore
    # the "u=..." url parameter and show user info only for
    # the logged in user.
    # If the user is an Admin user, we show info for the user
    # requested by the "u=..." parameter if any, or the logged
    # in user if not.
    # There may still be no user due to "u=..." for non-existant
    # or some corner-case but that's ok, page will show a "no user
    # found" message.
    user = userid = new = None
    if sess:  # I.e., if logged in...
        if sess.priv == 'A':
            userid, new = fv('u'), fv('new')
        if not new and not userid: userid = sess.userid
        L('cgi.user').debug("userid=%r, new=%r" % (userid, new))
        if userid:
            user = jmcgi.get_user(userid, svc, cfg)
            L('cgi.user').debug("read user data: %s" % (sanitize_o(user), ))
    L('cgi.user').debug("rendering template, new=%r" % new)
    jmcgi.jinja_page("user.jinja",
                     user=user,
                     result=fv('result'),
                     session=sess,
                     cfg=cfg,
                     parms=parms,
                     new=new,
                     svc=svc,
                     sid=sid,
                     dbg=dbg,
                     this_page='user.py')
Ejemplo n.º 14
0
def main(args, opts):
    jdb.reset_encoding(sys.stdout, opts.encoding)
    dir = jdb.find_in_syspath("dtd-audio.xml")
    dtd = jdb.get_dtd(dir + "/" + "dtd-audio.xml", "JMaudio", opts.encoding)
    print(dtd)
    print("<JMaudio>")
    cur = jdb.dbOpen(opts.database, **jdb.dbopts(opts))
    vols = jdb.dbread(cur, "SELECT * FROM sndvol")
    for v in vols:
        print("\n".join(fmtxml.sndvols([v])))
        sels = jdb.dbread(cur, "SELECT * FROM sndfile s WHERE s.vol=%s",
                          [v.id])
        for s in sels:
            print("\n".join(fmtxml.sndsels([s])))
            clips = jdb.dbread(cur, "SELECT * FROM snd c WHERE c.file=%s",
                               [s.id])
            for c in clips:
                print("\n".join(fmtxml.sndclips([c])))
    print('</JMaudio>')
Ejemplo n.º 15
0
def main(args, opts):
    jdb.reset_encoding(sys.stdout, opts.encoding)
    # Open the database.  jdb.dbopts() extracts the db-related
    # options from the command line options in 'opts'.
    cur = jdb.dbOpen(opts.database, **jdb.dbopts(opts))
    fidnum = args[0]
    lbls = args[1]
    xx, rsb = labels_from_db(cur, fidnum)
    rsa = labels_from_file(lbls)
    update, nomatch = align(rsa, rsb, opts.quiet)
    updated = added = None
    ans = ask_action()
    if ans == 'i':
        updated, added = do_interactive(cur, fidnum, update, nomatch)
    elif ans == 'u':
        updated, added = do_noninteractive(cur, fidnum, update, nomatch)
    if updated is not None:
        pout("%d sound records updated" % updated)
    if added is not None:
        pout("%d sound records added" % added)
        for a in nomatch:
            if hasattr(a, 'id'):
                pout("Added: %d:(%d,%d,%s)" % (a.id, a.strt, a.leng, a.trns))
Ejemplo n.º 16
0
def main (args, opts):
        jdb.reset_encoding (sys.stdout, 'utf-8')
        errs = []
        try: form, svc, dbg, cur, sid, sess, parms, cfg = jmcgi.parseform()
        except Exception as e: jmcgi.err_page ([str (e)])
        entries = jmcgi.get_entrs (cur, form.getlist ('e'),
                                        form.getlist ('q'), errs)
        if errs: jmcgi.err_page (errs)

          # Add a .SEQKR attribute to each entry in 'entries' that
          # gives the kanji and reading of the newest (most recently 
          # edited) entry that has the same sequence number. 
        seqkr_decorate (entries)

          # Sort the entries.  The sorting order will group entries 
          # with the same sequence number (.src,.seq) together and 
          # each of those groups will be ordered by the kanji/reading
          # of the newest (most recently edited) entry in the group.
          # (The kanji and/or readings of an entry are sometimes changed
          # and this order will keep the changed entries together with
          # their pre-changed versions, while maintaining an overall
          # ordering by kanji/reading.)  Within each group having the 
          # same sequence number, entries are sorted in descending order
          # by the timestamp of the most recent history; that is, from
          # the most recently edited entry to the least recently edited
          # one. 
        entries.sort (key=lambda e: (
                e.SEQKR[0], e.SEQKR[1], 
                e.src, e.seq,  # In case different seqs have same SEQKR.
                  # e._hist[*].dt is a datatime.datetime instance.
                -(e._hist[-1].dt.timestamp() if e._hist else 0), 
                -e.id))
        for e in entries:
            for s in e._sens:
                if hasattr (s, '_xref'): jdb.augment_xrefs (cur, s._xref)
                if hasattr (s, '_xrer'): jdb.augment_xrefs (cur, s._xrer, 1)
            if hasattr (e, '_snd'): jdb.augment_snds (cur, e._snd)
        cur.close()
        disp = form.getfirst ('disp')
        if disp == 'xml':
            etxts = [fmtxml.entr (e) for e in entries]
        elif disp == 'jm':
            etxts = [fmtxml.entr (e, compat='jmdict') for e in entries]
        elif disp == 'jmne':
            etxts = [fmtxml.entr (e, compat='jmnedict') for e in entries]
        elif disp == 'jel':
            etxts = [fmtjel.entr (e) for e in entries]
        elif disp == 'ed':
            etxts = [xslfmt.entr (e) for e in entries]
        else:
            etxts = ['' for e in entries]
        jmcgi.htmlprep (entries)
        jmcgi.add_encodings (entries)    # For kanjidic entries.
        if disp == 'ed': etxts = [jmcgi.txt2html (x) for x in etxts]
        jmcgi.add_filtered_xrefs (entries, rem_unap=True)

        if errs: jmcgi.err_page (errs)

        jmcgi.jinja_page ('entr.jinja',
                        entries=list(zip(entries, etxts)), disp=disp,
                        svc=svc, dbg=dbg, sid=sid, session=sess, cfg=cfg,
                        parms=parms, this_page='entr.py')
Ejemplo n.º 17
0
def main(args, opts):
    jdb.reset_encoding(sys.stdout, 'utf-8')
    errs = []
    so = None
    stats = {}
    try:
        form, svc, dbg, cur, sid, sess, parms, cfg = jmcgi.parseform()
    except Exception as e:
        jmcgi.err_page([str(e)])

    cfg_web = d2o(cfg['web'])
    cfg_srch = d2o(cfg['search'])
    fv = form.getfirst
    fl = form.getlist
    force_srchres = fv(
        'srchres')  # Force display of srchres page even if only one result.
    sqlp = (fv('sql') or '')
    soj = (fv('soj') or '')
    pgoffset = int(fv('p1') or 0)
    pgtotal = int(fv('pt') or -1)
    entrs_per_page = min(
        max(int(fv('ps') or cfg_web.DEF_ENTRIES_PER_PAGE),
            cfg_web.MIN_ENTRIES_PER_PAGE), cfg_web.MAX_ENTRIES_PER_PAGE)
    if not sqlp and not soj:
        so = jmcgi.SearchItems()
        so.idnum = fv('idval')
        so.idtyp = fv('idtyp')
        tl = []
        for i in (1, 2, 3):
            txt = (fv('t' + str(i)) or '')
            if txt:
                tl.append(
                    jmcgi.SearchItemsTexts(srchtxt=txt,
                                           srchin=fv('s' + str(i)),
                                           srchtyp=fv('y' + str(i))))
        if tl: so.txts = tl
        so.pos = fl('pos')
        so.misc = fl('misc')
        so.fld = fl('fld')
        so.dial = fl('dial')
        so.rinf = fl('rinf')
        so.kinf = fl('kinf')
        so.freq = fl('freq')
        so.grp = grpsparse(fv('grp'))
        so.src = fl('src')
        so.stat = fl('stat')
        so.unap = fl('appr')
        so.nfval = fv('nfval')
        so.nfcmp = fv('nfcmp')
        # Search using gA freq criterion no longer supported.  See
        # the comments in jmcgi._freqcond() but code left here for
        # reference.
        so.gaval = fv('gaval')
        so.gacmp = fv('gacmp')
        #FIXME? use selection boxes for dates?  Or a JS calendar control?
        so.ts = dateparse(fv('ts0'), 0, errs), dateparse(fv('ts1'), 1, errs)
        so.smtr = (fv('smtr') or ''), fv('smtrm')
        so.mt = fv('mt')
        # Pack up all the search criteria in a json string that will
        # be given to the srchres form, which will in turn give it back
        # to us if the user want to display the "next page".
        soj = serialize.so2js(so)

    elif soj:
        # 'soj' is a json string that encodes the so object (containing
        # the search criteria) that were used in previous invocation
        # of this script, which displayed the previous page.
        so = serialize.js2so(soj)

    elif sqlp:
        # 'sqlp' is a SQL statement string that allows an arbitrary search.
        # Because it can also do other things such as delete the database,
        # it should only be run as a user with read-only access to the
        # database and it is the job of jmcgi.adv_srch_allowed() to check
        # that.
        if not jmcgi.adv_srch_allowed(cfg, sess):
            jmcgi.err_page(["'sql' parameter is disallowed."])
        sql = sqlp.strip()
        if sql.endswith(';'): sql = sql[:-1]
        sql_args = []

    if so:
        try:
            condlist = jmcgi.so2conds(so)
        except ValueError as e:
            errs.append(str(e))
        # FIXME: [IS-115] Following will prevent kanjidic entries from
        #  appearing in results.  Obviously hardwiring id=4 is a hack.
        else:
            #condlist.append (('entr e', 'e.src!=4', []))
            sql, sql_args = jdb.build_search_sql(condlist)

    if errs: jmcgi.err_page(errs)

    orderby = "ORDER BY __wrap__.kanj,__wrap__.rdng,__wrap__.seq,__wrap__.id"
    page = "OFFSET %s LIMIT %s" % (pgoffset, entrs_per_page)
    sql2 = "SELECT __wrap__.* FROM esum __wrap__ " \
             "JOIN (%s) AS __user__ ON __user__.id=__wrap__.id %s %s" \
              % (sql, orderby, page)
    stats['sql'] = sql
    stats['args'] = sql_args
    stats['orderby'] = orderby
    if cfg_srch.MAX_QUERY_COST > 0:
        try:
            cost = jdb.get_query_cost(cur, sql2, sql_args)
        except Exception as e:
            jmcgi.err_page(errs=[str(e)],
                           cssclass="errormsg",
                           prolog="Database error (%s)" % e.__class__.__name__)
        stats['cost'] = cost
        if cost > cfg_srch.MAX_QUERY_COST:
            jmcgi.err_page([
                "The search request you made will likely take too "
                "long to execute.  Please use your browser's \"back\" "
                "button to return to the search page and add more "
                "criteria to restrict your search more narrowly. "
                "(The estimated cost was %.1f, max allowed is %d.)" %
                (cost, cfg_srch.MAX_QUERY_COST)
            ])
    t0 = time.time()
    try:
        rs = jdb.dbread(cur, sql2, sql_args)
    except Exception as e:  #FIXME, what exception value(s)?
        jmcgi.err_page(errs=[str(e)],
                       cssclass="errormsg",
                       prolog="Database error (%s)" % e.__class__.__name__)
    stats['dbtime'] = time.time() - t0
    reccnt = len(rs)
    if pgtotal < 0:
        if reccnt >= entrs_per_page:
            # If there may be more than one page of entries (because
            # 'reccnt' is greater than the page size, 'entrs_per_page',
            # then run another query to get the actual number of entries.
            # We only do this on the first page of results ('pgtotal' is
            # less then 0) and subsequently pass the value between pages
            # for performace reasons, even though the number of entries
            # may change before the user gets to the last page.
            sql3 = "SELECT COUNT(*) AS cnt FROM (%s) AS i " % sql
            cntrec = jdb.dbread(cur, sql3, sql_args)
            pgtotal = cntrec[0][0]  # Total number of entries.
        else:
            pgtotal = reccnt
    if reccnt == 1 and pgtotal == 1 and not force_srchres:
        # If there is only one entry, display it rather than a search
        # results page.  'force_srchres' allows supressing this behavior
        # for debugging.
        svcstr = ("svc=%s&sid=%s&" % (svc, sid)) if svc else ''
        print("Location: entr.py?%se=%d\n" % (svcstr, rs[0].id))
    else:
        jmcgi.jinja_page("srchres.jinja",
                         results=rs,
                         pt=pgtotal,
                         p0=pgoffset,
                         p1=pgoffset + reccnt,
                         soj=soj,
                         sql=sqlp,
                         parms=parms,
                         svc=svc,
                         dbg=dbg,
                         sid=sid,
                         session=sess,
                         cfg=cfg,
                         stats=stats,
                         this_page='srchres.py')
Ejemplo n.º 18
0
def main(args, opts):
    global Svc, Sid
    jdb.reset_encoding(sys.stdout, 'utf-8')
    errs = []
    dbh = svc = None
    try:
        form, svc, dbg, dbh, sid, sess, parms, cfg = jmcgi.parseform()
    except ValueError as e:
        jmcgi.err_page([str(e)])
    # Svc and Sid are used in function url() and are global in
    # in order to avoid having to pass them through several layers
    # of function calls.
    Svc, Sid = svc, sid

    L('cgi.edsubmit').debug("started: userid=%s, sid=%s" %
                            (sess and sess.userid, sess and sess.id))
    fv = form.getfirst
    # disp values: '': User submission, 'a': Approve. 'r': Reject;
    disp = fv('disp') or ''
    if not sess and disp:
        errs.append("Only registered editors can approve or reject entries")
    if errs: jmcgi.err_page(errs)
    try:
        entrs = serialize.unserialize(fv("entr"))
    except Exception:
        jmcgi.err_page(["Bad 'entr' parameter, unable to unserialize."])

    added = []
    # Clear any possible transactions begun elsewhere (e.g. by the
    # keyword table read in jdb.dbOpen()).  Failure to do this will
    # cause the following START TRANSACTON command to fail with:
    #  InternalError: SET TRANSACTION ISOLATION LEVEL must be
    #  called before any query
    L('cgi.edsubmit.main').debug("starting transaction")
    dbh.connection.rollback()
    dbh.execute("START TRANSACTION ISOLATION LEVEL SERIALIZABLE")
    # FIXME: we unserialize the entr's xref's as they were resolved
    #  by the edconf.py page.  Should we check them again here?
    #  If target entry was deleted in meantime, attempt to add
    #  our entr to db will fail with obscure foreign key error.
    #  Alternatively an edited version of target may have been
    #  created which wont have our xref pointing to it as it should.
    for entr in entrs:
        # FIXME: submission() can raise a psycopg2
        # TransactionRollbackError if there is a serialization
        # error resulting from a concurrent update.  Detecting
        # such a condition is why run with serializable isolation
        # level.  We need to trap it and present some sensible
        # error message.
        e = submission(dbh, entr, disp, errs, jmcgi.is_editor(sess),
                       sess.userid if sess else None)
        # The value returned by submission() is a 3-tuple consisting
        # of (id, seq, src) for the added entry.
        if e: added.append(e)

    if errs:
        L('cgi.edsubmit.main').info("rolling back transaction due to errors")
        dbh.connection.rollback()
        jmcgi.err_page(errs)
    else:
        L('cgi.edsubmit.main').info("doing commit")
        dbh.connection.commit()
    jmcgi.jinja_page("submitted.jinja",
                     added=added,
                     parms=parms,
                     svc=svc,
                     dbg=dbg,
                     sid=sid,
                     session=sess,
                     cfg=cfg,
                     this_page='edsubmit.py')
    L('cgi.edsubmit.main').debug("thank you page sent, exiting normally")
Ejemplo n.º 19
0
def main(args, opts):
    jdb.reset_encoding(sys.stdout, 'utf-8')
    errs = []
    entrs = []
    try:
        form, svc, dbg, cur, sid, sess, parms, cfg = jmcgi.parseform()
    except Exception as e:
        jmcgi.err_page([str(e)])

    fv = form.getfirst
    fl = form.getlist
    is_editor = jmcgi.is_editor(sess)
    dbg = fv('dbg')
    meth = fv('meth')
    def_corp = fv('c')  # Default corpus for new entries.
    defcorpid = None
    if def_corp:
        try:
            def_corp = int(def_corp)
        except ValueError:
            pass
        try:
            defcorpid = jdb.KW.SRC[def_corp].id
        except KeyError:
            errs.append("Bad url parameter: c=%s" % def_corp)
    force_corp = fv('f')  # Force default corpus for new entries.

    sentrs = fl("entr")
    for sentr in sentrs:
        try:
            entrs = serialize.unserialize(sentr)
        except Exception as e:
            errs.append("Bad 'entr' value, unable to unserialize: %s" % str(e))
        else:
            entrs.append(entr)

    jentrs = fl('j')
    for jentr in jentrs:
        try:
            entr = edparse.entr(jentr)
        except Exception as e:
            errs.append("Bad 'j' value, unable to parse: %s" % str(e))
        else:
            entr.src = None
            entrs.append(entr)

    elist, qlist, active = fl('e'), fl('q'), fv('a')
    if elist or qlist:
        entrs.extend(
            jmcgi.get_entrs(cur,
                            elist or [],
                            qlist or [],
                            errs,
                            active=active,
                            corpus=def_corp) or [])
    cur.close()

    if (elist or qlist or jentrs or sentrs) and not entrs:
        # The caller explictly specified and entry to edit but we
        # didn't find it (or them).  Rather than treating this as
        # though no entries were given and displaying a blank edit
        # form, show an error message.
        errs.append("No matching entries were found")
    if errs: jmcgi.err_page(errs)

    srcs = sorted(jdb.KW.recs('SRC'), key=lambda x: x.kw.lower())
    #srcs.insert (0, jdb.Obj (id=0, kw='', descr=''))
    if not entrs:
        # This is a blank new entry.
        # The following dummy entry will produce the default
        # text for new entries: no kanji, no reading, and sense
        # text "[1][n]".
        entr = jdb.Entr(
            _sens=[jdb.Sens(_pos=[jdb.Pos(kw=jdb.KW.POS['n'].id)])], src=None)
        entrs = [entr]
    for e in entrs:
        if not is_editor: remove_freqs(e)
        e.ISDELETE = (e.stat == jdb.KW.STAT['D'].id) or None
        # Provide a default corpus.
        if not e.src: e.src = defcorpid
        e.NOCORPOPT = force_corp

    if errs: jmcgi.err_page(errs)

    for e in entrs:
        e.ktxt = fmtjel.kanjs(e._kanj)
        e.rtxt = fmtjel.rdngs(e._rdng, e._kanj)
        e.stxt = fmtjel.senss(e._sens, e._kanj, e._rdng)

    if errs: jmcgi.err_page(errs)

    jmcgi.jinja_page('edform.jinja',
                     parms=parms,
                     extra={},
                     entrs=entrs,
                     srcs=srcs,
                     is_editor=is_editor,
                     svc=svc,
                     dbg=dbg,
                     sid=sid,
                     session=sess,
                     cfg=cfg,
                     this_page='edform.py')
Ejemplo n.º 20
0
def main(args, opts):
    jdb.reset_encoding(sys.stdout, 'utf-8')
    errs = []
    so = None
    stats = {}
    try:
        form, svc, dbg, cur, sid, sess, parms, cfg = jmcgi.parseform()
    except Exception as e:
        jmcgi.err_page([str(e)])
    fv = form.getfirst
    fl = form.getlist

    # The form values "userid", "fullname", "email", "priv",
    #  "disabled", come from editable fields in the user.py
    #  page.
    # The values "new" (i.e. create) and "delete" are also user
    #  boolean input from user.py indicating what the user wants
    #  to do.  Neither of them set indicates an update action on
    #  an existing account.  Both of them set is an error.
    # The form value "subjid" identifies the user whose data was
    #  originally loaded into the user.py form and is the user any
    #  update or delete will be performed on.  If it differs from
    #  sess.userid it indcates the action is to e done on the
    #  account of someone other than the logged user themself
    #  and is prohibited unless the logged in user has "admin"
    #  privilege.  For a new (create) action, "subjid" is ignored
    #  and the new user is created with the id given in "userid".

    # Set 'action' to "n" (new), "u" (update), "d" (delete) or
    #  "x" (invalid) according to the values of fv('new') and
    #  fv('delete') that were received from as url parameters
    #  from the User form.
    action = {(0,0):'u', (0,1):'d', (1,0):'n', (1,1):'x'}\
               [(bool(fv('new')),bool(fv('delete')))]
    L('cgi.userupd').debug(
        "new=%r, delete=%r, action=%r, subjid=%r, userid=%r" %
        (fv('new'), fv('delete'), action, fv('subjid'), fv('userid')))

    # NOTE: The jmcgi.err_page() calls below do not return,
    #  jmcgi.err_page() calls sys.exit().

    if not sess:
        jmcgi.err_page([],
                       prolog="<p>You must login before you can change your "
                       "user settings.</p>")
    if fv('subjid') != sess.userid and sess.priv != 'A':
        jmcgi.err_page(
            [],
            prolog="<p>You do not have sufficient privilege to alter "
            "settings for anyone other than yourself.</p>")
    if action in ('nd') and sess.priv != 'A':
        jmcgi.err_page(
            [],
            prolog="<p>You do not have sufficient privilege to create "
            "or delete users.</p>")
    if action == 'x':
        jmcgi.err_page(
            [], prolog="<p>\"New user\" and \"Delete\" are incompatible.</p>")

    errors = []
    # Get the id of the user we will be updating.  If creating a
    # new user, 'subjid' should not exist and thus 'subj' will be
    # None which has the beneficial effect of causing gen_sql_-
    # params() to generate change parameters for every form value
    # which is what we want when creating a user.
    subj = jmcgi.get_user(fv('subjid'), svc, cfg)
    if action in 'nu':  # "new" or "update" action...
        if action == 'u':
            L('cgi.userupd').debug("update user %r" % sanitize_o(subj))
        else:
            L('cgi.userupd').debug("create user %r" % fv('userid'))
        if action == 'n' and \
                (subj or fv('userid')==sess.userid
                 or jmcgi.get_user(fv('userid'), svc, cfg)):
            # This is the creation of a new user (fv('userid')).
            # The userid must not already exist.  The tests for
            # subj and sess.userid are simply to avoid an expensive
            # get_user() call when we already know the user exists.
            errors.append("Account name %s is already in use." % fv('userid'))
        if action == 'u' and fv('userid')!=subj.userid \
                and (fv('userid')==sess.userid \
                     or jmcgi.get_user(fv('userid'), svc, cfg)):
            # This is an update of an existing user.
            # If the new userid (fv('userid')) is the same as the
            # subj.userid it's not being changed and is ok.  If
            # different then it must not be the same as an exiting
            # userid.  The test for sess.userid is simply to avoid
            # an expensive get_user() call when we already know
            # that user exists.
            errors.append("Account name %s is already in use." % fv('userid'))

        # Get the parameters we'll need for the sql statement used
        # to update the user/sessions database.
        collist, values, err \
            = gen_sql_params (sess.priv=='A', subj, fv('pw1'), fv('pw2'),
                              fv('userid'), fv('fullname'), fv('email'),
                              fv('priv'), fv('disabled'))
        errors.extend(err)
        L('cgi.userupd').debug("collist: %r" % collist)
        L('cgi.userupd').debug("values: %r" % sanitize_v(values, collist))

    else:  # "delete" action...
        # We ignore changes made to the form fields since we
        # are going to delete the user, they are irrelevant.
        # Except for one: the "userid" field.  If that was
        # changed we treat it as an error due to the risk that
        # the user thought the changed userid will be deleted
        # which is not what will happen (we delete the "subjid"
        # user.)
        values = []
        if fv('userid') != fv('subjid'):
            errors.append("Can't delete user when userid has been changed.")
        if not subj:
            errors.append("User '%s' doesn't exist." % fv('subjid'))

    if errors:
        jmcgi.err_page(
            errs=errors,
            prolog="The following errors were found in the changes "
            "you requested.  Please use your browser's Back button "
            "to return to the user page, correct them, and resubmit "
            "your changes.")

    update_session = None
    result = None
    summary = 'not available'
    if action == 'n':  # Create new user...
        cols = ','.join(c for c, p in collist)
        pmarks = ','.join(p for c, p in collist)
        sql = "INSERT INTO users(%s) VALUES (%s)" % (cols, pmarks)
        values_sani = sanitize_v(values, collist)
        summary = "added user \"%s\"" \
                  % ''.join(p for c,p in collist if c=='userid')
    elif action == 'd':  # Delete existing user...
        sql = "DELETE FROM users WHERE userid=%s"
        values.append(fv('subjid'))
        values_sani = values
        summary = "deleted user \"%s\"" % fv('subjid')
    else:  # Update existing user...
        if not collist: result = 'nochange'
        else:
            if subj and subj.userid == sess.userid \
                    and fv('userid') and fv('userid'):
                update_session = fv('userid')
            updclause = ','.join(("%s=%s" % (c, p)) for c, p in collist)
            sql = "UPDATE users SET %s WHERE userid=%%s" % updclause
            values.append(fv('subjid'))
            values_sani = sanitize_v(values, collist)
            summary = "updated user %s (%s)" \
                       % (fv('subjid'), ','.join([c for c,p in collist]))

    if result != 'nochange':
        sesscur = jdb.dbOpenSvc(cfg, svc, session=True, nokw=True)
        L('cgi.userupd.db').debug("sql:  %r" % sql)
        # 'values_sani' should be the same as values but with any
        # password text masked out.
        L('cgi.userupd.db').debug("args: %r" % values_sani)
        sesscur.execute(sql, values)
        sesscur.connection.commit()
        #FIXME: trap db errors and try to figure out what went
        # wrong in terms that a user can remediate.
        if update_session:
            L('cgi.userupd').debug("update sess.userid: %r->%r" %
                                   (sess.userid, update_session))
            sess.userid = update_session
        L('cgi.userupd').info(summary)
        result = 'success'
    # If the user is not an admin we send them back to their
    # settings page (using 'userid' since it they may have changed
    # it.)  For admin users it's more complcatd because they might
    # have deleted the user.  Easiest for us to send him/her back
    # to the user list page which we know always exists.
    if sess.priv == 'A': return_to = 'users.py?'
    else:
        return_to = 'user.py?u=%s' % fv('userid')
    jmcgi.redirect(urlbase() + "%s&svc=%s&sid=%s&dbg=%s&result=%s" %
                   (return_to, svc, sid, dbg, result))
Ejemplo n.º 21
0
def main(args, opts):
    global Debug
    Debug = opts.debug
    # Open the database.  jdb.dbopts() extracts the db-related
    # options from the command line options in 'opts'.
    cur = jdb.dbOpen(opts.database, **jdb.dbopts(opts))

    # If no "--root" option was supplied, choose a default based
    # on the value of the "--compat" option.
    if not opts.root:
        if opts.compat in ('jmnedict', 'jmneold'): opts.root = 'JMnedict'
        else: opts.root = 'JMdict'

    outf = None
    if not opts.nodtd:
        # Choose a dtd to use based on the "--compat" option.
        # The dtd file is expected to be located somewhere in the
        # pythonpath (sys.path) directories.
        if opts.compat == 'jmdict': dtd = "dtd-jmdict.xml"
        elif opts.compat == 'jmdicthist': dtd = "dtd-jmdict.xml"
        elif opts.compat == 'jmnedict': dtd = "dtd-jmnedict.xml"
        elif opts.compat == 'jmneold': dtd = "dtd-jmneold.xml"
        else: dtd = "dtd-jmdict-ex.xml"
        dir = jdb.find_in_syspath(dtd)
        dtdfn = dir + "/" + dtd  # Fully qualified dtd file name.

        # jdb.get_dtd() reads the dtd text, and replaces the root
        # element name name and encoding with the values supplied
        # in the arguments.
        dtdtxt = jdb.get_dtd(dtdfn, opts.root, opts.encoding)
        if len(args) == 0: outf = sys.stdout
        else: outf = open(args[0], "w")
        jdb.reset_encoding(outf, opts.encoding)
        outf.write(dtdtxt)

    if opts.seqfile:
        if opts.seqfile == '-': f = sys.stdin
        else: f = open(opts.seqfile)
        #FIXME: we should read these incrementally.
        entrlist = [int(x)
                    for x in f.read().split()]  # seq# separated by sp or nl.
        if f != sys.stdin: f.close()

    # Turn the "--corpus" option value into a string that can be
    # and'ed into a SQL WHERE clause to restrict the results to
    # the specified corpora.
    corp_terms = parse_corpus_opt(opts.corpus, 'e.src')

    # If the output file was not opened in the dtd section
    # above, open it now.  We postpose opening it until the
    # last possible moment to avoid creating it and then
    # bombing because there was a typo in the input or dtd
    # filename, etc.
    # FIXME: Should do a "write" function that opens the
    #  file just before writing.
    if not outf:
        if len(args) == 0: outf = sys.stdout
        else: outf = open(args[0], "w")

    whr_act = " AND NOT unap AND stat=" + str(
        jdb.KW.STAT['A'].id) if opts.compat else ""
    if opts.begin:
        # If a "--begin" sequence number was given, we need to read
        # the entr record so we can get the src id number.  Complain
        # and exit if not found.  Complain if more than one entry
        # with the requested seq number exists.  More than one may be
        # found since the same sequence number may exist in different
        # corpora, or in the same corpus if an entry was edited.
        #
        #FIXME: no way to select from multiple entries with same seq
        # number.  Might want just the stat="A" entries for example.
        sql = "SELECT id,seq,src FROM entr e WHERE seq=%s%s%s ORDER BY src" \
                % (int(opts.begin), corp_terms, whr_act)
        if Debug: print(sql, file=sys.stderr)
        start = time.time()
        rs = jdb.dbread(cur, sql)
        if Debug:
            print("Time: %s (init read)" % (time.time() - start),
                  file=sys.stderr)
        if not rs:
            print ("No entry with seq '%s' found" \
                                 % opts.begin, file=sys.stderr)
            sys.exit(1)
        if len(rs) > 1:
            print ("Multiple entries having seq '%s' found, results " \
                   "may not be as expected.  Consider using -s to " \
                   "restrict to a single corpus." % (opts.begin), file=sys.stderr)
        lastsrc, lastseq, lastid = rs[0].src, rs[0].seq, rs[0].id
    if not opts.begin and not opts.seqfile:
        # If no "--begin" option, remove the " AND" from the front of
        # the 'corp_terms' string.  Read the first entry (by seq number)
        # in the requested corpora.
        cc = corp_terms[4:] if corp_terms else 'True'
        # If compat (jmdict or jmnedict), restrict the xml to Active
        # entries only.
        sql = "SELECT id,seq,src FROM entr e WHERE %s%s ORDER BY src,seq LIMIT 1" % (
            cc, whr_act)
        start = time.time()
        if Debug: print(sql, file=sys.stderr)
        rs = jdb.dbread(cur, sql)
        if Debug:
            print("Time: %s (init read)" % (time.time() - start),
                  file=sys.stderr)
        lastsrc, lastseq, lastid = rs[0].src, rs[0].seq, rs[0].id

    # Add an enclosing root element only if we are also including
    # a DTD (ie, producing a full XML file).  Otherwise, the file
    # generated will just be a list of <entr> elements.
    if not opts.nodtd:
        if opts.compat:  # Add a date comment...
            today = time.strftime("%Y-%m-%d", time.localtime())
            outf.write("<!-- %s created: %s -->\n" % (opts.root, today))
        outf.write('<%s>\n' % opts.root)

    entrlist_loc = 0
    count = opts.count
    done = 0
    blksize = opts.blocksize
    corpora = set()

    while count is None or count > 0:

        if opts.seqfile:
            seqnums = tuple(entrlist[entrlist_loc:entrlist_loc + blksize])
            if not seqnums: break
            entrlist_loc += blksize
            #FIXME: need detection of non-existent seq#s.
            sql = "SELECT id FROM entr e WHERE seq IN %s" + corp_terms + whr_act
            sql_args = [seqnums]
            if Debug: print(sql, sql_args, file=sys.stderr)
            start = time.time()
            tmptbl = jdb.entrFind(cur, sql, sql_args)
        else:
            # In this loop we read blocks of 'blksize' entries.  Each
            # block read is ordered by entr src (i.e. corpus), seq, and
            # id.  The block to read is specified in WHERE clause which
            # is effectively:
            #   WHERE ((e.src=lastsrc AND e.seq=lastseq AND e.id>=lastid+1)
            #           OR (e.src=lastsrc AND e.seq>=lastseq)
            #           OR e.src>lastsrc)
            # and (lastsrc, lastseq, lastid) are from the last entry in
            # the last block read.

            whr = "WHERE ((e.src=%%s AND e.seq=%%s AND e.id>=%%s) " \
                          "OR (e.src=%%s AND e.seq>%%s) " \
                          "OR e.src>%%s) %s%s" % (corp_terms, whr_act)
            sql = "SELECT e.id FROM entr e" \
                  " %s ORDER BY src,seq,id LIMIT %d" \
                   % (whr, blksize if count is None else min (blksize, count))

            # The following args will be substituted for the "%%s" in
            # the sql above, in jbd.findEntr().
            sql_args = [lastsrc, lastseq, lastid, lastsrc, lastseq, lastsrc]

            # Create a temporary table of id numbers and give that to
            # jdb.entrList().  This is an order of magnitude faster than
            # giving the above sql directly to entrList().
            if Debug: print(sql, sql_args, file=sys.stderr)
            start = time.time()
            tmptbl = jdb.entrFind(cur, sql, sql_args)
        mid = time.time()
        entrs, raw = jdb.entrList(cur,
                                  tmptbl,
                                  None,
                                  ord="src,seq,id",
                                  ret_tuple=True)
        end = time.time()
        if Debug: print("read %d entries" % len(entrs), file=sys.stderr)
        if Debug:
            print("Time: %s (entrFind), %s (entrList)" %
                  (mid - start, end - mid),
                  file=sys.stderr)
        if not entrs: break
        write_entrs(cur, entrs, raw, corpora, opts, outf)

        # Update the 'last*' variables for the next time through
        # the loop.  Also, decrement 'count', if we are counting.
        lastsrc = entrs[-1].src
        lastseq = entrs[-1].seq
        lastid = entrs[-1].id + 1
        if count is not None: count -= blksize
        done += len(entrs)
        if not Debug: sys.stderr.write('.')
        else: print("%d entries written" % done, file=sys.stderr)
    if not opts.nodtd: outf.writelines('</%s>\n' % opts.root)
    if not Debug: sys.stderr.write('\n')
    print("Wrote %d entries" % done, file=sys.stderr)
Ejemplo n.º 22
0
def main(args, opts):
    jdb.reset_encoding(sys.stdout, 'utf-8')
    errs = []
    chklist = {}
    try:
        form, svc, dbg, cur, sid, sess, parms, cfg = jmcgi.parseform()
    except Exception as e:
        jmcgi.err_page([str(e)])

    fv = form.getfirst
    fl = form.getlist
    KW = jdb.KW

    # 'eid' will be an integer if we are editing an existing
    # entry, or undefined if this is a new entry.
    pentr = None
    eid = url_int('id', form, errs)
    if eid:
        # Get the parent entry of the edited entry.  This is what the
        # edited entry will be diff'd against for the history record.
        # It is also the entry that will be pointed to by the edited
        # entry's 'dfrm' field.
        pentr = jdb.entrList(cur, None, [eid])
        #FIXME: Need a better message with more explanation.
        if not pentr:
            errs.append("The entry you are editing has been deleted.")
        else:
            pentr = pentr[0]

    # Desired disposition: 'a':approve, 'r':reject, undef:submit.
    disp = url_str('disp', form)
    if disp != 'a' and disp != 'r' and disp != '' and disp is not None:
        errs.append("Invalid 'disp' parameter: '%s'" % disp)

    # New status is A for edit of existing or new entry, D for
    # deletion of existing entry.
    delete = fv('delete')
    makecopy = fv('makecopy')
    if delete and makecopy:
        errs.append(
            "The 'delete' and 'treat as new'"
            " checkboxes are mutually exclusive; please select only one.")
    if makecopy: eid = None
    # FIXME: we need to disallow new entries with corp.seq
    # that matches an existing A, A*, R*, D*, D? entry.
    # Do same check in submit.py.

    seq = url_int('seq', form, errs)
    src = url_int('src', form, errs)
    notes = url_str('notes', form)
    srcnote = url_str('srcnote', form)

    # These are the JEL (JMdict Edit Language) texts which
    # we will concatenate into a string that is fed to the
    # JEL parser which will create an Entr object.
    kanj = (stripws(url_str('kanj', form))).strip()
    rdng = (stripws(url_str('rdng', form))).strip()
    sens = (url_str('sens', form)).strip()
    intxt = "\f".join((kanj, rdng, sens))
    grpstxt = url_str('grp', form)

    # Get the meta-edit info which will go into the history
    # record for this change.
    comment = url_str('comment', form)
    refs = url_str('reference', form)
    name = url_str('name', form)
    email = url_str('email', form)

    if errs: jmcgi.err_page(errs)

    # Parse the entry data.  Problems will be reported
    # by messages in 'perrs'.  We do the parse even if
    # the request is to delete the entry (is this right
    # thing to do???) since on the edconf page we want
    # to display what the entry was.  The edsubmit page
    # will do the actual deletion.

    entr, errs = parse(intxt)
    # 'errs' is a list which if not empty has a single item
    # which is a 2-seq of str's: (error-type, error-message).
    if errs or not entr:
        if not entr and not errs:
            errs = ([], "Unable to create an entry from your input.")
        jmcgi.err_page([errs[0][1]], prolog=errs[0][0], cssclass="errormsg")

    entr.dfrm = eid
    entr.unap = not disp

    # To display the xrefs and reverse xrefs in html, they
    # need to be augmented with additional info about their
    # targets.  collect_refs() simply returns a list Xref
    # objects that are on the entr argument's .xref list
    # (forward xrefs) if rev not true, or the Xref objects
    # on the entr argument's ._xrer list (reverse xrefs) if
    # rev is true).  This does not remove them from the entry
    # and is done simply for convenience so we can have
    # augment_xrefs() process them all in one shot.
    # augment_xrefs add an attribute, .TARG, to each Xref
    # object whose value is an Entr object for the entry the
    # xref points to if rev is not true, or the entry the xref
    # is from, if rev is true.  These Entr objects can be used
    # to display info about the xref target or source such as
    # seq#, reading or kanji.  See jdb.augment_xrefs() for details.
    # Note that <xrefs> and <xrers> below contain references
    # to the xrefs on the entries; thus the augmentation done
    # by jdb.augment_xrefs() alters the xref objects on those
    # entries.
    if pentr:
        x = jdb.collect_xrefs([pentr])
        if x: jdb.augment_xrefs(cur, x)
        # Although we don't allow editing of an entry's reverse
        # xref, we still augment them (on the parent entry)
        # because we will display them.
        x = jdb.collect_xrefs([pentr], rev=True)
        if x: jdb.augment_xrefs(cur, x, rev=True)
    x = jdb.collect_xrefs([entr])
    if x: jdb.augment_xrefs(cur, x)

    if delete:
        # Ignore any content changes made by the submitter by
        # restoring original values to the new entry.
        entr.seq = pentr.seq
        entr.src = pentr.src
        entr.stat = KW.STAT['D'].id
        entr.notes = pentr.notes
        entr.srcnote = pentr.srcnote
        entr._kanj = getattr(pentr, '_kanj', [])
        entr._rdng = getattr(pentr, '_rdng', [])
        entr._sens = getattr(pentr, '_sens', [])
        entr._snd = getattr(pentr, '_snd', [])
        entr._grp = getattr(pentr, '_grp', [])
        entr._cinf = getattr(pentr, '_cinf', [])

    else:
        # Migrate the entr details to the new entr object
        # which to this point has only the kanj/rdng/sens
        # info provided by jbparser.
        entr.seq = seq
        entr.src = src
        entr.stat = KW.STAT['A'].id
        entr.notes = notes
        entr.srcnote = srcnote
        entr._grp = jelparse.parse_grp(grpstxt)

        # This form and the JEL parser provide no way to change
        # some entry attributes such _cinf, _snd, reverse xrefs
        # and for non-editors, _freq.  We need to copy these items
        # from the original entry to the new, edited entry to avoid
        # loosing them.  The copy can be shallow since we won't be
        # changing the copied content.
        if pentr:
            if not jmcgi.is_editor(sess):
                jdb.copy_freqs(pentr, entr)
            if hasattr(pentr, '_cinf'): entr._cinf = pentr._cinf
            copy_snd(pentr, entr)

            # Copy the reverse xrefs that are on pentr to entr,
            # removing any that are no longer valid because they
            # refer to senses , readings or kanji no longer present
            # on the edited entry.  Note that these have already
            # been augmented above.
            nuked_xrers = realign_xrers(entr, pentr)
            if nuked_xrers:
                chklist['xrers'] = format_for_warnings(nuked_xrers, pentr)

        # Add sound details so confirm page will look the same as the
        # original entry page.  Otherwise, the confirm page will display
        # only the sound clip id(s).
        #FIXME? Should the following snd augmentation stuff be outdented
        # one level so that it is done in both the delete and non-delete
        # paths?
        snds = []
        for s in getattr(entr, '_snd', []):
            snds.append(s)
        for r in getattr(entr, '_rdng', []):
            for s in getattr(r, '_snd', []):
                snds.append(s)
        if snds: jdb.augment_snds(cur, snds)

        # If any xrefs were given, resolve them to actual entries
        # here since that is the form used to store them in the
        # database.  If any are unresolvable, an approriate error
        # is saved and will reported later.

        rslv_errs = jelparse.resolv_xrefs(cur, entr)
        if rslv_errs: chklist['xrslv'] = rslv_errs

    if errs: jmcgi.err_page(errs)

    # Append a new hist record details this edit.
    if not hasattr(entr, '_hist'): entr._hist = []
    entr = jdb.add_hist(entr, pentr, sess.userid if sess else None, name,
                        email, comment, refs, entr.stat == KW.STAT['D'].id)
    if not delete:
        check_for_errors(entr, errs)
        if errs: jmcgi.err_page(errs)
        pseq = pentr.seq if pentr else None
        check_for_warnings(cur, entr, pseq, chklist)

    # The following all expect a list of entries.
    jmcgi.add_filtered_xrefs([entr], rem_unap=False)
    serialized = serialize.serialize([entr])
    jmcgi.htmlprep([entr])

    entrs = [[entr, None]]  # Package 'entr' as expected by entr.jinja.
    jmcgi.jinja_page("edconf.jinja",
                     entries=entrs,
                     serialized=serialized,
                     chklist=chklist,
                     disp=disp,
                     parms=parms,
                     svc=svc,
                     dbg=dbg,
                     sid=sid,
                     session=sess,
                     cfg=cfg,
                     this_page='edconf.py')