summaryrefslogtreecommitdiffstats
path: root/lib/sisu/v6/digests.rb
diff options
context:
space:
mode:
Diffstat (limited to 'lib/sisu/v6/digests.rb')
-rw-r--r--lib/sisu/v6/digests.rb397
1 files changed, 397 insertions, 0 deletions
diff --git a/lib/sisu/v6/digests.rb b/lib/sisu/v6/digests.rb
new file mode 100644
index 0000000..954185d
--- /dev/null
+++ b/lib/sisu/v6/digests.rb
@@ -0,0 +1,397 @@
+# encoding: utf-8
+=begin
+
+ * Name: SiSU
+
+ * Description: a framework for document structuring, publishing and search
+
+ * Author: Ralph Amissah
+
+ * Copyright: (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
+ 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014 Ralph Amissah,
+ All Rights Reserved.
+
+ * License: GPL 3 or later:
+
+ SiSU, a framework for document structuring, publishing and search
+
+ Copyright (C) Ralph Amissah
+
+ 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/>.
+
+ If you have Internet connection, the latest version of the GPL should be
+ available at these locations:
+ <http://www.fsf.org/licensing/licenses/gpl.html>
+ <http://www.gnu.org/licenses/gpl.html>
+
+ <http://www.sisudoc.org/sisu/en/manifest/gpl.fsf.html>
+
+ * SiSU uses:
+ * Standard SiSU markup syntax,
+ * Standard SiSU meta-markup syntax, and the
+ * Standard SiSU object citation numbering and system
+
+ * Hompages:
+ <http://www.jus.uio.no/sisu>
+ <http://www.sisudoc.org>
+
+ * Download:
+ <http://www.sisudoc.org/sisu/en/SiSU/download.html>
+
+ * Git
+ <http://sources.sisudoc.org/gitweb/?p=code/sisu.git;a=summary>
+ <http://sources.sisudoc.org/?p=code/sisu.git;a=blob;f=lib/sisu/v6/digests.rb;hb=HEAD>
+
+ * Ralph Amissah
+ <ralph@amissah.com>
+ <ralph.amissah@gmail.com>
+
+ ** Description: document digests (md5|sha256) and structure processing
+
+=end
+module SiSU_DigestView
+ require_relative 'particulars' # particulars.rb
+ require_relative 'prog_text_translation' # prog_text_translation.rb
+ require_relative 'shared_markup_alt.rb' # shared_markup_alt.rb
+ class Source
+ @@dg=nil
+ def initialize(opt)
+ @opt=opt
+ @fnb=@opt.fnb
+ @@endnotes_para=[]
+ @@dg=nil
+ @dg=@@dg ||=SiSU_Env::InfoEnv.new.digest.type
+ @particulars=SiSU_Particulars::CombinedSingleton.instance.get_all(opt)
+ end
+ def read
+ begin
+ @env,@md,@ao_array=@particulars.env,@particulars.md,@particulars.ao_array
+ unless @opt.act[:quiet][:set]==:on
+ tool=(@opt.act[:verbose][:set]==:on \
+ || @opt.act[:verbose_plus][:set]==:on \
+ || @opt.act[:maintenance][:set]==:on) \
+ ? "#{@env.program.text_editor} file://#{@md.file.output_path.hash_digest.dir}/#{@md.file.base_filename.hash_digest}"
+ : "[#{@opt.f_pth[:lng_is]}] #{@opt.fno}"
+ (@opt.act[:verbose][:set]==:on \
+ || @opt.act[:verbose_plus][:set]==:on \
+ || @opt.act[:maintenance][:set]==:on) \
+ ? SiSU_Screen::Ansi.new(@opt.act[:color_state][:set],"Document #{@dg} Digests",tool).green_hi_blue
+ : SiSU_Screen::Ansi.new(@opt.act[:color_state][:set],"Document #{@dg} Digests",tool).green_title_hi
+ if @opt.act[:verbose_plus][:set]==:on \
+ or @opt.act[:maintenance][:set]==:on
+ SiSU_Screen::Ansi.new(@opt.act[:color_state][:set],@opt.fns,"file://#{@md.file.output_path.hash_digest.dir}/#{@md.file.base_filename.hash_digest}").flow
+ end
+ end
+ SiSU_DigestView::Source::Scroll.new(@particulars).songsheet
+ rescue
+ SiSU_Errors::Rescued.new($!,$@,@opt.cmd,@opt.fns).location do
+ __LINE__.to_s + ':' + __FILE__
+ end
+ ensure
+ end
+ end
+ private
+ class Scroll <Source
+ @@dl=nil
+ @@ds={}
+ @@description,@@ds[:digests],@@ds[:tree],@@ds[:summary],@@sc_info=[],[],[],[],[]
+ def initialize(particulars) #data='',md='')
+ @particulars=particulars
+ @data,@env,@md=@particulars.ao_array,@particulars.env,@particulars.md
+ SiSU_Env::FileOp.new(@md).mkdir
+ @@dg ||=@env.digest.type
+ @@dl ||=@env.digest.length
+ @dg,@dl=@@dg,@@dl
+ l=SiSU_Env::StandardiseLanguage.new(@md.opt.lng).language
+ @language=l[:n]
+ @tr=SiSU_Translate::Source.new(@md,@language)
+ @sp=' '
+ end
+ def songsheet
+ @@description,@@ds[:digests],@@ds[:tree],@@ds[:summary],@@sc_info=[],[],[],[],[]
+ message_digest
+ ao_structure
+ supplementary
+ output
+ end
+ def description(f,e='')
+ puts f + e.to_s if @md.opt.act[:verbose_plus][:set]==:on
+ @@description << f << e
+ end
+ def digests(f,e='')
+ puts f if @md.opt.act[:verbose_plus][:set]==:on
+ @@ds[:digests] << f + "\n"
+ end
+ def ao_structure_tree(f,e='')
+ puts f + e.to_s if @md.opt.act[:verbose_plus][:set]==:on
+ @@ds[:tree] << f << e
+ end
+ def ao_structure_summary(f,e='')
+ puts f + e.to_s if @md.opt.act[:verbose_plus][:set]==:on
+ @@ds[:summary] << f << e
+ end
+ def rcinfo(f,e='')
+ puts f + e.to_s if @md.opt.act[:verbose_plus][:set]==:on
+ @@sc_info << f << e
+ end
+ def output
+ file=SiSU_Env::FileOp.new(@md)
+ filename_digest=file.write_file.hash_digest
+ filename_digest << @@description.join << @@ds[:digests].join << @@ds[:tree].join << @@ds[:summary].join << @@sc_info.join
+ end
+ def rgx_txt(txt)
+ txt=txt.gsub(/([()])/,"\\\\\\1")
+ end
+ def message_digest
+ data=@data
+ sys=SiSU_Env::SystemCall.new
+ @p=[]
+ @g,@v,@r='','',''
+ data.each do |para|
+ x=nil
+ y,para_endnotes=[],[]
+ if para =~/#{Mx[:id_o]}~(\d+);(?:(?:\w|[0-6]:)\d+);(?:\w\d+)#{Mx[:id_c]}#{Mx[:id_o]}([0-9a-f]{#{@dl}}):([0-9a-f]{#{@dl}})#{Mx[:id_c]}/
+ ocn,d_clean,d_all=$1,$2,$3
+ @ocn=ocn unless ocn.to_i==0
+ para=para.gsub(/#{Mx[:fa_bold_o]}(.+?)#{Mx[:fa_bold_c]}/,'<b>\1</b>').
+ gsub(/#{Mx[:fa_italics_o]}(.+?)#{Mx[:fa_italics_c]}/,'<i>\1</i>').
+ gsub(/#{Mx[:fa_underscore_o]}(.+?)#{Mx[:fa_underscore_c]}/,'<u>\1</u>')
+ if para=~/#{Mx[:en_a_o]}[\d*+]+.+?#{Mx[:id_o]}[0-9a-f]{#{@dl}}#{Mx[:id_c]}#{Mx[:en_a_c]}/
+ para_endnotes << para.scan(/(?:#{Mx[:en_a_o]}|#{Mx[:en_b_o]})([\d*+]+).+?#{Mx[:id_o]}([0-9a-f]{#{@dl}})#{Mx[:id_c]}(?:#{Mx[:en_a_c]}|#{Mx[:en_b_c]})/)
+ end
+ images=[]
+ if para !~/^%+\s/ \
+ and para =~/(?:^|[^_\\])#{Mx[:lnk_o]}(\S+\.(png|jpg|gif))\s.+?#{Mx[:lnk_c]}(?:#{Mx[:url_o]}\S+?#{Mx[:url_c]}|image)/
+ images=para.scan(/(?:^|[^_\\])#{Mx[:lnk_o]}(\S+\.(?:png|jpg|gif))\s.+?#{Mx[:lnk_c]}(?:#{Mx[:url_o]}\S+?#{Mx[:url_c]}|image)/).flatten
+ else nil
+ end
+ x=case para
+ when /^#{Mx[:meta_o]}title#{Mx[:meta_c]}/
+ "\n" << ' '*0 << '@' << ' '*9
+ when /^#{Mx[:meta_o]}subtitle#{Mx[:meta_c]}/
+ "\n" << ' '*1 << '@' << ' '*8
+ when /^#{Mx[:lv_o]}1:/ #fix Mx[:lv_o]
+ "\n" << ' '*2 << ':A ' << ' '*6 << '- ' << ocn << ' '*(10-ocn.length) << d_clean << ' ' << d_all
+ when /^#{Mx[:lv_o]}2:/ #fix Mx[:lv_o]
+ "\n" << ' '*3 << ':B ' << ' '*5 << '- ' << ocn << ' '*(10-ocn.length) << d_clean << ' ' << d_all
+ when /^#{Mx[:lv_o]}3:/ #fix Mx[:lv_o]
+ "\n" << ' '*4 << ':C ' << ' '*4 << '- ' << ocn << ' '*(10-ocn.length) << d_clean << ' ' << d_all
+ when /^#{Mx[:lv_o]}4:/ #fix Mx[:lv_o]
+ "\n" << ' '*5 << '1' << ' '*4 << '- ' << ocn << ' '*(10-ocn.length) << d_clean << ' ' << d_all
+ when /^#{Mx[:lv_o]}5:/ #fix Mx[:lv_o]
+ "\n" << ' '*6 << '2' << ' '*3 << '- ' << ocn << ' '*(10-ocn.length) << d_clean << ' ' << d_all
+ when /^#{Mx[:lv_o]}6:/ #fix Mx[:lv_o]
+ "\n" << ' '*7 << '3' << ' '*2 << '- ' << ocn << ' '*(10-ocn.length) << d_clean << ' ' << d_all
+ else
+ if para =~/MD5\(\S+?\.sst\)=\s*<u>([0-9a-f]{#{@dl}})<\/u>/ #watch
+ @n,@s=/MD5\((\S+?\.sst)\)=\s*<u>([0-9a-f]{#{@dl}})<\/u>/.match(para)[1,2]
+ end
+ x=unless ocn =~ /^0$/
+ if images \
+ and images.length > 0 # then get path of image & produce digest
+ @image_name,@image_dgst,@img=[],[],[]
+ images.each do |i|
+ image_source=if FileTest.file?("#{@env.path.image_source_include_local}/#{i}")
+ @env.path.image_source_include_local
+ elsif FileTest.file?("#{@env.path.image_source_include_remote}/#{i}")
+ @env.path.image_source_include_remote
+ elsif FileTest.file?("#{@env.path.image_source_include}/#{i}")
+ @env.path.image_source_include
+ else
+ SiSU_Screen::Ansi.new(@md.opt.act[:color_state][:set],"ERROR - image:", %{"#{i}" missing}, "search locations: #{@env.path.image_source_include_local}, #{@env.path.image_source_include_remote} and #{@env.path.image_source_include}").error2 unless @md.opt.act[:quiet][:set]==:on
+ nil
+ end
+ @img << /\S+\.(png|jpg|gif)/.match(i)[1]
+ not_found_msg='image not found'
+ if image_source
+ para_image = image_source + '/' + i
+ @image_name << i
+ @image_dgst << (@dg =~/^sha(?:2|256)$/) \
+ ? sys.sha256(para_image)
+ : sys.md5(para_image)
+ else
+ @image_name << ' '*16 + i + ' [image missing]'
+ @image_dgst << ''
+ @image_dgst[1]=not_found_msg + ' '*(32-not_found_msg.length)
+ end
+ end
+ line= "\n" + ' '*9 + ' - ' + ocn + ' '*(10-ocn.length) + d_clean + ' ' + d_all + "\n"
+ line_image=[]
+ c=0
+ @image_name.each do |ok|
+ line_image << %{ #{@img[c]} #{@image_dgst[c][1]} #{@image_name[c]}}
+ c +=1
+ end
+ line=line + line_image.join("\n")
+ else "\n" + ' '*9 + ' - ' + ocn + ' '*(10-ocn.length) + d_clean + ' ' + d_all
+ end
+ else
+ prefix=''
+ metad=[@tr.full_title,@tr.author,@tr.translator,@tr.illustrator,@tr.prepared_by,@tr.digitized_by,@tr.description,@tr.subject,@tr.abstract,@tr.publisher,@tr.contributor,@tr.date_created,@tr.date_issued,@tr.date_available,@tr.date_modified,@tr.date_valid,@tr.date,@tr.type,@tr.format,@tr.rights,@tr.identifier,@tr.source,@tr.language,@tr.language_original,@tr.relation,@tr.coverage,@tr.keywords,@tr.comments,@tr.cls_loc,@tr.cls_dewey,@tr.cls_gutenberg,@tr.cls_isbn,@tr.prefix_a,@tr.prefix_b,@tr.sourcefile,@tr.sourcefile_digest,@tr.last_generated,@tr.sisu_version,@tr.ruby_version,@tr.sc_number,@tr.sc_date,'Generated by: ','Ruby version: ']
+ metad.each do |n|
+ m=rgx_txt(n)
+ if m=~/\S+/ \
+ and para=~/^#{m}:/
+ x,o=0,18
+ while x < 2; o = o + 2
+ x=o - n.length
+ end
+ space=' '*x
+ prefix="#{n.downcase}#{space}"
+ break
+ else prefix=' '*9
+ end
+ end
+ m_title=rgx_txt(@tr.full_title)
+ m_author=rgx_txt(@tr.author)
+ m_sourcefile_digest=rgx_txt(@tr.sourcefile_digest)
+ m_sisu_version=rgx_txt(@tr.sisu_version)
+ m_last_generated=rgx_txt(@tr.last_generated)
+ m_ruby_version=rgx_txt(@tr.ruby_version)
+ case para
+ when /#{m_title}: /
+ @t=/#{m_title}: (.+?)#{Mx[:id_o]}~\d;(?:\w|[0-6]:)\d+;\w\d+#{Mx[:id_c]}#{Mx[:id_o]}[0-9a-f]{#{@dl}}:[0-9a-f]{#{@dl}}#{Mx[:id_c]}/.match(para)[1].gsub(/<\/?u>/,'').strip
+ when /#{m_author}: /
+ @c=/#{m_author}: (.+?)#{Mx[:id_o]}~\d;(?:\w|[0-6]:)\d+;\w\d+#{Mx[:id_c]}#{Mx[:id_o]}[0-9a-f]{#{@dl}}:[0-9a-f]{#{@dl}}#{Mx[:id_c]}/.match(para)[1].gsub(/<\/?u>/,'').strip
+ when /#{m_sourcefile_digest}.+?<u>/ #watch
+ dgst_extra="\n" << ' '*21 << 'source' << ' '*4 << @md.dgst[1] << ' '*34 << @md.fns
+ when /#{m_sisu_version}: /
+ @v=/#{m_sisu_version}: (.+?)#{Mx[:id_o]}~\d;(?:\w|[0-6]:)\d+;\w\d+#{Mx[:id_c]}#{Mx[:id_o]}[0-9a-f]{#{@dl}}:[0-9a-f]{#{@dl}}#{Mx[:id_c]}/.match(para)[1].gsub(/<\/?u>/,'').strip
+ when /#{m_last_generated}: /
+ @g=/#{m_last_generated}: (.+?)#{Mx[:id_o]}~\d;(?:\w|[0-6]:)\d+;\w\d+#{Mx[:id_c]}#{Mx[:id_o]}[0-9a-f]{#{@dl}}:[0-9a-f]{#{@dl}}#{Mx[:id_c]}/.match(para)[1].gsub(/<\/?u>/,'').strip
+ when /#{m_ruby_version}: /
+ @r=/#{m_ruby_version}: (.+?)#{Mx[:id_o]}~\d;(?:\w|[0-6]:)\d+;\w\d+#{Mx[:id_c]}#{Mx[:id_o]}[0-9a-f]{#{@dl}}:[0-9a-f]{#{@dl}}#{Mx[:id_c]}/.match(para)[1].gsub(/<\/?u>/,'').strip
+ end
+ dgst_extra ||=''
+ "\n" << prefix << ' - ' << ocn << ' '*(10-ocn.length) << d_clean << ' ' << d_all << dgst_extra << "\n"
+ end
+ end
+ para_endnotes[0].each { |e| y << "\n" + ' '*(28-e[0].length) + "[#{e[0].to_s}] #{e[1].to_s}" } if para_endnotes[0]
+ if y; digests(x,y)
+ else digests(x)
+ end
+ end
+ end
+ manifest="#{@env.url.root}/#{@md.fnb}/sisu_manifest.html"
+ a=%{ocn digest clean (no markup/notes),#{@sp*33}digest all (includes markup & endnotes)\n}
+ description("#{@md.title.full}\n")
+ description("#{@md.author}\n")
+ description("#{@md.fns}\n")
+ description("----------------------------------------------\n")
+ description("SiSU Document Content Certificate (Digest/DCC)\n")
+ description("----------------------------------------------\n")
+ description(" #{@dg} digests\n")
+ description("------------\n")
+ description("Sourcefile digest: #{@md.dgst[1]}\n")
+ description(" source filename: #{@md.fns}\n")
+ description("available outputs: #{manifest}\n")
+ #description(" time generated: #{@g}\n")
+ #description(" SiSU version used: #{@v}\n")
+ #description(" Ruby version used: #{@r}\n")
+ description("------------\n")
+ description("Document Digests\n")
+ description(a)
+ end
+ def ao_structure
+ data=@data
+ endnotes=nil
+ data.each do |t_o|
+ dgst=SiSU_TextRepresentation::ModifiedTextPlusHashDigest.new(@md,t_o).composite.dgst
+ if dgst
+ if t_o.is==:heading
+ digests("#{@sp*0}#{dgst[:ocn]}#{@sp*(8-dgst[:ocn].to_s.length)}#{dgst[:dgst_stripped_txt]} #{dgst[:dgst_markedup_txt]} #{dgst[:is]} #{t_o.lv}")
+ elsif t_o.is==:heading_insert
+ digests("#{@sp*0}[#{dgst[:ocn]}]#{@sp*(6-dgst[:ocn].to_s.length)}#{dgst[:dgst_stripped_txt]} #{dgst[:dgst_markedup_txt]} #{dgst[:is]} #{t_o.lv}")
+ else
+ digests("#{@sp*0}#{dgst[:ocn]}#{@sp*(8-dgst[:ocn].to_s.length)}#{dgst[:dgst_stripped_txt]} #{dgst[:dgst_markedup_txt]} #{dgst[:is]}")
+ if dgst[:images]
+ dgst[:images].each do |img|
+ digests("#{@sp*8}#{img[:img_dgst]}#{@sp*66}#{img[:img_type]} #{img[:img_name]}")
+ end
+ end
+ end
+ if dgst[:endnotes]
+ dgst[:endnotes].each do |en|
+ digests("#{@sp*8}#{en[:note_dgst]}#{@sp*66}note [#{en[:note_number]}]")
+ endnotes=en[:note_number]
+ end
+ end
+ end
+ end
+ l=Hash.new(0)
+ ocn=nil
+ ao_structure_tree("------------\n")
+ ao_structure_tree("document structure[*]\n")
+ data.each do |t_o|
+ if t_o.is==:heading
+ x=case t_o.ln
+ when 1 then l[1] +=1 #fix Mx[:lv_o]
+ ' '*0 << ':A'
+ when 2 then l[2] +=1 #fix Mx[:lv_o]
+ ' '*1 << ':B'
+ when 3 then l[3] +=1 #fix Mx[:lv_o]
+ ' '*2 << ':C'
+ when 4 then l[4] +=1 #fix Mx[:lv_o]
+ ' '*3 << '1'
+ when 5 then l[5] +=1 #fix Mx[:lv_o]
+ ' '*4 << '2'
+ when 6 then l[6] +=1 #fix Mx[:lv_o]
+ ' '*5 << '3'
+ else nil
+ end
+ end
+ ocn=t_o.ocn if defined? t_o.ocn and t_o.is !=:heading_insert
+ ao_structure_tree("#{x}\n") if x and not x.empty?
+ end
+ ao_structure_tree(" [*] heading levels\n")
+ ao_structure_summary("------------\n")
+ ao_structure_summary("document structure[*]\n")
+ [0,1,2,3,4,5,6].each do |y|
+ v=case y
+ when 1 then ':A'
+ when 2 then ':B'
+ when 3 then ':C'
+ when 4 then '1 '
+ when 5 then '2 '
+ when 6 then '3 '
+ end
+ ao_structure_summary("#{v} = #{l[y]}\n") if l[y] > 0
+ end
+ ao_structure_summary("objects (ocn) = #{ocn}\n")
+ ao_structure_summary("endnotes = #{endnotes}\n")
+ ao_structure_summary(" [*] number of headers (@) and of each heading level (:A to :C and 1 to 3)\n")
+ end
+ def supplementary
+ if defined? @md.sc_number \
+ and @md.sc_number
+ rcinfo("------------\n")
+ rcinfo("source control information\n")
+ rcinfo(" (the following information while not important for document content certification\n may help the publisher in locating the version referred to)\n")
+ rcinfo(" rcs version number: #{@md.sc_number}\n")
+ if defined? @md.sc_date \
+ and @md.sc_date
+ rcinfo(" rcs date: #{@md.sc_date}\n")
+ end
+ if defined? @md.sc_time \
+ and @md.sc_time
+ rcinfo(" rcs time: #{@md.sc_time}\n")
+ end
+ end
+ rcinfo("------------\n")
+ rcinfo("Note: the time generated related fields (text and digests) will vary between otherwise identical document outputs\n")
+ end
+ end
+ end
+end
+__END__