initial commit master
authorSebastian <basti@notizbuch>
Thu, 24 May 2012 12:58:39 +0000 (14:58 +0200)
committerSebastian <basti@notizbuch>
Thu, 24 May 2012 13:06:57 +0000 (15:06 +0200)
'music', 'art' are usable
'index', 'webpage', 'litterature' are not yet implemented or dummies
works with (slightly modified) starter-package by Piratenpartei Bremen
(see www.kulturtankstelle.net)

23 files changed:
README.txt [new file with mode: 0644]
cgi-bin/kt [new file with mode: 0755]
kulturtankstelle/config.xml [new file with mode: 0644]
kulturtankstelle/header.jpg [new file with mode: 0644]
kulturtankstelle/licenses/cc-by-nc-nd.png [new file with mode: 0644]
kulturtankstelle/licenses/cc-by-nc-sa.png [new file with mode: 0644]
kulturtankstelle/licenses/cc-by-nc.png [new file with mode: 0644]
kulturtankstelle/licenses/cc-by-nd.png [new file with mode: 0644]
kulturtankstelle/licenses/cc-by-sa.png [new file with mode: 0644]
kulturtankstelle/licenses/cc-by.png [new file with mode: 0644]
kulturtankstelle/modules/KTart.pm [new file with mode: 0644]
kulturtankstelle/modules/KTmain.pm [new file with mode: 0644]
kulturtankstelle/modules/KTmusic.pm [new file with mode: 0644]
kulturtankstelle/style.css [new file with mode: 0644]
kulturtankstelle/templates/kt_art_details.tmpl [new file with mode: 0644]
kulturtankstelle/templates/kt_art_overview.tmpl [new file with mode: 0644]
kulturtankstelle/templates/kt_footer.tmpl [new file with mode: 0644]
kulturtankstelle/templates/kt_header.tmpl [new file with mode: 0644]
kulturtankstelle/templates/kt_index.tmpl [new file with mode: 0644]
kulturtankstelle/templates/kt_language_selector.tmpl [new file with mode: 0644]
kulturtankstelle/templates/kt_menu.tmpl [new file with mode: 0644]
kulturtankstelle/templates/kt_music_details.tmpl [new file with mode: 0644]
kulturtankstelle/templates/kt_music_overview.tmpl [new file with mode: 0644]

