# coding: utf-8 ############################################################################ # Copyright 2009-2019 Benjamin Kellermann # # # # This file is part of Dudle. # # # # Dudle is free software: you can redistribute it and/or modify it under # # the terms of the GNU Affero General Public License as published by # # the Free Software Foundation, either version 3 of the License, or # # (at your option) any later version. # # # # Dudle 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 Affero General Public # # License for more details. # # # # You should have received a copy of the GNU Affero General Public License # # along with dudle. If not, see <http://www.gnu.org/licenses/>. # ############################################################################ $KCODE = "u" if RUBY_VERSION < '1.9.0' require "yaml" require "cgi" $cgi = CGI.new unless $cgi require 'gettext' require 'gettext/cgi' include GetText GetText.cgi=$cgi GetText.output_charset = 'utf-8' require "locale" if File.exists?("data.yaml") && !File.stat("data.yaml").directory? $is_poll = true GetText.bindtextdomain("dudle", :path => Dir.pwd + "/../locale/") else $is_poll = false GetText.bindtextdomain("dudle", :path => Dir.pwd + "/locale/") end $:.push("..") require_relative "date_locale" require_relative "html" require_relative "poll" require_relative "config_defaults" require_relative "charset" class Dudle attr_reader :html, :table, :urlsuffix, :css, :user_css, :title, :tab def is_poll? $is_poll end def tabs_to_html(active_tab) ret = "<div id='tabs'><ul id='tablist'>" @tabs.each{|tab,file| case file when _(active_tab) ret += "<li id='active_tab' class='active_tab' > #{tab} </li> " when "" ret += "<li class='separator_tab'></li>" else ret += "<li class='nonactive_tab' ><a href='#{@html.relative_dir}#{file}'> #{tab} </a></li> " end } ret += "</ul></div>" ret end def inittabs @tabs = [] @tabs << [_("Home"),@basedir] if is_poll? @tabs << ["",""] @tabs << [_("Poll"),"."] @tabs << [_("History"),"history.cgi"] @tabs << ["",""] @configtabs = [ [_("Edit Columns"),"edit_columns.cgi"], [_("Invite Participants"),"invite_participants.cgi"], [_("Access Control"),"access_control.cgi"], [_("Overview"),"overview.cgi"] ] @tabs += @configtabs @tabs << [_("Delete Poll"),"delete_poll.cgi"] @tabs << ["",""] else @tabs << [_("Examples"),"example.cgi"] @tabs << [_("About"),"about.cgi"] end @tabs << [_("Customize"),"customize.cgi"] @tabtitle = @tabs.collect{|title,file| title if file == @tab}.compact[0] end def revision @requested_revision || VCS.revno end def breadcrumbs crumbs = $conf.breadcrumbs crumbs << "<a href='#{@basedir}'>" + _("Dudle Home") + "</a>" if is_poll? if @tab == "." crumbs << @title else crumbs << "<a href='.'>#{@title}</a>" crumbs << @tabtitle end else if @tab != "." crumbs << @tabtitle end end "<div id='breadcrumbs'><ul><li class='breadcrumb'>#{crumbs.join("</li><li class='breadcrumb'>")}</li></ul></div>" end def initialize(params = {:revision => nil, :title => nil, :hide_lang_chooser => nil, :relative_dir => "", :load_extensions => true}) @requested_revision = params[:revision] @hide_lang_chooser = params[:hide_lang_chooser] @cgi = $cgi @tab = File.basename($0) @tab = "." if @tab == "index.cgi" if is_poll? # log last read access manually (no need to grep server logfiles) File.open("last_read_access","w").close unless @cgi.user_agent =~ $conf.bots @basedir = ".." inittabs @table = YAML::load(VCS.cat(self.revision, "data.yaml")) @urlsuffix = File.basename(File.expand_path(".")) @title = @table.name configfiles = @configtabs.collect{|name,file| file} @is_config = configfiles.include?(@tab) @wizzardindex = configfiles.index(@tab) if @is_config @html = HTML.new("dudle - #{@title} - #{@tabtitle}",params[:relative_dir]) @html.add_html_head('<meta name="robots" content="noindex, nofollow" />') @html.header["Cache-Control"] = "no-cache" else @basedir = "." inittabs @title = params[:title] || "dudle" @html = HTML.new(@title,params[:relative_dir]) end @css = ["default", "classic", "print"].collect{|f| f + ".css"} if Dir.exists?("#{@basedir}/css/") Dir.open("#{@basedir}/css/").each{|f| if f =~ /\.css$/ @css << "css/#{f}" end } end if $cgi.include?("css") @user_css = $cgi["css"] @html.add_cookie("css",@user_css,"/",Time.now + (1*60*60*24*365 * (@user_css == $conf.default_css ? -1 : 1 ))) else @user_css = $cgi.cookies["css"][0] @user_css ||= $conf.default_css end if $cgi.user_agent =~ /.*MSIE [567]\..*/ css = [@user_css] else css = @css end css.each{|href| @html.add_css("#{@basedir}/#{href}",href.scan(/([^\/]*)\.css/).flatten[0] ,href == @user_css) } @html << <<HEAD <body><div id="top"></div> HEAD $conf.header.each{|h| @html << h } @html << <<HEAD #{breadcrumbs} <div id='main'> #{tabs_to_html(@tab)} <div id='content'> <h1 id='polltitle'>#{CGI.escapeHTML(@title)}</h1> HEAD ################### # init extenisons # ################### @extensions = [] $d = self # FIXME: this is dirty, but extensions need to know table elem if Dir.exists?("#{@basedir}/extensions/") && params[:load_extensions] Dir.open("#{@basedir}/extensions/").sort.each{|f| if File.exists?("#{@basedir}/extensions/#{f}/main.rb") @extensions << f if File.exists?("#{@basedir}/extensions/#{f}/preload.rb") $current_ext_dir = f require "#{@basedir}/extensions/#{f}/preload" end end } end end def wizzard_nav ret = "<div id='wizzard_navigation'><table><tr>" [[_("Previous"),@wizzardindex == 0], [_("Next"),@wizzardindex >= @configtabs.size()-2], [_("Finish"),@wizzardindex == @configtabs.size()-1]].each{|button,disabled| ret += <<READY <td> <form method='post' action=''> <div> <input type='hidden' name='undo_revision' value='#{self.revision}' /> <input type='submit' #{disabled ? "disabled='disabled'" : ""} name='#{button}' value='#{button}' /> </div> </form> </td> READY } ret += "</tr></table></div>" end def wizzard_redirect [[_("Previous"),@wizzardindex-1], [_("Next"),@wizzardindex+1], [_("Finish"),@configtabs.size()-1]].each{|action,linkindex| if $cgi.include?(action) @html.header["status"] = "REDIRECT" @html.header["Cache-Control"] = "no-cache" @html.header["Location"] = @configtabs[linkindex][1] @html << _("All changes were saved successfully.") + " <a href=\"#{@configtabs[linkindex][1]}\">" + _("Proceed!") + "</a>" out exit end } end def out @html << wizzard_nav if @is_config @html.add_cookie("lang",@cgi["lang"],"/",Time.now + (1*60*60*24*365)) if @cgi.include?("lang") @html << "</div>" # content @html << "<div id='languageChooser'><ul>" lang = [# sorted by native speakers according to English Wikipedia ["es", "Español"],# 480 million native speakers (2018) ["en", "English"],# 360–400 million (2006) ["ar", "اَلْعَرَبِيَّة"],# 310 million, all varieties (2011–2016) ["pt_BR", "Português brasileiro"],# 205 million (2011) ["de", "Deutsch"],# 95 million (2014) ["it", "Italiano"],# 90 million (2012) ["fr", "Français"],# 76.8 million (2014) ["nl", "Nederlands"],# 24 million (2016) ["sw", "Kiswahili"],# 15 million (2012) ["hu", "Magyar"],# 13 million (2002–2012) ["sv", "Svenska"],# 10 million (2018) ["cs", "Česky"],# 10.7 million (2015) ["da", "Dansk"],# 5.5 million (2012) ["fi", "Finnish"],# 5.4 million (2009–2012) ["he", "עִבְרִית"],# 5 million (2017) ["no", "Norsk"],# 4.32 million (2012) ["ca", "Català"],# 4.1 million (2012) ["gl", "Galego"],# 2.4 million (2012) ["et", "Eesti"],# 1.1 million (2012) ["eo", "Esperanto"]# estimated 1000 to several thousand (2016) ] unless @hide_lang_chooser lang.each{|short,long| if short == GetText.locale.to_s @html << "<li class='lang'>#{long}</li>" else @html << "<li class='lang'><a href='?lang=#{short}'>#{long}</a></li>" end } end @html << "</ul></div>" # languageChooser @html << "</div>" # main $conf.footer.each{|f| @html << f } @extensions.each{|e| if File.exists?("#{@basedir}/extensions/#{e}/main.rb") $current_ext_dir = e require "#{@basedir}/extensions/#{e}/main" end } @html << "</body>" @html.out(@cgi) end def <<(htmlbodytext) @html << htmlbodytext end end