| require 'digest/sha1' |
| require 'logger' |
| require 'ftools' |
| require 'cgi' |
| |
| #--###################################################################### |
| # Copyright (c) 2006 LogicaCMG |
| # |
| # All rights reserved. This program and the accompanying materials |
| # are made available under the terms of the Eclipse Public License v1.0 |
| # which accompanies this distribution, and is available at |
| # http://www.eclipse.org/legal/epl-v10.html |
| # |
| # Contributors: |
| # |
| # Onno van der Straaten:: initial implementation |
| #++###################################################################### |
| # {Copyright (c) 2006 LogicaCMG}[link:files/COPYRIGHT.html] |
| |
| EPFWIKI_CSDIFF_PATH = "\"" + File.expand_path(RAILS_ROOT) + "/script/other/CSDiff/CSDiff.exe\"" |
| FLASH_RECORD_UPDATED = "Record updated!" |
| FLASH_RECORD_CREATED = "Record created!" |
| FLASH_RECORD_DELETED = "Record deleted!" |
| FLASH_USE_POST_NOT_GET = 'The action does not allow a GET request, a POST request should be used' |
| FLASH_NOT_OWNER = "This record was created by someone else, it can only be modified by the user that created it." |
| |
| MSG_EMAIL_SERVER_GENERATED = "**This message was generated by a server. Don't reply to this address.**" |
| |
| def create_cookie(theUser) |
| cookies[:epfwiki_id] = {:value => theUser.id.to_s, :expires => Time.now+31536000} |
| cookies[:epfwiki_token] = {:value => hash_pw(theUser.hashed_password),:expires => Time.now+31536000} |
| end |
| def expire_cookie |
| cookies.delete :epfwiki_id |
| cookies.delete :epfwiki_token |
| end |
| |
| def notify_cadmin |
| Notifier::deliver_env_to(User.find_central_admin, session.instance_variable_get("@data"), params, request.env, nil) |
| end |
| |
| def job_backup |
| buildid = buildid(Time.now) |
| #File.delete(ENV['EPFWIKI_BACKUP_DIR']) if File.exists?(ENV['EPFWIKI_BACKUP_DIR']) |
| File.makedirs(ENV['EPFWIKI_BACKUP_DIR'] + buildid ) |
| params = Array.new |
| params << ENV['EPFWIKI_BACKUP_BAT_PATH'] #0: path to backup bat |
| params << buildid + ".zip" #1: zipname |
| params << ENV['EPFWIKI_BACKUP_BAT_PATH'].split(":")[0] #2: drive |
| params << ENV['EPFWIKI_BACKUP_DIR'] + buildid + "/" #3: backup dir |
| params << ENV['EPFWIKI_ANT_PATH'] #4: path to ant |
| params << ENV['EPFWIKI_ROOT_DIR'] #5: root dir of app |
| params << ENV['EPFWIKI_MYSQLDUMP_PATH'] #6: path to mysql |
| params << ActiveRecord::Base.configurations[RAILS_ENV]['database'] #7: database to backup |
| params << ActiveRecord::Base.configurations[RAILS_ENV]['username'] #8: username |
| params << ActiveRecord::Base.configurations[RAILS_ENV]['password'] #9: password |
| params << ENV['EPFWIKI_ROOT_DIR'].gsub("/","\\") #10: root dir of app |
| cmdline = params.join(" ") |
| path = ENV['EPFWIKI_BACKUP_DIR'] + buildid + "/" + buildid + ".zip" |
| #$stdout.print("Commandline: " + cmdline) |
| cmd = IO.popen(cmdline, "w+") |
| cmd.close_write |
| text = cmd.readlines.join.gsub(ActiveRecord::Base.configurations[RAILS_ENV]['password'], "********") |
| write_log("backup.log", text) |
| cmd.close_read |
| while !File.exists?(path) |
| sleep(3) |
| end |
| Notifier::deliver_email(User.find_central_admin, "Backup " + buildid + ".zip", [path], "<pre>" + text + "</pre>") |
| end |
| |
| def job_monthly_report |
| Notifier::deliver_report(:type => 'M', :host => ENV['EPFWIKI_HOST']) |
| end |
| |
| def job_weekly_report |
| Notifier::deliver_report(:type => 'W', :host => ENV['EPFWIKI_HOST']) |
| end |
| |
| def job_daily_report |
| Notifier::deliver_report(:type => 'D', :host => ENV['EPFWIKI_HOST']) |
| end |
| |
| def buildid(time) |
| return time.strftime("%Y%m%d_%H%M") |
| end |
| |
| def email_addresses_4_report(users) |
| if users.class.to_s == "User" |
| return users.email |
| else |
| recipients = Array.new |
| for user in users |
| recipients = user.email if !recipients |
| recipients << user.email |
| end |
| return recipients |
| end |
| end |
| |
| def diff_files(path, path2fromfile, path2diff, force = false) |
| force = !File.exists?(path2diff) |
| if !force |
| force = (File.mtime(path) > File.mtime(path2diff) || File.mtime(path2fromfile) > File.mtime(path)) |
| end |
| if force |
| if File.compare(path2fromfile, path) |
| File.copy(path, path2diff) |
| else |
| logger.info("Generating diff file " + path2diff) |
| File.makedirs(ENV['EPFWIKI_DIFFS_PATH']) |
| # /Ohc:\HtmlOutput.htm /sC /t=4 U:\rupwiki\public\rupastxt\page_8.txt U:\rupwiki\public\rupastxt\page_5.txt BaseFile RevisedFile |
| cmd = EPFWIKI_CSDIFF_PATH + " /Oh" + path2diff + " /bD /sC /t=4 /q " + path2fromfile + " " + path + " BaseFile RevisedFile" |
| logger.info("Processing command: " + cmd ) |
| File.delete(path2diff) if File.exists?(path2diff) |
| csdiffcommand = IO.popen(cmd, "w+") |
| csdiffcommand.close_write |
| logger.info("File generated by CSDiff, changing output!") |
| # TODO after sleeping some time log error and continue |
| while !File.exists?(path2diff) |
| sleep(3) |
| end |
| # we need to change the file a little bit, only interested in the html |
| lines = IO.readlines(path2diff) |
| aOutputFile = File.new(path2diff, "w") |
| doOut = false |
| lines.each do |aLine| |
| doOut = false if aLine.index("</pre>") |
| aOutputFile.puts(aLine) if doOut |
| doOut = true if aLine.index("<pre>") # new |
| end |
| aOutputFile.close |
| end |
| end |
| return IO.readlines(path2diff).join |
| end |
| |
| def diff_markdown(aRecord, aFromRecord, force = false) |
| path2markdowndiff = path2markdowndiff(aRecord, aFromRecord) |
| html2markdownfile(aRecord.path, path2markdown(aRecord), force) |
| html2markdownfile(aFromRecord.path, path2markdown(aFromRecord), force) |
| diff_files(path2markdown(aRecord), path2markdown(aFromRecord), path2markdowndiff, force) |
| return IO.readlines(path2markdowndiff).join |
| end |
| |
| #-- |
| # NOTE: CSDIFF has a thing about generating diffs for files with extension .html, |
| # therefore we copy rename the file |
| #++ |
| def diff(aRecord, aFromRecord, force = false) |
| logger.info("Diff of " + aRecord.path ) |
| path2diff = path2diff(aRecord, aFromRecord) |
| File.copy(aRecord.path, aRecord.path + ".txt") if !File.exists?(aRecord.path + ".txt") || File.mtime(aRecord.path + ".txt") < File.mtime(aRecord.path) || force |
| File.copy(aFromRecord.path, aFromRecord.path + ".txt") if !File.exists?(aFromRecord.path + ".txt") || File.mtime(aFromRecord.path + ".txt") < File.mtime(aFromRecord.path) || force |
| diff_files(aRecord.path + ".txt", aFromRecord.path + ".txt", path2diff, force) |
| return IO.readlines(path2diff).join |
| end |
| |
| def path2diff(aRecord, aFromRecord) |
| return ENV['EPFWIKI_DIFFS_PATH'] + aFromRecord.class.to_s.downcase + aFromRecord.id.to_s + "_to_" + aRecord.class.to_s.downcase + aRecord.id.to_s + ".html" |
| end |
| |
| def path2markdowndiff(aRecord, aFromRecord = nil) |
| return ENV['EPFWIKI_DIFFS_PATH'] + aFromRecord.class.to_s.downcase + aFromRecord.id.to_s + "_to_" + aRecord.class.to_s.downcase + aRecord.id.to_s + "_markdown.html" if aFromRecord |
| return ENV['EPFWIKI_DIFFS_PATH'] + aRecord.class.to_s.downcase + aRecord.id.to_s + "_markdown.html" |
| end |
| |
| def path2markdown(aRecord) |
| return ENV['EPFWIKI_MARKDOWN_PATH'] + aRecord.class.to_s.downcase + aRecord.id.to_s + ".txt" |
| end |
| |
| #-- |
| # for #html2markdown the Python encoding setting is very important. |
| # In site.py in c:\Python24\Lib set the encoding to utf_8. encoding = "utf_8". |
| # The html content is utf-8 |
| #++ |
| def html2markdown(path2html) |
| cmd = ENV['EPFWIKI_MARKDOWN_BAT_FILE'] + " \"" + path2html+ "\" " + ENV['EPFWIKI_ROOT_DIR'].split(":")[0] + ": " + ENV['EPFWIKI_ROOT_DIR'] |
| #logger.info("Generating markdown with command: " + cmd) |
| html2markdownCmd = IO.popen(cmd, "w+") |
| html2markdownCmd.close_write |
| line = html2markdownCmd.gets |
| markdown = Array.new |
| cnt = 1 |
| while line |
| markdown << line if cnt > 4 |
| line = html2markdownCmd.gets |
| cnt = cnt + 1 |
| end |
| return markdown.join |
| rescue |
| logger.info("Resque in html2markdown, notifying administrator") |
| notify_cadmin |
| return "N.A" |
| ensure |
| html2markdownCmd.close if html2markdownCmd && !html2markdownCmd.closed? |
| end |
| |
| def html2markdownfile(path2html, path2markdown, force = false) |
| # generate markdown if file does not exist or if markdown file is older than version file |
| if !File.exists?(path2markdown) || File.mtime(path2markdown) < File.mtime(path2html) || force |
| File.makedirs(ENV['EPFWIKI_MARKDOWN_PATH']) |
| # TODO a better solution than this bat file |
| markdown = html2markdown(path2html) |
| aOutputFile = File.new(path2markdown, "w") |
| aOutputFile.puts(markdown) |
| aOutputFile.close |
| end |
| return IO.readlines(path2markdown).join |
| end |
| |
| def mine?(theRecord) |
| return (theRecord.id == session['user'].id) if (theRecord.class.to_s == "User") |
| return (theRecord.user_id == session['user'].id) |
| end |
| |
| def admin? |
| return session['user'].admin? if session['user'] |
| return false |
| end |
| |
| def user? |
| return !session['user'].nil? |
| end |
| |
| def cadmin? |
| return (session['user'].admin == "C") if session['user'] |
| return false |
| end |
| |
| # #remove_empty_lines all lines in a file, lines with only <tt># \r\n</tt> |
| # created because PINEdit adds empty lines on each save? |
| def remove_empty_lines(path) |
| someLines = IO.readlines(path) |
| outFile = File.new(path, "w") |
| someLines.each do |aLine| |
| outFile.puts(aLine) if !(aLine.gsub(" ","").chomp.length == 0) |
| end |
| outFile.close |
| end |
| |
| def tidy_file(path) |
| require 'tidy' |
| Tidy.path = ENV['EPFWIKI_TIDY_PATH'] |
| html = IO.readlines(path).join("\n") |
| xml = Tidy.open(:show_warnings=>true) do |tidy| |
| tidy.options.indent = 'auto' # auto won't indent title, li elements |
| tidy.options.quote_ampersand = false |
| tidy.options.output_encoding = 'utf8' |
| tidy.options.input_encoding = 'utf8' |
| tidy.options.char_encoding = 'utf8' |
| tidy.options.wrap = 0 |
| tidy.options.quote_nbsp = 1 |
| tidy.options.tidy_mark = 0 |
| xml = tidy.clean(html) |
| xml |
| outFile = File.new(path, "w") |
| outFile.puts(xml) |
| outFile.close |
| end |
| end |
| |
| def db_script_version(path2migratefolder) |
| files = Dir.entries(path2migratefolder) - [".", ".."] |
| version = 0 |
| files.each { |file| version = file.split("_")[0].to_i if file.split("_")[0].to_i > version } |
| return version |
| end |
| |
| def db_migrate_to_version(version = nil) |
| cmdline = "migrate.bat" |
| cmdline = "migrate.bat version=#{version}" if version |
| cmd = IO.popen(cmdline, "w+") |
| cmd.close_write |
| return cmd.readlines.join |
| end |
| |
| def write_log(logfilename, content) |
| aOutputFile = File.new("#{ENV['EPFWIKI_ROOT_DIR']}log/#{logfilename}", "w") |
| aOutputFile.puts(content) |
| aOutputFile.close |
| end |
| |
| def hash_pw(pw) |
| return Digest::SHA1.hexdigest(pw || '') |
| end |
| |
| # ENV['EPFWIKI_HOST'] env variable is needed, because in a job we don't know the host |
| def job_daily |
| @sites2update = Site.find_wikis_update |
| @cadmin = User.find_central_admin |
| |
| Site.find_baseline_processes_2scan.each do |bp| |
| bp.scan4content |
| end |
| |
| Site.find_wikis_pending.each do |wiki| |
| wiki.wikify |
| if wiki.save |
| Notifier::deliver_wiki_created(wiki,wiki.user) |
| else |
| raise 'wiki.wikify: ' + wiki.errors.full_messages.join(', ') |
| end |
| end |
| |
| Site.find_wikis_update.each do |wiki| |
| if !wiki.checkouts.empty? |
| Notifier::deliver_update_site_checkin_request(wiki) |
| else |
| wiki.update_wiki |
| if wiki.save |
| Notifier::deliver_email([User.find_cental_admin], |
| "[#{ENV['EPFWIKI_APP_NAME']}] Site #{wiki.title} updated!",[], |
| "The wiki site <strong>#{wiki.title}</strong> was succesfully updated to baseline #{wiki.baseline.baseline}") |
| else |
| raise 'wiki.update_wiki ' + wiki.errors.full_messages.join(', ') |
| end |
| end |
| end |
| |
| DifferenceAnalysis.find(:all, :conditions => 'analyzed_on is null').each do |difference_analysis| |
| difference_analysis.perform_analysis |
| if difference_analysis.save |
| Notifier::deliver_email(User.find_central_admin, |
| "Difference Analysis #{self.title} created", [], |
| "NEW: #{pages_new.size.to_s}, REMOVED: #{pages_removed.size.to_s}, EQUAL: #{pages_equal.size.to_s}" ) |
| else |
| raise 'difference_analysis.perform_analysis' + difference_analysis.error.full_messages.join(', ') |
| end |
| end |
| |
| rescue => e |
| Notifier::deliver_email(User.find_central_admin, 'Error running job_daily', [], e.message + "\n" + e.backtrace.join("\n")) |
| end |