diff --git a/README.txt b/README.txt
new file mode 100644 (file)
index 0000000..cddc9da
--- /dev/null
@@ -0,0 +1,75 @@
+Kulturtankstelle
+================
+
+Kontakt: <svenska-pirat@arcor.de> oder Mailingliste unter
+         <kulturtankstelle@lists.piratenpartei-bremen.de>
+
+Inhalte: getestet mit leicht verändertem Starter-Paket der Bremer Piraten
+
+- cgi-bin/kt:
+--- Hauptprogramm der Kulturtankstelle
+--- Perl, CGI-Script
+--- verwendet HTML::Template, XML::Simple, (optional) CGI::Carp
+--- Anpassungen nötig:
+----- 'use lib' muss auf Modulpfad zeigen
+----- $configfile muss auf config.xml zeigen
+
+- kulturtankstelle/config.xml:
+--- zentrale Konfigurationsdatei der Kulturtankstelle
+
+--- enthält Pfade:
+----- root:       Programmdateien im Dateisystem
+----- webroot:    Programmdateien im HTTP-Server
+----- content:    Inhalte im Dateisystem
+----- webcontent: Inhalte im HTTP-Server
+
+--- enthält Menüeinträge:
+----- 'id' ist ein frei wählbarer Eintrag im Menü
+----- 'type' ist ein vorgefertigter Seitentyp:
+------- "index":       Standardeintrag, derzeit nicht implementiert
+------- "music":       Albenübersicht und Albumdetails
+------- "art":         Übersicht aller Kollektionen und Details einer Kollektion
+------- "litterature": eBooks, derzeit nicht implementiert
+------- "webpage":     lokal vorhandene Webseite, derzeit nicht implementiert
+----- 'folder' enthält den Pfad relativ zum Ordner für die Inhalte
+
+--- enthält Übersetzungen aller im Programm verwendeten Strings
+
+- kulturtankstelle/style.css:
+--- zentrales Stylesheet
+
+- kulturtankstelle/licenses/*:
+--- Bilder und HTML-Lizenztexte der CC-Lizenzen
+--- jeder Content-Teil darf aber auch eigene Lizenzen besitzen
+
+- kulturtankstelle/templates/*:
+--- Templates aller Seiten
+--- siehe Dokumentation zu HTML::Template für Aufbau
+
+- kulturtankstelle/modules/*
+--- enthält die "Intelligenz" der Kulturtankstelle
+
+--- KTmain.pm:
+----- read_config()    => liest und parst config.xml
+----- read_templates() => liest alle Templates ein
+----- print_header()   => zeigt kt_header.tmpl an
+----- print_footer()   => zeigt kt_footer.tmpl
+----- print_menu()     => zeigt kt_menu.tmpl an
+----- print_language_selector() => zeigt kt_language_selector.tmpl an
+----- print_content()  => verweist auf print_content() im entsprechenden Modul
+----- get_language()   => wählt Sprache aus (URL, Browser-Settings oder 'de')
+----- get_string()     => übersetzt String
+----- get_license()    => erkennt bekannte Lizenzen und gibt Bild/URL zurück
+
+--- KTmusic.pm:
+----- init()           => initialisiert Musik-Teil
+----- print_content()  => verweist auf print_overview oder print_albumdetails
+----- print_overview() => zeigt Albumliste
+----- print_albumdetails() => zeigt Albumdetails
+----- get_time()       => zerlegt Sekundenanzahl in lesbaren String
+
+--- KTart.pm:
+----- init()           => initialisiert Kunst-Teil
+----- print_content()  => verweist auf print_overview oder print_details
+----- print_overview() => zeigt Liste aller Kollektionen
+----- print_details()  => zeigt Details einer Kollektion
diff --git a/cgi-bin/kt b/cgi-bin/kt
new file mode 100755 (executable)
index 0000000..f0d135e
--- /dev/null
@@ -0,0 +1,35 @@
+#!/usr/bin/perl -w
+use strict;
+use 5.010;
+
+# Standard perl modules
+use CGI::Carp 'fatalsToBrowser';       # no more HTTP 500 errors :-)
+use HTML::Template;
+use XML::Simple;
+use Data::Dumper;
+
+# Kulturtankstelle modules
+use lib '/srv/www/kulturtankstelle/modules';
+use KTmain;
+use KTmusic;
+use KTart;
+
+# Global variables
+my $configfile = '/srv/www/kulturtankstelle/config.xml';
+my $config;            # XML configuration file
+my $templates;         # HTML templates
+
+# Initialization
+print "Content-Type: text/html\r\n\r\n";
+$config = &KTmain::read_config($configfile) or die "Error reading config";
+$templates = &KTmain::read_templates($config) or die "Error reading templates";
+
+&KTmusic::init($config);
+&KTart::init($config);
+
+# Send out document
+&KTmain::print_header($config, $templates->{header});
+&KTmain::print_menu($config, $templates->{menu});
+&KTmain::print_language_selector($config, $templates->{language_selector});
+&KTmain::print_content($config, $templates);
+&KTmain::print_footer($config, $templates->{footer});
diff --git a/kulturtankstelle/config.xml b/kulturtankstelle/config.xml
new file mode 100644 (file)
index 0000000..b2a6f90
--- /dev/null
@@ -0,0 +1,71 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<kulturtankstelle>
+       <dirs>
+               <root>/srv/www/kulturtankstelle/</root>
+               <webroot>/kulturtankstelle/</webroot>
+               <content>/srv/www/data/</content>
+               <webcontent>/data/</webcontent>
+       </dirs>
+
+       <menu>
+               <entry id="startpage" type="index" />
+               <entry id="music" type="music" folder="music/" />
+               <entry id="art" type="art" folder="art/" />
+               <entry id="ebooks" type="litterature" folder="litterature/" />
+               <entry id="information" type="webpage" folder="information/" />
+       </menu>
+
+       <translation>
+               <de>
+                       <startpage>Startseite</startpage>
+                       <music>Musik</music>
+                       <art>Kunst</art>
+                       <ebooks>E-Books</ebooks>
+                       <information>Informationen</information>
+                       <license>Lizenz</license>
+                       <music_tracks>Stücke</music_tracks>
+                       <music_artist>Artist</music_artist>
+                       <music_contents>Musik: Übersicht</music_contents>
+                       <music_details>Musik: Details</music_details>
+                       <music_track>Track</music_track>
+                       <music_title>Titel</music_title>
+                       <music_length>Länge</music_length>
+                       <music_fetchalbum>[ Album herunterladen ]</music_fetchalbum>
+                       <music_download>Download</music_download>
+                       <music_downloadtext>[ laden ]</music_downloadtext>
+                       <art_contents>Kunst: Übersicht</art_contents>
+                       <art_details>Kunst: Details</art_details>
+                       <art_artist>Künster</art_artist>
+                       <art_pieces>Stücke</art_pieces>
+                       <art_year>Entstehungsjahr</art_year>
+                       <art_description>Beschreibung</art_description>
+                       <art_fetchcollection>[ Kollection herunterladen ]</art_fetchcollection>
+               </de>
+
+               <en>
+                       <startpage>start page</startpage>
+                       <music>music</music>
+                       <art>art</art>
+                       <ebooks>e-books</ebooks>
+                       <information>information</information>
+                       <license>license</license>
+                       <music_tracks>tracks</music_tracks>
+                       <music_artist>artist</music_artist>
+                       <music_contents>music: overview</music_contents>
+                       <music_details>music: album details</music_details>
+                       <music_track>track</music_track>
+                       <music_title>title</music_title>
+                       <music_length>length</music_length>
+                       <music_download>download</music_download>
+                       <music_downloadtext>[ get ]</music_downloadtext>
+                       <music_fetchalbum>[ fetch album ]</music_fetchalbum>
+                       <art_contents>art: overview</art_contents>
+                       <art_details>art: collection details</art_details>
+                       <art_artist>artist</art_artist>
+                       <art_pieces>pieces</art_pieces>
+                       <art_year>year</art_year>
+                       <art_description>description</art_description>
+                       <art_fetchcollection>[ fetch collection ]</art_fetchcollection>
+               </en>
+       </translation>
+</kulturtankstelle>
diff --git a/kulturtankstelle/header.jpg b/kulturtankstelle/header.jpg
new file mode 100644 (file)
index 0000000..1414c33
Binary files /dev/null and b/kulturtankstelle/header.jpg differ
diff --git a/kulturtankstelle/licenses/cc-by-nc-nd.png b/kulturtankstelle/licenses/cc-by-nc-nd.png
new file mode 100644 (file)
index 0000000..072f8cd
Binary files /dev/null and b/kulturtankstelle/licenses/cc-by-nc-nd.png differ
diff --git a/kulturtankstelle/licenses/cc-by-nc-sa.png b/kulturtankstelle/licenses/cc-by-nc-sa.png
new file mode 100644 (file)
index 0000000..ed028fe
Binary files /dev/null and b/kulturtankstelle/licenses/cc-by-nc-sa.png differ
diff --git a/kulturtankstelle/licenses/cc-by-nc.png b/kulturtankstelle/licenses/cc-by-nc.png
new file mode 100644 (file)
index 0000000..54ebdfb
Binary files /dev/null and b/kulturtankstelle/licenses/cc-by-nc.png differ
diff --git a/kulturtankstelle/licenses/cc-by-nd.png b/kulturtankstelle/licenses/cc-by-nd.png
new file mode 100644 (file)
index 0000000..35eca20
Binary files /dev/null and b/kulturtankstelle/licenses/cc-by-nd.png differ
diff --git a/kulturtankstelle/licenses/cc-by-sa.png b/kulturtankstelle/licenses/cc-by-sa.png
new file mode 100644 (file)
index 0000000..c67509f
Binary files /dev/null and b/kulturtankstelle/licenses/cc-by-sa.png differ
diff --git a/kulturtankstelle/licenses/cc-by.png b/kulturtankstelle/licenses/cc-by.png
new file mode 100644 (file)
index 0000000..ecd2abc
Binary files /dev/null and b/kulturtankstelle/licenses/cc-by.png differ
diff --git a/kulturtankstelle/modules/KTart.pm b/kulturtankstelle/modules/KTart.pm
new file mode 100644 (file)
index 0000000..47d2c79
--- /dev/null
@@ -0,0 +1,311 @@
+#!/usr/bin/perl -w
+use strict;
+use 5.010;
+
+package KTart;
+
+# package global art data
+# $art->{$id}->{titles} is array of collection titles
+# $art->{$id}->{collections} is hash of collection information hashes
+my $art;
+
+# initialize KTart module (fill $art)
+# in:  $config
+# out: true or undef
+sub init
+{
+       my $c;
+
+       unless($c = shift) {
+               say "Error: ".(caller 0)[3].": no config";
+               return;
+       }
+
+       # include every menu entry with type='art'
+       foreach my $entry (@{$c->{menu}->{entry}}) {
+               next unless ($entry->{id} eq 'art');
+
+               # fetch all collection folders
+               my $basepath = $c->{dirs}->{content} . $entry->{folder};
+               unless(opendir(COLLECTIONS, $basepath)) {
+                       say "Error: ".(caller 0)[3].
+                                               ": can't open $basepath: $!";
+                       return;
+               }
+               my @folders = readdir(COLLECTIONS);
+               closedir(COLLECTIONS);
+
+               # read and parse $folder/info.xml
+               foreach my $folder(sort @folders) {
+                       next if $folder =~ /^\.+$/;
+
+                       # parse collection information file
+                       my $infofile = "$basepath/$folder/info.xml";
+                       my $collection = eval { XML::Simple::XMLin(
+                               $infofile, KeyAttr => []) };
+                       if($@) {
+                               say "Error: ".(caller 0)[3].": $infofile: $@";
+                               next;
+                       }
+
+                       # TODO: check data structures more thorough
+                       unless($collection->{collectionname}) {
+                               say "Error: ".(caller 0)[3].
+                                       "$infofile contains no collectionname";
+                               next;
+                       }
+
+                       # fill in collection title, folder and all other data
+                       my $title = $collection->{collectionname};
+                       push (@{$art->{$entry->{id}}->{titles}}, $title);
+                       $art->{$entry->{id}}->{collections}->{$title} =
+                                                               $collection;
+                       $art->{$entry->{id}}->{collections}->{$title}->{path} =
+                                                               $folder;
+               }
+       }
+}
+
+# check for art area overview or collection detail page
+# in:  $config, $entry (menu entry from $config), $templates
+# out: nothing
+sub print_content
+{
+       my $c;
+       my $entry;
+       my $templates;
+
+       unless($c = shift) {
+               say "Error: ".(caller 0)[3].": no config";
+               return;
+       }
+
+       unless($entry = shift) {
+               say "Error: ".(caller 0)[3].": no entry";
+               return;
+       }
+
+       unless($templates = shift) {
+               say "Error: ".(caller 0)[3].": no templates";
+               return;
+       }
+
+       # check for 'collection' parameter in QUERY_STRING
+       if($ENV{QUERY_STRING}) {
+               foreach(split(/;/, $ENV{QUERY_STRING})) {
+                       (my $param, my $val) = split(/=/, $_);
+                       next unless ($param =~ /^collection$/);
+
+                       # found -> print collection detail page
+                       &KTart::print_details(
+                               $c,
+                               $entry,
+                               $templates,
+                               $val,
+                       );
+                       return;
+               }
+       }
+
+       # not found -> print collection overview
+       &KTart::print_overview(
+               $c,
+               $entry,
+               $templates,
+       );
+}
+
+# print collection overview
+# in:  $config, $entry (menu entry from $config), $templates
+# out: nothing
+sub print_overview
+{
+       my $c;
+       my $entry;
+       my $templates;
+
+       unless($c = shift) {
+               say "Error: ".(caller 0)[3].": no config";
+               return;
+       }
+
+       unless($entry = shift) {
+               say "Error: ".(caller 0)[3].": no entry";
+               return;
+       }
+
+       unless($templates = shift) {
+               say "Error: ".(caller 0)[3].": no templates";
+               return;
+       }
+
+       # set global variables
+       $templates->{art_overview}->param(
+               PAGETITLE => &KTmain::get_string($c, 'art_contents'),
+               SCRIPT => $ENV{SCRIPT_NAME},
+               LANGUAGE => &KTmain::get_language($c),
+               MENUID => $entry->{id},
+               MENUTITLE => &KTmain::get_string($c, $entry->{id}),
+               PIECES => &KTmain::get_string($c, 'art_pieces'),
+               ARTIST => &KTmain::get_string($c, 'art_artist'),
+               LICENSE => &KTmain::get_string($c, 'license'),
+       );
+
+       # set per-collection variables
+       my @collections = @{$art->{$entry->{id}}->{titles}};
+       my @loopdata;
+       for my $index (0 .. $#collections) {
+               my %data;
+               my $info = $art->{$entry->{id}}->{collections}->{$collections[$index]};
+
+               $data{COLLECTIONID} = $index;
+               $data{COLLECTIONTITLE} = $collections[$index];
+               $data{COLLECTIONCOVER} = $c->{dirs}->{webcontent} .
+                                       $entry->{folder} .
+                                       $info->{path} .
+                                       "/cover.jpg";
+               $data{PIECESCOUNT} = $info->{collectionimagecount};
+               $data{ARTISTNAME} = $info->{collectionartist};
+
+               # fill in license data
+               (my $url, my $img) =
+                       &KTmain::get_license($c, $info->{collectionlicense});
+               if(($url) && ($img)) {
+                       $data{LICENSEURL} = $url;
+                       $data{LICENSETEXT} = "<img src=\"$img\">";
+               } else {
+                       $data{LICENSEURL} = $c->{dirs}->{webcontent} .
+                                               $entry->{folder} .
+                                               $info->{path} . "/" .
+                                               $info->{collectionlicense};
+                       $data{LICENSETEXT} =
+                                       &KTmain::get_string($c, 'license');
+               }
+
+               push(@loopdata, \%data);
+       }
+       $templates->{art_overview}->param(COLLECTIONLOOP => \@loopdata);
+
+       print $templates->{art_overview}->output;
+}
+
+# print collection details
+# in:  $config, $entry, $templates, $collectionid
+#      ($collectionid: index in $art->{id]->{titles} array)
+# out: nothing
+sub print_details
+{
+       my $c;
+       my $entry;
+       my $templates;
+       my $collectionid;
+
+       unless($c = shift) {
+               say "Error: ".(caller 0)[3].": no config";
+               return;
+       }
+
+       unless($entry = shift) {
+               say "Error: ".(caller 0)[3].": no entry";
+               return;
+       }
+
+       unless($templates = shift) {
+               say "Error: ".(caller 0)[3].": no templates";
+               return;
+       }
+
+       unless(defined($collectionid = shift)) {
+               say "Error: ".(caller 0)[3].": no albumid";
+               return;
+       }
+
+       my $title = $art->{$entry->{id}}->{titles}->[$collectionid];
+       my $info = $art->{$entry->{id}}->{collections}->{$title};
+
+       # set global variables
+       $templates->{art_details}->param(
+               # general
+               PAGETITLE => &KTmain::get_string($c, 'art_details'),
+               SCRIPT => $ENV{SCRIPT_NAME},
+               LANGUAGE => &KTmain::get_language($c),
+               MENUID => $entry->{id},
+
+               # translations
+               MENUTITLE => &KTmain::get_string($c, $entry->{id}),
+               PIECES => &KTmain::get_string($c, 'art_pieces'),
+               ARTIST => &KTmain::get_string($c, 'art_artist'),
+               LICENSE => &KTmain::get_string($c, 'license'),
+#              TITLE => &KTmain::get_string($c, 'art_title'),
+#              LENGTH => &KTmain::get_string($c, 'art_length'),
+               DESCRIPTION => &KTmain::get_string($c, 'art_description'),
+               YEAR => &KTmain::get_string($c, 'art_year'),
+               FETCHCOLLECTION => &KTmain::get_string($c, 'art_fetchcollection'),
+#              DOWNLOAD => &KTmain::get_string($c, 'art_download'),
+#              DOWNLOADTEXT => &KTmain::get_string($c, 'art_downloadtext'),
+
+               # collection specific
+               COLLECTIONID => $collectionid,
+               COLLECTIONTITLE => $title,
+               PIECESCOUNT => $info->{collectionimagecount},
+               ARTISTNAME => $info->{collectionartist},
+               LICENSETEXT => $info->{collectionlicense},
+               COLLECTIONCOVER => $c->{dirs}->{webcontent} .
+                               $entry->{folder} .
+                               $info->{path} .
+                               "/cover.jpg",
+               # TODO: dynamically create zipfile
+               FETCHCOLLECTIONLINK => "javascript:alert(\'not implemented\')",
+       );
+
+       # fill in license data
+       (my $url, my $img) =
+               &KTmain::get_license($c, $info->{albumlicense});
+       if(($url) && ($img)) {
+               $templates->{art_details}->param(
+                       LICENSEURL => $url,
+                       LICENSETEXT => "<img src=\"$img\">",
+               );
+       } else {
+               $templates->{art_details}->param(
+                       LICENSEURL => $c->{dirs}->{webcontent} .
+                               $entry->{folder} .
+                               $info->{path} . "/" .
+                               $info->{collectionlicense},
+                       LICENSETEXT =>
+                               &KTmain::get_string($c, 'license'),
+               );
+       }
+
+       # set collection-specific variables
+       my @loopdata;
+       foreach my $image (@{$info->{image}}) {
+               my %imagedata;
+
+               $imagedata{IMAGETITLE} = $image->{title};
+               $imagedata{IMAGEFILE} = $c->{dirs}->{webcontent} .
+                                               $entry->{folder} .
+                                               $info->{path} . "/" .
+                                               $image->{filename};
+
+               $imagedata{IMAGEFILE_THUMB} = $c->{dirs}->{webcontent} .
+                                               $entry->{folder} .
+                                               $info->{path} . "/" .
+                                               # FIXME: thumbnail filename!
+                                               substr($image->{filename}, 0, -4).
+                                               "_tn.jpg";
+
+               $imagedata{IMAGE_THUMBWIDTH} = $image->{thumbnailsizex};
+               $imagedata{IMAGE_THUMBHEIGHT} = $image->{thumbnailsizey};
+               $imagedata{ARTISTNAME} = $image->{artist};
+               $imagedata{CREATIONYEAR} = $image->{year};
+               $imagedata{DESCRIPTIONTEXT} = $image->{description};
+
+               push(@loopdata, \%imagedata);
+       }
+       $templates->{art_details}->param(IMAGELOOP => \@loopdata);
+
+       print $templates->{art_details}->output;
+}
+
+1;
diff --git a/kulturtankstelle/modules/KTmain.pm b/kulturtankstelle/modules/KTmain.pm
new file mode 100644 (file)
index 0000000..fa4ed5e
--- /dev/null
@@ -0,0 +1,400 @@
+#!/usr/bin/perl -w
+use strict;
+use 5.010;
+
+package KTmain;
+
+# read and parse xml configuration file
+# in:  $filename - filename of XML file
+# out: $config   - hash reference with parsed contents
+sub read_config
+{
+       my $filename;
+       my $config;
+
+       unless($filename = shift) {
+               say "Error: ".(caller 0)[3].": no configuration file";
+               return;
+       }
+
+       $config = eval { main::XMLin("$filename", KeyAttr => [ ] ); };
+       if($@) {
+               say "Error: ".(caller 0)[3].": parsing failed: $@";
+               return;
+       }
+
+       return $config;
+}
+
+# read all template files from template directory ($c->{dirs}->{templates})
+# in:  $config    - global configuration
+# out: $templates - hash reference with template objects
+sub read_templates
+{
+       my $c;
+
+       unless($c = shift) {
+               say "Error: ".(caller 0)[3].": no configuration";
+               return;
+       }
+
+       unless($c->{dirs}->{root}) {
+               say "Error: ".(caller 0)[3].": no template directory";
+               return;
+       }
+
+       my $dir = "$c->{dirs}->{root}/templates";
+       unless(opendir(TEMPLATES, $dir)) {
+               say "Error: ".(caller 0)[3].": $!";
+               return;
+       }
+
+       my %t;
+       while(readdir(TEMPLATES)) {
+               next unless /^kt_([0-9a-zA-Z_]+)\.tmpl$/;
+               $t{$1} = HTML::Template->new(
+                       filename => "$dir/$_",
+                       loop_context_vars => 1,
+                       global_vars => 1,
+               );
+       }
+       closedir(TEMPLATES);
+
+       return \%t;
+}
+
+# print header from template
+# in:  $config, $template
+# out: nothing
+sub print_header
+{
+       my $c;
+       my $t;
+
+       unless($c = shift) {
+               say "Error: ".(caller 0)[3].": no config";
+               return;
+       }
+
+       unless($t = shift) {
+               say "Error: ".(caller 0)[3].": no template";
+               return;
+       }
+
+       $t->param(WEBROOT => "$c->{dirs}->{webroot}");
+       print $t->output;
+}
+
+# print footer from template
+# in:  $config, $template
+# out: nothing
+sub print_footer
+{
+       my $c;
+       my $t;
+
+       unless($c = shift) {
+               say "Error: ".(caller 0)[3].": no config";
+               return;
+       }
+
+       unless($t = shift) {
+               say "Error: ".(caller 0)[3].": no template";
+               return;
+       }
+
+       print $t->output;
+}
+
+# print menu from template
+# in:  $config, $template
+# out: nothing
+sub print_menu
+{
+       my $c;
+       my $t;
+
+       unless($c = shift) {
+               say "Error: ".(caller 0)[3].": no config";
+               return;
+       }
+
+       unless($t = shift) {
+               say "Error: ".(caller 0)[3].": no template";
+               return;
+       }
+
+       my @entries;
+       foreach(@{$c->{menu}->{entry}}) {
+               push (@entries, {
+                       TEXT => &KTmain::get_string($c, $_->{id}),
+                       URL  => "$ENV{SCRIPT_NAME}?".
+                               "lang=".&KTmain::get_language($c).";".
+                               "id=$_->{id}",
+               });
+       }
+
+       $t->param(MENU_ENTRIES => [ @entries ]);
+       print $t->output;
+}
+
+# print language selector
+# in:  $config, $template
+# out: nothing
+sub print_language_selector
+{
+       my $c;
+       my $t;
+
+       unless($c = shift) {
+               say "Error: ".(caller 0)[3].": no config";
+               return;
+       }
+
+       unless($t = shift) {
+               say "Error: ".(caller 0)[3].": no template";
+               return;
+       }
+
+       # fetch all request parameters, filter "lang" parameter
+       my @newparams;
+       if($ENV{REQUEST_URI}) {
+               (undef, my $params) = split(/\?/, $ENV{REQUEST_URI});
+               foreach(split(/;/, $params)) {
+                       (my $param, my $val) = split(/=/, $_);
+                       next if $param =~ /^lang$/;
+                       $val = "" unless $val;
+                       push(@newparams, "$param=$val");
+               }
+       }
+
+       # find all languages
+       my $script = $ENV{SCRIPT_NAME};
+       my @languages;
+       foreach my $lang (sort keys $c->{translation}) {
+               push (@languages, {
+                       LANG => $lang,
+                       URI => "$script?lang=$lang;".join(";", @newparams),
+               });
+
+               my $uri = "$script?lang=$lang;".join(";", @newparams);
+       }
+       $t->param(LANGUAGES => [ @languages ]);
+       print $t->output;
+}
+
+# select content printing function based on 'id'
+# in:  $config and $templates (all of them)
+# out: nothing
+sub print_content
+{
+       my $c;
+       my $templates;
+
+       unless($c = shift) {
+               say "Error: ".(caller 0)[3].": no configuration";
+               return;
+       }
+
+       unless($templates = shift) {
+               say "Error: ".(caller 0)[3].": no templates";
+               return;
+       }
+
+       # get page id
+       my $id;
+       if($ENV{QUERY_STRING}) {
+               foreach(split(/;/, $ENV{QUERY_STRING})) {
+                       (my $param, my $val) = split(/=/, $_);
+                       next unless ($param =~ /^id$/);
+                       $id = $val;
+               }
+       }
+
+       # get page type
+       my $entry;
+       foreach(@{$c->{menu}->{entry}}) {
+               if($id eq $_->{id}) {
+                       $entry = $_;
+               }
+       }
+
+       # switch/case depending on page type
+       given($entry->{type}) {
+               when ('music') {
+                       # music area
+                       &KTmusic::print_content(
+                               $c,
+                               $entry,
+                               $templates);
+                       }
+
+               when ('art') {
+                       # art area
+                       &KTart::print_content(
+                               $c,
+                               $entry,
+                               $templates);
+                       }
+
+               when ('litterature') {
+                       # litterature area
+                       &KTlitterature::print_content(
+                               $c,
+                               $entry,
+                               $templates);
+                       }
+
+               when ('webpage') {
+                       # webpage area
+                       say "WEBPAGE at $entry->{folder}";
+                       }
+
+               default {
+                       # fallback: index page from template
+                       print $templates->{index}->output;
+                       }
+       }
+}
+
+sub get_language
+{
+       my $c;
+
+       unless($c = shift) {
+               say "Error: ".(caller 0)[3].": no config";
+               return;
+       }
+
+       # check QUERY_STRING for "lang="
+       if($ENV{QUERY_STRING}) {
+               foreach(split(/;/, $ENV{QUERY_STRING})) {
+                       (my $param, my $val) = split(/=/);
+                       next unless ($param =~ /^lang$/);
+
+                       if($c->{translation}->{$val}) {
+                               return $val;
+                       }
+               }
+       }
+
+       # check HTTP_ACCEPT_LANGUAGE
+       if($ENV{HTTP_ACCEPT_LANGUAGE}) {
+               my %ll;
+               foreach(split(/,/, $ENV{HTTP_ACCEPT_LANGUAGE})) {
+                       (my $l, my $q) = split(/;q=/);
+                       $q = 1 unless $q;
+                       $ll{$l} = $q;
+               }
+
+               # sort languages by q values, descending
+               foreach( sort { $ll{$b} <=> $ll{$a} } (keys %ll) ) {
+                       if($c->{translation}->{$_}) {
+                               return $_;
+                       }
+               }
+       }
+
+       # fallback
+       return "de";
+}
+
+# get translated string
+# in:  $config, $string
+# out: string or undef
+sub get_string
+{
+       my $c;
+       my $s;
+
+       unless($c = shift) {
+               say "Error: ".(caller 0)[3].": no config";
+               return;
+       }
+
+       unless($s = shift) {
+               say "Error: ".(caller 0)[3].": no string";
+               return;
+       }
+
+       my $lang = &KTmain::get_language($c);
+
+       if($c->{translation}->{$lang}->{$s}) {
+               return $c->{translation}->{$lang}->{$s};
+       } else {
+               return "!$s";
+       }
+}
+
+# return license and image file url for known licenses
+# in:  $config, license text (i.e. 'cc__by_nc_sa')
+# out: [url, imageurl] if known license, [undef, undef] else
+sub get_license
+{
+       my $config;
+       my $license;
+
+       unless($config = shift) {
+               say "Error: ".(caller 0)[3].": no config";
+               return;
+       }
+
+       unless($license = shift) {
+               return (undef, undef);
+       }
+
+       given($license) {
+               # CC license: see http://creativecommons.org/licenses/
+               when('cc__by') {        # CC: Attribution
+                       return (
+                               $config->{dirs}->{webroot}.
+                                       "/licenses/cc-by.html",
+                               $config->{dirs}->{webroot}.
+                                       "/licenses/cc-by.png",
+                       );
+               }
+
+               when('cc__by_nc') {     # CC: Attribution, NonCommercial
+                       return (
+                               $config->{dirs}->{webroot}.
+                                       "/licenses/cc-by-nc.html",
+                               $config->{dirs}->{webroot}.
+                                       "/licenses/cc-by-nc.png",
+                       );
+               }
+
+               when('cc__by_nd') {     # CC: Attribution, NoDerivs
+                               $config->{dirs}->{webroot}.
+                                       "/licenses/cc-by-nd.html",
+                               $config->{dirs}->{webroot}.
+                                       "/licenses/cc-by-nd.png",
+               }
+
+               when('cc__by_sa') {     # CC: Attribution, ShareAlike
+                               $config->{dirs}->{webroot}.
+                                       "/licenses/cc-by-sa.html",
+                               $config->{dirs}->{webroot}.
+                                       "/licenses/cc-by-sa.png",
+               }
+
+               when('cc__by_nc_nd') {  # CC: Attrib, NonCommercial, NoDerivs
+                               $config->{dirs}->{webroot}.
+                                       "/licenses/cc-by-nc-nd.html",
+                               $config->{dirs}->{webroot}.
+                                       "/licenses/cc-by-nc-nd.png",
+               }
+
+               when('cc__by_nc_sa') {  # CC: Attrib, NonCommercial, ShareAlike
+                               $config->{dirs}->{webroot}.
+                                       "/licenses/cc-by-nc-sa.html",
+                               $config->{dirs}->{webroot}.
+                                       "/licenses/cc-by-nc-sa.png",
+               }
+
+               default {               # anything else
+                       return [undef, undef];
+               }
+       }
+}
+
+1;
diff --git a/kulturtankstelle/modules/KTmusic.pm b/kulturtankstelle/modules/KTmusic.pm
new file mode 100644 (file)
index 0000000..0704624
--- /dev/null
@@ -0,0 +1,321 @@
+#!/usr/bin/perl -w
+use strict;
+use 5.010;
+
+package KTmusic;
+
+# package global music data
+# $music->{$id}->{titles} is array of album titles
+# $music->{$id}->{albums} is hash of album information hashes
+my $music;
+
+# initialize KTmusic module (create $music)
+# in:  $config
+# out: true or undef
+sub init
+{
+       my $c;
+
+       unless($c = shift) {
+               say "Error: ".(caller 0)[3].": no config";
+               return;
+       }
+
+       # include every menu entry with type='music'
+       foreach my $entry (@{$c->{menu}->{entry}}) {
+               next unless ($entry->{id} eq 'music');
+
+               # fetch all album folders
+               my $basepath = $c->{dirs}->{content} . $entry->{folder};
+               unless(opendir(ALBUMS, $basepath)) {
+                       say "Error: ".(caller 0)[3].
+                                               ": can't open $basepath: $!";
+                       return;
+               }
+               my @folders = readdir(ALBUMS);
+               closedir(ALBUMS);
+
+               # read and parse $folder/info.xml
+               foreach my $folder(sort @folders) {
+                       next if $folder =~ /^\.+$/;
+
+                       # parse album information file
+                       my $infofile = "$basepath/$folder/info.xml";
+                       my $album = eval { XML::Simple::XMLin(
+                               $infofile, KeyAttr => []) };
+                       if($@) {
+                               say "Error: ".(caller 0)[3].": $infofile: $@";
+                               next;
+                       }
+
+                       # TODO: check data structures more thorough
+                       unless($album->{albumtitle}) {
+                               say "Error: ".(caller 0)[3].
+                                       "$infofile contains no album title";
+                               next;
+                       }
+
+                       # fill in album title, folder and all other data
+                       my $title = $album->{albumtitle};
+                       push (@{$music->{$entry->{id}}->{titles}}, $title);
+                       $music->{$entry->{id}}->{albums}->{$title} = $album;
+                       $music->{$entry->{id}}->{albums}->{$title}->{path} =
+                                                                       $folder;
+               }
+       }
+}
+
+# check for music area overview or album detail page
+# in:  $config, $entry (menu entry from $config), $templates
+# out: nothing
+sub print_content
+{
+       my $c;
+       my $entry;
+       my $templates;
+
+       unless($c = shift) {
+               say "Error: ".(caller 0)[3].": no config";
+               return;
+       }
+
+       unless($entry = shift) {
+               say "Error: ".(caller 0)[3].": no entry";
+               return;
+       }
+
+       unless($templates = shift) {
+               say "Error: ".(caller 0)[3].": no templates";
+               return;
+       }
+
+       # check for 'albumid' parameter in QUERY_STRING
+       if($ENV{QUERY_STRING}) {
+               foreach(split(/;/, $ENV{QUERY_STRING})) {
+                       (my $param, my $val) = split(/=/, $_);
+                       next unless ($param =~ /^albumid$/);
+
+                       # found -> print album detail page
+                       &KTmusic::print_albumdetails(
+                               $c,
+                               $entry,
+                               $templates,
+                               $val,
+                       );
+                       return;
+               }
+       }
+
+       # not found -> print album overview
+       &KTmusic::print_overview(
+               $c,
+               $entry,
+               $templates,
+       );
+}
+
+# print album overview
+# in:  $config, $entry (menu entry from $config), $templates
+# out: nothing
+sub print_overview
+{
+       my $c;
+       my $entry;
+       my $templates;
+
+       unless($c = shift) {
+               say "Error: ".(caller 0)[3].": no config";
+               return;
+       }
+
+       unless($entry = shift) {
+               say "Error: ".(caller 0)[3].": no entry";
+               return;
+       }
+
+       unless($templates = shift) {
+               say "Error: ".(caller 0)[3].": no templates";
+               return;
+       }
+
+       # set global variables
+       $templates->{music_overview}->param(
+               PAGETITLE => &KTmain::get_string($c, 'music_contents'),
+               SCRIPT => $ENV{SCRIPT_NAME},
+               LANGUAGE => &KTmain::get_language($c),
+               MENUID => $entry->{id},
+               MENUTITLE => &KTmain::get_string($c, $entry->{id}),
+               TRACKS => &KTmain::get_string($c, 'music_tracks'),
+               ARTIST => &KTmain::get_string($c, 'music_artist'),
+               LICENSE => &KTmain::get_string($c, 'license'),
+       );
+
+       # set per-album variables
+       my @albums = @{$music->{$entry->{id}}->{titles}};
+       my @loopdata;
+       for my $index (0 .. $#albums) {
+               my %albumdata;
+               my $albuminfo =
+                       $music->{$entry->{id}}->{albums}->{$albums[$index]};
+
+               $albumdata{ALBUMID} = $index;
+               $albumdata{ALBUMTITLE} = $albums[$index];
+               $albumdata{ALBUMCOVER} = $c->{dirs}->{webcontent} .
+                                       $entry->{folder} .
+                                       $albuminfo->{path} .
+                                       "/cover.jpg";
+               $albumdata{TRACKCOUNT} = $albuminfo->{albumtrackcount};
+               $albumdata{ARTISTNAME} = $albuminfo->{albumartist};
+               $albumdata{LICENSETEXT} = $albuminfo->{albumlicense};
+
+               # fill in license data
+               (my $url, my $img) =
+                       &KTmain::get_license($c, $albuminfo->{albumlicense});
+               if(($url) && ($img)) {
+                       $albumdata{LICENSEURL} = $url;
+                       $albumdata{LICENSETEXT} = "<img src=\"$img\">";
+               } else {
+                       $albumdata{LICENSEURL} = $c->{dirs}->{webcontent} .
+                                               $entry->{folder} .
+                                               $albuminfo->{path} . "/" .
+                                               $albuminfo->{albumlicense};
+                       $albumdata{LICENSETEXT} =
+                                       &KTmain::get_string($c, 'license');
+               }
+
+               push(@loopdata, \%albumdata);
+       }
+       $templates->{music_overview}->param(ALBUMLOOP => \@loopdata);
+
+       print $templates->{music_overview}->output;
+}
+
+# print album details
+# in:  $config, $entry, $templates, $albumid
+#      ($albumid: index in $music->{id]->{titles} array)
+# out: nothing
+sub print_albumdetails
+{
+       my $c;
+       my $entry;
+       my $templates;
+       my $albumid;
+
+       unless($c = shift) {
+               say "Error: ".(caller 0)[3].": no config";
+               return;
+       }
+
+       unless($entry = shift) {
+               say "Error: ".(caller 0)[3].": no entry";
+               return;
+       }
+
+       unless($templates = shift) {
+               say "Error: ".(caller 0)[3].": no templates";
+               return;
+       }
+
+       unless(defined($albumid = shift)) {
+               say "Error: ".(caller 0)[3].": no albumid";
+               return;
+       }
+
+       my $albumtitle = $music->{$entry->{id}}->{titles}->[$albumid];
+       my $albuminfo = $music->{$entry->{id}}->{albums}->{$albumtitle};
+
+       # set global variables
+       $templates->{music_details}->param(
+               # general
+               PAGETITLE => &KTmain::get_string($c, 'music_details'),
+               SCRIPT => $ENV{SCRIPT_NAME},
+               LANGUAGE => &KTmain::get_language($c),
+               MENUID => $entry->{id},
+
+               # translations
+               MENUTITLE => &KTmain::get_string($c, $entry->{id}),
+               TRACKS => &KTmain::get_string($c, 'music_tracks'),
+               ARTIST => &KTmain::get_string($c, 'music_artist'),
+               LICENSE => &KTmain::get_string($c, 'license'),
+               TRACK => &KTmain::get_string($c, 'music_track'),
+               TITLE => &KTmain::get_string($c, 'music_title'),
+               LENGTH => &KTmain::get_string($c, 'music_length'),
+               DOWNLOAD => &KTmain::get_string($c, 'music_download'),
+               DOWNLOADTEXT => &KTmain::get_string($c, 'music_downloadtext'),
+               FETCHALBUM => &KTmain::get_string($c, 'music_fetchalbum'),
+
+               # album specific
+               ALBUMID => $albumid,
+               ALBUMTITLE => $albumtitle,
+               TRACKCOUNT => $albuminfo->{albumtrackcount},
+               ARTISTNAME => $albuminfo->{albumartist},
+               LICENSETEXT => $albuminfo->{albumlicense},
+               ALBUMCOVER => $c->{dirs}->{webcontent} .
+                               $entry->{folder} .
+                               $albuminfo->{path} .
+                               "/cover.jpg",
+               # TODO: dynamically create zipfile
+               FETCHALBUMLINK => "javascript:alert(\'not implemented\')",
+       );
+
+       # fill in license data
+       (my $url, my $img) =
+               &KTmain::get_license($c, $albuminfo->{albumlicense});
+       if(($url) && ($img)) {
+               $templates->{music_details}->param(
+                       LICENSEURL => $url,
+                       LICENSETEXT => "<img src=\"$img\">",
+               );
+       } else {
+               $templates->{music_details}->param(
+                       LICENSEURL => $c->{dirs}->{webcontent} .
+                               $entry->{folder} .
+                               $albuminfo->{path} . "/" .
+                               $albuminfo->{albumlicense},
+                       LICENSETEXT =>
+                               &KTmain::get_string($c, 'license'),
+               );
+       }
+
+       # set track-specific variables
+       my @loopdata;
+       foreach my $track (@{$albuminfo->{song}}) {
+               my %trackdata;
+
+               $trackdata{TRACKTITLE}  = $track->{title},
+               $trackdata{TRACKLENGTH} = &get_time($track->{playtime}),
+               $trackdata{TRACKPATH}   = $c->{dirs}->{webcontent} .
+                                               $entry->{folder} .
+                                               $albuminfo->{path} . '/' .
+                                               $track->{filename},
+
+               push(@loopdata, \%trackdata);
+       }
+       $templates->{music_details}->param(TRACKLOOP => \@loopdata);
+
+       print $templates->{music_details}->output;
+}
+
+# turn number of seconds into human-readable format m:ss or h:mm:ss
+# in:  $num_seconds
+# out: string or undef
+sub get_time
+{
+       my $seconds;
+       my $output;
+
+       unless($seconds = shift) {
+               say "Error: ".(caller 0)[3].": no seconds";
+               return;
+       }
+
+       (my $sec, my $min, my $hour) = gmtime($seconds);
+       if($hour) {
+               $output = sprintf("%u:%02u:%02u", $hour, $min, $sec);
+       } else {
+               $output = sprintf("%u:%02u", $min, $sec);
+       }
+       return $output;
+}
+
+1;
diff --git a/kulturtankstelle/style.css b/kulturtankstelle/style.css
new file mode 100644 (file)
index 0000000..0271d51
--- /dev/null
@@ -0,0 +1,168 @@
+/* stylesheet fuer kulturtankstelle */
+
+/* main */
+
+body {
+       margin: 0;
+       padding: 0;
+       font-family: sans-serif;
+}
+
+a {
+       font-weight: bold;
+       text-decoration: none;
+       color: black;
+}
+
+a:hover {
+       color: #FF6600;
+}
+
+/* menu */
+
+.menu {
+       background-image: url(header.jpg);
+       background-repeat: no-repeat;
+       background-color: gray;
+       width: 150px;
+       height: 100%;
+       padding-top: 134px;
+       float: left;
+}
+
+.menu ul {
+       list-style: none;
+       padding: 5px;
+}
+
+.menu ul a {
+       display: block;
+       width: 100%;
+       border: 1px solid black;
+       border-left-color: white;
+       border-top-color: white;
+       background-color: silver;
+}
+
+.menu ul a:hover {
+       width: 100%;
+       border-color: white;
+       border-left-color: black;
+       border-top-color: black;
+       background-color: silver;
+}
+
+/* content */
+
+.content {
+       position: absolute;
+       left: 150px;
+       width: 80%;
+       margin: 0;
+       padding-top: 20px;
+       padding-right: 10px;
+       padding-bottom: 20px;
+       padding-left: 10px;
+}
+
+.content_header {
+       font-size: 16px;
+       font-weight: bold;
+       padding-top: 50px;
+       padding-bottom: 50px;
+}
+
+.content_linkpath {
+       font-size: 10px;
+}
+
+.language_selector {
+       text-align: right;
+       font-size: 12pt;
+}
+
+/* music */
+
+.music_cover {
+       border: 1px solid black;
+       float: left;
+       margin-right: 10px;
+       width: 100px;
+       height: 100px;
+}
+
+.music_album {
+       height: 105px;
+       font-size: 12px;
+}
+
+.music_albumtitle {
+       font-size: 16px;
+       font-weight: bold;
+       padding-bottom: 20px;
+}
+
+.music_content table {
+       border-style: solid;
+       border-width: 1px;
+}
+
+.music_content tr#rowhead {
+       background-color: #c0c0c0;
+}
+
+.music_content tr#row0 {
+       background-color: #ffffff;
+}
+
+.music_content tr#row1 {
+       background-color: #e0e0e0;
+}
+
+.music_content td {
+       padding-left: 5px;
+       padding-right: 20px;
+}
+
+.music_content table a {
+       font-weight: normal;
+       text-decoration: underline;
+}
+
+/* art */
+
+.art_cover {
+       border: 1px solid black;
+       float: left;
+       margin-right: 10px;
+       width: 100px;
+       height: 100px;
+}
+
+.art_collection {
+       height: 105px;
+       font-size: 12px;
+}
+
+.art_collectiontitle {
+       font-size: 16px;
+       font-weight: bold;
+       padding-bottom: 20px;
+}
+
+.art_content {
+       font-size: 12px;
+}
+
+.art_image {
+       border: 1px solid black;
+       background-color: #333333;
+       padding: 10px;
+}
+
+.art_imagetitle {
+       font-size: 16px;
+       font-weight: bold;
+       padding-bottom: 20px;
+}
+
diff --git a/kulturtankstelle/templates/kt_art_details.tmpl b/kulturtankstelle/templates/kt_art_details.tmpl
new file mode 100644 (file)
index 0000000..772d2ca
--- /dev/null
@@ -0,0 +1,40 @@
+<div class="content">
+  <div class="content_header">
+    <TMPL_VAR NAME=PAGETITLE>
+  </div>
+
+  <div class="content_linkpath">
+    <a href="<TMPL_VAR NAME=SCRIPT>?lang=<TMPL_VAR NAME=LANGUAGE>">Kulturtankstelle</a> &gt;&gt;
+    <a href="<TMPL_VAR NAME=SCRIPT>?lang=<TMPL_VAR NAME=LANGUAGE>;id=<TMPL_VAR NAME=MENUID>"><TMPL_VAR NAME=MENUTITLE></a> &gt;&gt;
+    <a href="<TMPL_VAR NAME=SCRIPT>?lang=<TMPL_VAR NAME=LANGUAGE>;id=<TMPL_VAR NAME=MENUID>;collection=<TMPL_VAR NAME=COLLECTIONID>"><TMPL_VAR NAME=COLLECTIONTITLE></a>
+  </div>
+
+  <div class="art_collection">
+    <a href="<TMPL_VAR NAME=COLLECTIONCOVER>">
+      <img class="art_cover" src="<TMPL_VAR NAME=COLLECTIONCOVER>" height="100" width="100" alt="<TMPL_VAR NAME=COLLECTIONTITLE>">
+    </a>
+
+    <div class="art_collectiontitle"><TMPL_VAR NAME=COLLECTIONTITLE></div>
+      <TMPL_VAR NAME=ARTIST>: <TMPL_VAR NAME=ARTISTNAME><br />
+      <TMPL_VAR NAME=PIECES>: <TMPL_VAR NAME=PIECESCOUNT><br />
+      <TMPL_VAR NAME=LICENSE>: <a href="<TMPL_VAR NAME=LICENSEURL>"><TMPL_VAR NAME=LICENSETEXT></a><br /><br />
+      <a href="<TMPL_VAR NAME=FETCHCOLLECTIONLINK>"><TMPL_VAR NAME=FETCHCOLLECTION></a><br />
+    </div><br />
+
+    <div class="art_content">
+      <TMPL_LOOP NAME=IMAGELOOP>
+      <div class="art_imagetitle">
+        <TMPL_VAR NAME=IMAGETITLE>
+      </div>
+      <a href="<TMPL_VAR NAME=IMAGEFILE>">
+        <img src="<TMPL_VAR NAME=IMAGEFILE_THUMB>" class="art_image" width="<TMPL_VAR NAME=IMAGE_THUMBWIDTH>" height="<TMPL_VAR NAME=IMAGE_THUMBHEIGHT>">
+      </a><br />
+      <TMPL_VAR NAME=ARTIST>: <TMPL_VAR NAME=ARTISTNAME><br />
+      <TMPL_VAR NAME=YEAR>: <TMPL_VAR NAME=CREATIONYEAR><br />
+      <TMPL_VAR NAME=DESCRIPTION>:<br />
+      <TMPL_VAR NAME=DESCRIPTIONTEXT><br />
+      <br />
+      </TMPL_LOOP>
+    </div>
+  </div>
+</div>
diff --git a/kulturtankstelle/templates/kt_art_overview.tmpl b/kulturtankstelle/templates/kt_art_overview.tmpl
new file mode 100644 (file)
index 0000000..406d94a
--- /dev/null
@@ -0,0 +1,27 @@
+<div class="content">
+  <div class="content_header">
+    <TMPL_VAR NAME=PAGETITLE>
+  </div>
+
+  <div class="content_linkpath">
+    <a href="<TMPL_VAR NAME=SCRIPT>?lang=<TMPL_VAR NAME=LANGUAGE>">Kulturtankstelle</a> &gt;&gt;
+    <a href="<TMPL_VAR NAME=SCRIPT>?lang=<TMPL_VAR NAME=LANGUAGE>;id=<TMPL_VAR NAME=MENUID>"><TMPL_VAR NAME=MENUTITLE></a>
+  </div>
+
+  <TMPL_LOOP NAME=COLLECTIONLOOP>
+  <div class="art_collection">
+    <a href="<TMPL_VAR NAME=SCRIPT>?lang=<TMPL_VAR NAME=LANGUAGE>;id=<TMPL_VAR NAME=MENUID>;collection=<TMPL_VAR NAME=COLLECTIONID>">
+      <img class="art_cover" src="<TMPL_VAR NAME=COLLECTIONCOVER>" height="100" width="100" alt="<TMPL_VAR NAME=COLLECTIONTITLE>">
+    </a>
+
+    <div class="art_collectiontitle">
+      <a href="<TMPL_VAR NAME=SCRIPT>?lang=<TMPL_VAR NAME=LANGUAGE>;id=<TMPL_VAR NAME=MENUID>;collection=<TMPL_VAR NAME=COLLECTIONID>"><TMPL_VAR NAME=COLLECTIONTITLE></a>
+    </div>
+
+    <TMPL_VAR NAME=ARTIST>: <TMPL_VAR NAME=ARTISTNAME><br />
+    <TMPL_VAR NAME=PIECES>: <TMPL_VAR NAME=PIECESCOUNT><br />
+    <TMPL_VAR NAME=LICENSE>: <a href="<TMPL_VAR NAME=LICENSEURL>"><TMPL_VAR NAME=LICENSETEXT></a><br />
+  </div><br />
+  </TMPL_LOOP>
+</div>
+
diff --git a/kulturtankstelle/templates/kt_footer.tmpl b/kulturtankstelle/templates/kt_footer.tmpl
new file mode 100644 (file)
index 0000000..b605728
--- /dev/null
@@ -0,0 +1,2 @@
+  </body>
+</html>
diff --git a/kulturtankstelle/templates/kt_header.tmpl b/kulturtankstelle/templates/kt_header.tmpl
new file mode 100644 (file)
index 0000000..50b4f65
--- /dev/null
@@ -0,0 +1,7 @@
+<html>
+  <head>
+    <title>Kulturtankstelle</title>
+    <link href="<TMPL_VAR NAME=WEBROOT>/style.css" rel="stylesheet" type="text/css" />
+  </head>
+
+  <body>
diff --git a/kulturtankstelle/templates/kt_index.tmpl b/kulturtankstelle/templates/kt_index.tmpl
new file mode 100644 (file)
index 0000000..24ea4e1
--- /dev/null
@@ -0,0 +1,7 @@
+<div class="content">
+  <div class="content_header">
+    Kulturtankstelle
+  </div>
+
+  Hier kommt ein sch&ouml;ner Willkommengru&szlig; hin!
+</div>
diff --git a/kulturtankstelle/templates/kt_language_selector.tmpl b/kulturtankstelle/templates/kt_language_selector.tmpl
new file mode 100644 (file)
index 0000000..d8dfe03
--- /dev/null
@@ -0,0 +1,3 @@
+<div class="language_selector"><TMPL_LOOP NAME=LANGUAGES>
+  <a href="<TMPL_VAR NAME=URI>"><TMPL_VAR NAME=LANG></a></TMPL_LOOP>
+</div>
diff --git a/kulturtankstelle/templates/kt_menu.tmpl b/kulturtankstelle/templates/kt_menu.tmpl
new file mode 100644 (file)
index 0000000..7039a82
--- /dev/null
@@ -0,0 +1,7 @@
+<div class="menu">
+  <ul><TMPL_LOOP NAME="MENU_ENTRIES">
+      <li>
+        <a href="<TMPL_VAR NAME=URL>"><TMPL_VAR ESCAPE=HTML NAME=TEXT></a>
+      </li></TMPL_LOOP>
+  </ul>
+</div>
diff --git a/kulturtankstelle/templates/kt_music_details.tmpl b/kulturtankstelle/templates/kt_music_details.tmpl
new file mode 100644 (file)
index 0000000..8d5e6ef
--- /dev/null
@@ -0,0 +1,50 @@
+<div class="content">
+  <div class="content_header">
+    <TMPL_VAR NAME=PAGETITLE>
+  </div>
+
+  <div class="content_linkpath">
+    <a href="<TMPL_VAR NAME=SCRIPT>?lang=<TMPL_VAR NAME=LANGUAGE>">Kulturtankstelle</a> &gt;&gt;
+    <a href="<TMPL_VAR NAME=SCRIPT>?lang=<TMPL_VAR NAME=LANGUAGE>;id=<TMPL_VAR NAME=MENUID>"><TMPL_VAR NAME=MENUTITLE></a> &gt;&gt;
+    <a href="<TMPL_VAR NAME=SCRIPT>?lang=<TMPL_VAR NAME=LANGUAGE>;id=<TMPL_VAR NAME=MENUID>;albumid=<TMPL_VAR NAME=ALBUMID>"><TMPL_VAR NAME=ALBUMTITLE></a>
+  </div>
+
+  <div class="music_album">
+    <a href="<TMPL_VAR NAME=ALBUMCOVER>">
+      <img class="music_cover" src="<TMPL_VAR NAME=ALBUMCOVER>" height="100" width="100" alt="<TMPL_VAR NAME=ALBUMTITLE>">
+    </a>
+
+    <div class="music_albumtitle"><TMPL_VAR NAME=ALBUMTITLE></div>
+      <TMPL_VAR NAME=TRACKS>: <TMPL_VAR NAME=TRACKCOUNT><br />
+      <TMPL_VAR NAME=ARTIST>: <TMPL_VAR NAME=ARTISTNAME><br />
+      <TMPL_VAR NAME=LICENSE>: <a href="<TMPL_VAR NAME=LICENSEURL>"><TMPL_VAR NAME=LICENSETEXT></a><br /><br />
+      <a href="<TMPL_VAR NAME=FETCHALBUMLINK>"><TMPL_VAR NAME=FETCHALBUM></a><br />
+    </div><br />
+
+
+    <div class="music_content">
+      <table>
+        <tr id="rowhead">
+          <th><TMPL_VAR NAME=TRACK></th>
+          <th><TMPL_VAR NAME=TITLE></th>
+          <th><TMPL_VAR NAME=LENGTH></th>
+          <th><TMPL_VAR NAME=DOWNLOAD></th>
+        </tr>
+
+        <TMPL_LOOP NAME=TRACKLOOP>
+        <TMPL_IF NAME="__odd__">
+        <tr id="row1">
+        <TMPL_ELSE>
+        <tr id="row2">
+        </TMPL_IF>
+          <td><TMPL_VAR NAME="__counter__"></td>
+          <td><TMPL_VAR NAME=TRACKTITLE></td>
+          <td><TMPL_VAR NAME=TRACKLENGTH></td>
+          <td><a href="<TMPL_VAR NAME=TRACKPATH>">
+              <TMPL_VAR NAME=DOWNLOADTEXT></a></td>
+        </tr>
+        </TMPL_LOOP>
+      </table>
+    </div>
+  </div>
+</div>
diff --git a/kulturtankstelle/templates/kt_music_overview.tmpl b/kulturtankstelle/templates/kt_music_overview.tmpl
new file mode 100644 (file)
index 0000000..ffe2a3a
--- /dev/null
@@ -0,0 +1,27 @@
+<div class="content">
+  <div class="content_header">
+    <TMPL_VAR NAME=PAGETITLE>
+  </div>
+
+  <div class="content_linkpath">
+    <a href="<TMPL_VAR NAME=SCRIPT>?lang=<TMPL_VAR NAME=LANGUAGE>">Kulturtankstelle</a> &gt;&gt;
+    <a href="<TMPL_VAR NAME=SCRIPT>?lang=<TMPL_VAR NAME=LANGUAGE>;id=<TMPL_VAR NAME=MENUID>"><TMPL_VAR NAME=MENUTITLE></a>
+  </div>
+
+  <TMPL_LOOP NAME=ALBUMLOOP>
+  <div class="music_album">
+    <a href="<TMPL_VAR NAME=SCRIPT>?lang=<TMPL_VAR NAME=LANGUAGE>;id=<TMPL_VAR NAME=MENUID>;albumid=<TMPL_VAR NAME=ALBUMID>">
+      <img class="music_cover" src="<TMPL_VAR NAME=ALBUMCOVER>" height="100" width="100" alt="<TMPL_VAR NAME=ALBUMTITLE>">
+    </a>
+
+    <div class="music_albumtitle">
+      <a href="<TMPL_VAR NAME=SCRIPT>?lang=<TMPL_VAR NAME=LANGUAGE>;id=<TMPL_VAR NAME=MENUID>;albumid=<TMPL_VAR NAME=ALBUMID>"><TMPL_VAR NAME=ALBUMTITLE></a>
+    </div>
+
+    <TMPL_VAR NAME=ARTIST>: <TMPL_VAR NAME=ARTISTNAME><br />
+    <TMPL_VAR NAME=TRACKS>: <TMPL_VAR NAME=TRACKCOUNT><br />
+    <TMPL_VAR NAME=LICENSE>: <a href="<TMPL_VAR NAME=LICENSEURL>"><TMPL_VAR NAME=LICENSETEXT></a><br />
+  </div><br />
+  </TMPL_LOOP>
+</div>
+