diff options
author | Norbert Preining <norbert@preining.info> | 2019-09-02 13:46:59 +0900 |
---|---|---|
committer | Norbert Preining <norbert@preining.info> | 2019-09-02 13:46:59 +0900 |
commit | e0c6872cf40896c7be36b11dcc744620f10adf1d (patch) | |
tree | 60335e10d2f4354b0674ec22d7b53f0f8abee672 /support/ratexdb/ratexdb.rb |
Initial commit
Diffstat (limited to 'support/ratexdb/ratexdb.rb')
-rw-r--r-- | support/ratexdb/ratexdb.rb | 471 |
1 files changed, 471 insertions, 0 deletions
diff --git a/support/ratexdb/ratexdb.rb b/support/ratexdb/ratexdb.rb new file mode 100644 index 0000000000..b1af7d236e --- /dev/null +++ b/support/ratexdb/ratexdb.rb @@ -0,0 +1,471 @@ +#!/usr/bin/env ruby + +# ratexdb Version 0.14 +# Database Access in LaTeX +# Copyright (C) 2007-2010 Robin Höns, Integranova GmbH +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# +# For more information see the web pages +# +# Robin Höns: http://www.hoens.net/robin +# Integranova and the Programming Machine: +# http://www.programmiermaschine.de +# http://www.care-t.com + +require 'dbi' +require 'FileUtils' + + +$filedebug = nil + +# primitive debug output routine +def debugoutput line + if $filedebug + $filedebug.puts "#{line}" + end +end + + + +def replace_latex dbtext +# Replace Latex special characters in DB result +#Unterstrich _ \_ +#Rückstrich\Backslash \ \setminus +#Dollarzeichen $ \$ +#Kaufmanns-Und & \& +#Raute # \# +#Geschweifte Klammern { } \{ \} +#Prozentzeichen % \% + debugoutput "replatex rein: " + dbtext + + specialhash = { + ?\\ => "\\\\ensuremath{\\\\backslash}", + ?_ => "\\\\_", + ?$ => "\\\\$", + ?& => "\\\\&", + ?# => "\\\\#", + ?{ => "\\\\{", + ?} => "\\\\}", + ?~ => "\\\\~{}", + ?% => "\\\\%" + } + + result = "" + + for i in (0..dbtext.length) + maski = specialhash[dbtext[i]] + if maski + result << maski + else + result << dbtext[i,1] + end + end + + debugoutput "replatex raus: " + result + + return result +end + +def replace_sql dbtext +# Replace SQL special characters in DB result +# (important against SQL injection!) + return dbtext.gsub("'", "''") +end + +def check_number dbtext +# This text must contain a single numeric value +# (important against SQL injection!) + unless dbtext =~ /\A(\+|-)?[\da-fA-F]+\Z/ + raise "Numeric variable contains non-numeric value: #{dbtext}" + end + return dbtext +end + + +def execute_if texblock + debugoutput "Pruefe if #{$select_to_handle}" + debugoutput texblock + + selectkram = $select_hash[$select_to_handle] + $select_to_handle = nil + $modus_collect = false + + selectbefehl = selectkram[0] + debugoutput "Select: #{selectbefehl}" + row = $dbconn.select_one( selectbefehl ) + + if row + # Ja, es gibt Daten zu diesem Select + for nowline in texblock.split("\n") + debugoutput "nowline " + nowline + handle_line(nowline) + end + end +end + + +def execute_for_loop texblock + + debugoutput "Mache #{$select_to_handle} mit:" + debugoutput texblock + + selectkram = $select_hash[$select_to_handle] + $select_to_handle = nil + $modus_collect = false + + selectbefehl = selectkram[0] + variablen = selectkram[1] + + debugoutput "Select: #{selectbefehl}" + for myvar in variablen + debugoutput "Var: #{myvar}" + end + + rows = $dbconn.select_all( selectbefehl ) + + for row in rows + ergebnis = texblock + vari = 0 + while vari < variablen.length + variable_regexs = variablen[vari].split("/") + varname = variable_regexs[0] + + debugoutput "ok: " + varname + if varname[0,2] != "##" + raise "Variable #{varname} does not begin with ##" + end + varnamesql = "$$" + varname[2..-1] + varnamenum = "&&" + varname[2..-1] + + original_db_result = row[vari].to_s + current_db_result_latex = replace_latex(original_db_result) + current_db_result_sql = replace_sql(original_db_result) + if ergebnis.index(varnamenum) + current_db_result_num = check_number(original_db_result) + else + current_db_result_num = original_db_result + end + + debugoutput "latex: #{current_db_result_latex}" + debugoutput "sql: #{current_db_result_sql}" + debugoutput "num: #{current_db_result_num}" + + # Perform all Regexp replaces + rei = 2 + while rei < variable_regexs.length + debugoutput variable_regexs[rei-1] + rei_regex = Regexp.new( variable_regexs[rei-1] ) + debugoutput rei_regex + rei_replace = variable_regexs[rei] + debugoutput rei_replace + current_db_result_latex = current_db_result_latex.gsub(rei_regex, rei_replace) + current_db_result_sql = current_db_result_sql.gsub(rei_regex, rei_replace) + current_db_result_num = current_db_result_num.gsub(rei_regex, rei_replace) + + debugoutput "latex: #{current_db_result_latex}" + debugoutput "sql: #{current_db_result_sql}" + debugoutput "num: #{current_db_result_num}" + + rei += 2 + end + +# Handle the three variable flavours + ergebnis = ergebnis.gsub(varname, current_db_result_latex) + ergebnis = ergebnis.gsub(varnamesql, current_db_result_sql) + if ergebnis.index(varnamenum) + ergebnis = ergebnis.gsub(varnamenum, current_db_result_num) + end + + vari += 1 + end + debugoutput "Ergebnis: #{ergebnis}" + for nowline in ergebnis.split("\n") + handle_line(nowline) + end + end +end + +def execute_defselect texblock + debugoutput "defselect #{$select_to_define}" + debugoutput texblock + + $defining_select_statement = texblock + +end + + +def execute_defvariablen texblock + debugoutput "defvariablen #{$select_to_define}" + debugoutput texblock + + # remove all white space from variable list + + varliste = Array.new + + for var in texblock.split(",") + varliste << var.strip + end + + varliste.each {|var| debugoutput "Got Var: " + var} + + $select_hash[$select_to_define] = [$defining_select_statement, varliste] + + $select_to_define = nil + $modus_collect = false +end + + +def handle_line_unless_empty(line) + debugoutput "handle unless empty" + unless line == nil + unless line.length == 0 + debugoutput "Handle: " + line + handle_line line + else +# debugoutput "line is empty" + end + else +# debugoutput "line is nil" + end +end + +def handle_line(line) +# debugoutput "Handle: " + line + +## matchDef=/\A([^%]*)\\texdbdef\{##([^\}]*)\}\{(.*)\}\{(.*)\}(.*)/ + matchDef=/\A([^%]*)\\texdbdef\{##([^\}]*)\}\{(.*)/ +## matchFor=/\A(.*)\\texdbfor\{##([^\}]*)\}\{(.*)\}(.*)/ + matchFor=/\A([^%]*)\\texdbfor\{##([^\}]*)\}\{(.*)/ + matchIf=/\A([^%]*)\\texdbif\{##([^\}]*)\}\{(.*)/ + matchDbDef=/\A([^%]*)\\texdbconnection\{([^\}]*)\}(.*)/ + matchDbCmd=/\A([^%]*)\\texdbcommand\{([^\}]*)\}(.*)/ + + if $modus_collect == false + if line =~ matchDef + debugoutput "Found Def!" + handle_line_unless_empty($1) + $select_to_define = $2 + $bracedepth = 1 + $modus_collect = 1 + $collected_text = "" + $kommando="defselect" + handle_line_unless_empty($3) + elsif line =~ matchFor + debugoutput "Found For!" + handle_line_unless_empty($1) + $select_to_handle = $2 + $bracedepth = 1 + $modus_collect = 1 + $collected_text = "" + $kommando="for" + handle_line_unless_empty($3) + elsif line =~ matchIf + debugoutput "Found If!" + handle_line_unless_empty($1) + $select_to_handle = $2 + $bracedepth = 1 + $modus_collect = 1 + $collected_text = "" + $kommando="if" + handle_line_unless_empty($3) + elsif line =~ matchDbDef + debugoutput "Found DbDef!" + handle_line_unless_empty($1) + debugoutput "Datenbank: #{$2}" + dbpar = $2.split(",") + $dbconn = DBI.connect(dbpar[0], dbpar[1], dbpar[2], dbpar[3]) + handle_line_unless_empty($3) + elsif line =~ matchDbCmd + debugoutput "Found DbCmd!" + handle_line_unless_empty($1) + debugoutput "Command: #{$2}" + unless $dbconn + raise "Please put texdbconnection before texdbcommand!" + end + sth = $dbconn.execute($2) + sth.finish + handle_line_unless_empty($3) + else + $fileout.puts "#{line}" + end + else + # wir sammeln Zeilen + + if line == nil + linelength = 0 + else + linelength = line.length + end +# debugoutput linelength + i = 0 + backslashgelesen = 0 + while i < linelength && $bracedepth > 0 + currchar = line[i] +# debugoutput "curr #{currchar} backsl #{backslashgelesen}" + if currchar == ?\\ + if backslashgelesen == 0 + backslashgelesen = 1 + else + backslashgelesen = 0 + end + elsif currchar == ?{ + if backslashgelesen == 0 + $bracedepth += 1 + debugoutput "Tiefe: #{$bracedepth}" + else + debugoutput "kein ++, Backslash!" + end + backslashgelesen = 0 + elsif currchar == ?} + if backslashgelesen == 0 + $bracedepth -= 1 + debugoutput "Tiefe: #{$bracedepth}" + else + debugoutput "kein --, Backslash!" + end + backslashgelesen = 0 + else + backslashgelesen = 0 + end + i += 1 + end # while + debugoutput "Zeile Tiefe: #{$bracedepth}" + $collected_text << line[0, i] + i -= 1 + + if $bracedepth == 0 + # chop, um } wegzuschmeißen + if $kommando == "for" + execute_for_loop $collected_text.chop + $modus_collect = false + elsif $kommando == "if" + execute_if $collected_text.chop + $modus_collect = false + elsif $kommando == "defselect" + execute_defselect $collected_text.chop + i += 1 + if i >= linelength || line[i] != ?{ + raise "In texdbdef of #{$select_to_define} there is nothing allowed between the select and variable block, but I did not find the \}\{." + end + $modus_collect = 1 + $kommando = "defvariablen" + $bracedepth = 1 + $collected_text = "" + elsif $kommando == "defvariablen" + execute_defvariablen $collected_text.chop + $modus_collect = false + end + + handle_line_unless_empty line[i+1 .. -1] + end + + $collected_text << "\n" + + end +end + +def output_help + + puts "Ratexdb 0.14 Copyright (C) 2007-2010 Robin Hoens, Integranova GmbH" + puts "This program comes with ABSOLUTELY NO WARRANTY." + puts "This is free software, and you are welcome to redistribute it" + puts "under certain conditions." + puts "See file COPYING for details." + puts "" + puts "Usage:" + puts "#{$0} [-p|-l] <texfile.tex> [Parameters...]" + puts "-p = pdflatex" + puts "-l = latex" + puts "none of the two: just produce texfile1.tex" + exit +end + + +if ARGV.length == 0 + output_help +end + +arg_index = 0 + +before_texfile = 1 + +while before_texfile + if ARGV[arg_index] == "-p" + texbefehl = "pdflatex" + resultextension = ".pdf" + elsif ARGV[arg_index] == "-l" + texbefehl = "latex" + resultextension = ".dvi" + elsif ARGV[arg_index] == "-d" + $filedebug = File.new("ratexdb.txt", "w") + else + before_texfile = false + end + arg_index += 1 + if ARGV.length < arg_index + output_help + end +end + +arg_index -= 1 + +datei_rein = ARGV[arg_index] +datei_raus = datei_rein.sub(/\.tex\Z/, "1.tex") + +if datei_raus == datei_rein + raise "Sorry: File name must end on .tex. I got #{datei_rein}" +end + +debugoutput datei_rein +debugoutput datei_raus + +$select_to_handle = nil +$select_hash = {} +$variable_hash = {} +$modus_collect = false + +cmdlinehash = {} +i=1 +while arg_index + i < ARGV.length + cmdlinehash[i.to_s] = ARGV[arg_index + i] + i+=1 +end + +filein = File.new(datei_rein, "r") +$fileout = File.new(datei_raus, "w") +while (line = filein.gets) + cmdlinehash.each {|key, value| + line = line.gsub("##" + key, replace_latex(value)) + line = line.gsub("$$" + key, replace_sql(value)) + if line.index("&&" + key) + line = line.gsub("&&" + key, check_number(value)) + end + } + handle_line line.chomp +end +filein.close +$fileout.close + +$dbconn.disconnect if $dbconn + +if texbefehl + system(texbefehl, datei_raus) + + rauspdf = datei_raus.sub(/\.tex\Z/, resultextension) + ergebnispdf = datei_rein.sub(/\.tex\Z/, resultextension) + + File.mv(rauspdf, ergebnispdf) +end |