]> git.plutz.net Git - serve0/commitdiff
initial commit
authorpaul <paul@plutz.net>
Sat, 6 Sep 2014 06:37:20 +0000 (06:37 +0000)
committerpaul <paul@plutz.net>
Sat, 6 Sep 2014 06:37:20 +0000 (06:37 +0000)
svn path=/trunk/; revision=1

12 files changed:
action.sh [new file with mode: 0755]
cgi.sh [new file with mode: 0755]
constants.sh [new file with mode: 0755]
index.cgi [new file with mode: 0755]
page.sh [new file with mode: 0755]
pages/videoview.sh [new file with mode: 0755]
templates/filterdiag.html.sh [new file with mode: 0755]
templates/frame.html.sh [new file with mode: 0755]
templates/tagger.html.sh [new file with mode: 0755]
templates/videoview.css.sh [new file with mode: 0755]
templates/videoview.html.sh [new file with mode: 0755]
templates/view.html.sh [new file with mode: 0755]

diff --git a/action.sh b/action.sh
new file mode 100755 (executable)
index 0000000..0077575
--- /dev/null
+++ b/action.sh
@@ -0,0 +1,24 @@
+#!/bin/zsh
+
+# Copyright 2014 Paul Hänsch
+#
+# This file is part of Serve0.
+# 
+# Serve0 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.
+# 
+# Serve0 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 Serve0.  If not, see <http://www.gnu.org/licenses/>. 
+
+ACTION="$(echo "$_GET[\"action\"]" |egrep '^[a-zA-Z0-9_-]+$')"
+ACTION="${_EXEC}/actions/${ACTION}.sh"
+[ -x "$ACTION" ] || echo -n "Location: http://$HTTP_HOST/?page=error\n\n"
+
+. $ACTION
diff --git a/cgi.sh b/cgi.sh
new file mode 100755 (executable)
index 0000000..49e68b4
--- /dev/null
+++ b/cgi.sh
@@ -0,0 +1,54 @@
+#!/bin/zsh
+
+# Copyright 2014 Paul Hänsch
+#
+# This file is part of Serve0.
+# 
+# Serve0 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.
+# 
+# Serve0 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 Serve0.  If not, see <http://www.gnu.org/licenses/>. 
+
+declare -A _GET
+declare -A _POST
+declare -A _REF
+
+cgi_get() {  # parse HTTP GET string
+  echo "$QUERY_STRING" |tr '&' '\n' |while read query; do
+    key="$(echo "$query" |sed -r 's:^([a-zA-Z0-9_-]*)=(.*)$:\1:')"
+    val="$(echo "$query" |sed -r 's:^([a-zA-Z0-9_-]*)=(.*)$:\2:')"
+    _GET["$key"]="$(echo -e "$(echo "$val" |sed 's:+: :g;s:%:\\x:g')")"
+  done
+}
+
+cgi_post() {  # parse HTTP POST string
+  sed -u 1q |tr '&' '\n' |while read query; do
+    key="$(echo "$query" |sed -r 's:^([a-zA-Z0-9_-]*)=(.*)$:\1:')"
+    val="$(echo "$query" |sed -r 's:^([a-zA-Z0-9_-]*)=(.*)$:\2:')"
+    value="$(echo -e "$(echo "$val" |sed 's:+: :g;s:%:\\x:g')")"
+    if [ -n "$_POST[\"$key\"]" ]; then
+      n=0
+      while [ -n "$_POST[\"$key$n\"]" ]; do n=$(($n + 1)); done
+      _POST["$key$n"]="$value"
+    else
+      _POST["$key"]="$value"
+    fi
+    #debug "_POST[$key] => $value"
+  done
+}
+
+cgi_refdata() { # Parse GET data from referer
+  echo "$HTTP_REFERER" |cut -d'?' -f2- |tr '&' '\n' |while read query; do
+    key="$(echo "$query" |sed -r 's:^([a-zA-Z0-9_-]*)=(.*)$:\1:')"
+    val="$(echo "$query" |sed -r 's:^([a-zA-Z0-9_-]*)=(.*)$:\2:')"
+    _REF["$key"]="$(echo -e "$(echo "$val" |sed 's:+: :g;s:%:\\x:g')")"
+  done
+}
diff --git a/constants.sh b/constants.sh
new file mode 100755 (executable)
index 0000000..84d7c7a
--- /dev/null
@@ -0,0 +1,20 @@
+#!/bin/zsh
+
+# Copyright 2014 Paul Hänsch
+#
+# This file is part of Serve0.
+# 
+# Serve0 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.
+# 
+# Serve0 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 Serve0.  If not, see <http://www.gnu.org/licenses/>. 
+
+_GET['page']=videoview
diff --git a/index.cgi b/index.cgi
new file mode 100755 (executable)
index 0000000..d17b4c3
--- /dev/null
+++ b/index.cgi
@@ -0,0 +1,70 @@
+#!/bin/zsh
+
+# Copyright 2014 Paul Hänsch
+#
+# This file is part of Serve0.
+# 
+# Serve0 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.
+# 
+# Serve0 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 Serve0.  If not, see <http://www.gnu.org/licenses/>. 
+
+export LC_ALL=de_DE.UTF-8
+
+# basic functions
+die() {
+  echo "$*" >/dev/stderr
+  exit 1
+}
+debug() { #change to false to disable debugging
+  #true && echo "$*" >>debug
+  true && [ -n "$*" ] && echo -E "$*" >>/dev/stderr
+  true && [ -z "$*" ] && tee /dev/stderr
+}
+
+# this program is supposed to be symlinked into a http root directory
+# we will use the http root as object storage (data directory) and call sub
+# programs from the directory in which the real executable resides
+# therefore we need to identify the code and data directories _EXEC and _DATA
+call="$0"
+real="$(readlink -f $call)"
+_EXEC="$(dirname "$real")"  #execution directory
+_DATA="$(dirname "$call")"  #storage directory
+
+[ -w "$_DATA" ] && [ -d "$_DATA" ] || die "storage directory must be writable"
+
+# create directories for object storage
+for each in "$_DATA"/{cache,meta,mp4,videos,thumbs,trash,by_length}; do
+  [ ! -e "$each" ] && mkdir "$each"
+  [ -w "$each" ] && [ -d "$each" ] || die "storage $each must be a writable directory"
+done
+
+# create htaccess file
+[ -f .htaccess ] || cat >.htaccess <<EOF
+Options                +ExecCGI
+AddHandler     cgi-script .cgi
+DirectoryIndex index.cgi
+EOF
+[ -f .htaccess ] || die "no htaccess file present and unable to create one"
+
+. "$_EXEC/cgi.sh"
+
+cgi_get
+
+. "$_EXEC/constants.sh"
+
+if [ -n "$_GET[\"action\"]" ]; then
+  . "$_EXEC/action.sh"
+elif [ -n "$_GET[\"export\"]" ]; then
+  . "$_EXEC/export.sh"
+else
+  . "$_EXEC/page.sh"
+fi
diff --git a/page.sh b/page.sh
new file mode 100755 (executable)
index 0000000..fce83fb
--- /dev/null
+++ b/page.sh
@@ -0,0 +1,34 @@
+#!/bin/zsh
+
+# Copyright 2014 Paul Hänsch
+#
+# This file is part of Serve0.
+# 
+# Serve0 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.
+# 
+# Serve0 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 Serve0.  If not, see <http://www.gnu.org/licenses/>. 
+
+echo -n "Content-Type: text/html;charset=utf-8\n\n"
+
+PAGE="$(echo "$_GET[\"page\"]" |egrep '^[a-zA-Z0-9_-]+$')"
+PAGE="${_EXEC}/pages/${PAGE}.sh"
+[ -x "$PAGE" ] || PAGE="${_EXEC}/pages/error.sh"
+
+NAVIGATION() {
+  for each in "${_EXEC}"/pages/*.sh; do
+    link="$(echo "$each" |sed -r "s:^.*/([^/]*)\.sh$:\1:")"
+    title="$($each title)"
+    [ -n "$title" ] && echo "/?page=$link $title"
+  done
+}
+
+. ${_EXEC}/templates/frame.html.sh
diff --git a/pages/videoview.sh b/pages/videoview.sh
new file mode 100755 (executable)
index 0000000..0229b36
--- /dev/null
@@ -0,0 +1,147 @@
+#!/bin/zsh
+
+# Copyright 2014 Paul Hänsch
+#
+# This file is part of Serve0.
+# 
+# Serve0 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.
+# 
+# Serve0 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 Serve0.  If not, see <http://www.gnu.org/licenses/>. 
+
+filterdiag() {
+  . ${_EXEC}/templates/filterdiag.html.sh
+}
+
+tagger() {
+  n=foot
+  hideall="$(sed -rn "s;^([^:]+):.*$;hide_inline('${n}_\\1')\\;;p" <<<"$taglist" |sort -u)hide_inline('${n}_none');"
+
+  . ${_EXEC}/templates/tagger.html.sh
+}
+
+view() {
+  meta="${_DATA}/meta/$info.meta"
+  video="${_DATA}/videos/$info"
+  #reenc="vp8/$(sed -r 's:^(.*)\.[a-zA-Z0-9]{3,4}$:\1:' <<<"$info" )"
+  #[ -f "$reenc.mp4" ] && reenc="$reenc.mp4" || reenc="$reenc.mkv"
+  tags="$(sed -n '2p' "$meta")"
+  description="$(sed -n '3,$p' "$meta")"
+  length=0; width=0; height=0;
+  eval $(mplayer -noconsolecontrols -input file=/dev/null -slave -really-quiet -identify -frames 0 -ao null -vo null "$video" 2>/dev/null |sed -rn 's:ID_VIDEO_WIDTH=(.*):width=\1:p;s:ID_VIDEO_HEIGHT=(.*):height=\1:p;s:ID_LENGTH=(.*)(\..*)$:length=\1:p;')
+  
+  taglist=$(
+    for each in ${_DATA}/meta/*.meta; do
+      sed -n '2s:|:\n:gp' "$each"
+    done |sort -u |grep -xv '')
+  
+    . ${_EXEC}/templates/view.html.sh
+}
+
+_printVideo(){
+  info="$1"
+  meta="${_DATA}/meta/$info.meta"
+  tags="$(sed -n 2p "$meta")"
+  thumb="${_DATA}/thumbs/$info.jpg"
+  head -n1 "$meta" |read length width height
+  [ -z "$length" ] && length=0
+  [ -z "$width" ] && width=0
+  [ -z "$height" ] && height=0
+
+  video="${_DATA}/videos/$info"
+#  reenc="vp8/$(sed -r 's:^(.*)\.[a-zA-Z0-9]{3,4}$:\1:' <<<"$info" )"
+  mpfake="${_DATA}/mp4/$(sed -r 's:^(.*)\.[a-zA-Z0-9]{3,4}$:\1.mp4:' <<<"$info" )"
+#  [ -f "$reenc.mp4" ] && reenc="$reenc.mp4" || reenc="$reenc.mkv"
+  [ -r "$meta" ] || ./genmeta.sh "$video" "$meta"
+  [ -r "$thumb" ] || ./genthumb.sh "$video" "$thumb"
+  [ -L "$mpfake" ] || ln -s "../$video" "$mpfake"
+#    anchor=$(ls videos |grep -xA2 "$info" |tail -n1)
+  video="$(echo "$video" |sed 's/\?/\%6F/g')"
+  thumb="$(echo "$thumb" |sed 's/\?/%6F/g')"
+  mpfake="$(echo "$mpfake" |sed 's/\?/%6F/g')"
+
+  [ "$(($length % 60))" -lt 10 ] &&\
+    minutes="$(($length / 60)):0$(($length % 60))" ||\
+    minutes="$(($length / 60)):$(($length % 60))"
+
+  cat <<VIDEOend
+    <div class="thumb">
+      <a name="$info" href="?i=$info&p=$page&f=$filter&s=$search&o=$order#$anchor"><img src="$thumb"></a>
+      <div class="thumbinfo">
+        <a href="$video"><b>$info</b></a><br>
+       <!-- a href="$reenc">VP8</a -->
+        <a href="$mpfake">fake-mp4</a><br>
+       <input type="checkbox" name="tagsel" value="$info">
+        <span class="coord">${minutes}min</span>
+        <span class="coord">${width}x${height}</span><br>
+        <!--a class="function" href='write/lock.cgi?p=Locations&e=$info&i=$info&f=$filter#$anchor'>edit</a-->
+        <span class="tag">$(sed 's,|$,,;s,|,</span> <span class="tag">,g' <<<"$tags")</span>
+      </div>
+    </div>
+VIDEOend
+}
+
+_by_name(){ ls ${_DATA}/videos/ }
+_by_date(){ ls -c ${_DATA}/videos/ }
+_by_length(){ ls ${_DATA}/by_length/ |sed -r 's:[0-9]{5} - ::g' }
+
+thumblist() {
+  cache="${_DATA}/cache/?o=${order}&s=${search}&f=${filter}&p=${page}"
+  [ -f "$cache" ] && [ "$cache" -ot ${_DATA}/videos -o "$cache" -ot ${_DATA}/meta ] && rm "$cache"
+  if [ -r "$cache" ]; then
+    cat "$cache"
+    exit 0
+  fi
+  
+  filterex="p"
+  for each in $(sed 's,\^, ,g' <<<"$filter"); do
+    if egrep -q '^!' <<<"$each"; then
+      this="$(sed 's,^!,,' <<<"$each")"
+      filterex="/${this}/q;{${filterex}}"
+    else
+      filterex="/${each}/{${filterex}}"
+    fi
+  done
+  
+  case "$order" in
+    Date) genlist="_by_date"
+      ;;
+    Length) genlist="_by_length"
+      ;;
+    *) genlist="_by_name"
+      ;;
+  esac
+    
+  $genlist |while read video; do
+    #video="$(basename "$each")"
+    if [ -n "$search" ] ; then
+      egrep -iq "$search" <<<"$video" <"${_DATA}/meta/$video.meta" && (echo "$video" || exit 0)
+    elif [ "$filterex" != p ]; then
+       [ -n "$(sed -rn "2{$filterex}" "${_DATA}/meta/$video.meta")" ] && (echo "$video" || exit 0)
+    else
+      echo "$video" || exit 0
+    fi
+  done |sed -n $(($page * $pagesize + 1)),$(($page * $pagesize + $pagesize))p | while read line; do
+    _printVideo "$line"
+  done |tee "$cache"
+}
+
+case "$1" in
+  title)
+    echo "Videos"
+  ;;
+  css)
+    . ${_EXEC}/templates/videoview.css.sh
+  ;;
+  body)
+    . ${_EXEC}/templates/videoview.html.sh
+  ;;
+esac
diff --git a/templates/filterdiag.html.sh b/templates/filterdiag.html.sh
new file mode 100755 (executable)
index 0000000..f35e15e
--- /dev/null
@@ -0,0 +1,70 @@
+#!/bin/zsh    
+
+cat <<FilterEnd
+  <div class="panel" id="search" style="display: block;">
+    <form action="index.cgi" method="get" accept-charset="UTF-8">
+      <input type="text" name="s" value="$search" placeholder="Search">
+      Order by:<select size="1" name="o">
+       <option>Name</option>
+       <option>Date</option>
+       <option>Length</option>
+      </select>
+      <input type="submit" name="submit" value="Find">
+      <a class="panel" href="?">Clear All</a>
+      <a class="panel" href="#" onclick="javascript:hide_block('search');show_block('advfilter');">Advanced</a>
+    <span style="float:right;">
+      <b>Page:</b> <a href="?i=$info&o=$order&p=$([ "$page" != 0 ] && echo $(($page - 1)) || echo 0)&f=$filter&s=$search#$anchor">&lt;&lt;</a>
+      <a href="?i=&o=$order&p=$page&f=$filter&s=$search#$anchor">$(($page + 1))</a>
+      <a href="?i=$info&o=$order&p=$(($page + 1))&f=$filter&s=$search#$anchor">&gt;&gt;</a>
+    </span>
+    </form>
+  </div>
+
+
+  <div class="panel" id="advfilter" style="display: none;">
+    <input disabled type="text" name="s" value="$search" placeholder="Search">
+    <input disabled type="submit" name="submit" value="Find">
+    <a class="panel" href="?">Clear All</a>
+    <a class="panel" href="#" onclick="javascript:hide_block('advfilter');$(for n in {1..9}; do echo "hide_inline('filter$n');"; done)show_block('search')">Hide</a>
+    <hr>
+    Up to <b>10</b> filter boxes will appear as you start selecting tags. You can select <b>multiple</b> tags in each box by holding down the <b>Ctrl</b>-key. Click the "<b>Filter!</b>" button when you are ready.
+    <form action="filter.cgi" method="post" accept-charset="UTF-8">
+    $(for n in {0..9}; do
+      hideall="$(sed -rn "s;^([^:]+):.*$;hide_inline('${n}_\\1')\\;;p" <<<"$taglist" |sort -u)hide_inline('${n}_none');"
+      echo "
+      <div id=\"filter$n\" $([ $n -gt 0 ] && echo 'style="display:none;"')><b>and</b><br>
+        <input type=\"radio\" name=\"type$n\" value=\"pos\" checked><b>Any</b><br>
+        <input type=\"radio\" name=\"type$n\" value=\"neg\"><b>None</b><br>
+        of the tags selected here:<br> Category:
+        <select name=\"category\" size=\"1\" onchange=\"${hideall}show_inline('${n}_'+this.options[this.options.selectedIndex].value)\">
+          <option>none</option>
+          $(sed -rn 's;^([^:]+):.*$;<option>\1</option>;p' <<<"$taglist" |sort -u)
+        </select><br>
+        <select name=\"filter\" size=\"12\" multiple id=\"${n}_none\" onchange=\"show_inline('filter$((1+$n))')\">
+           $(sed -rn 's;^([^:]+)$;<option>\1</option>;p' <<<"$taglist")
+        </select>
+        $(sed -rn 's;^([^:]+):.*$;\1;p' <<<"$taglist" |sort -u |while read cat; do echo "
+        <select name=\"cfilter\" size=\"12\" multiple id=\"${n}_$cat\" style=\"display:none;\" onchange=\"show_inline('filter$((1+$n))')\">
+           $(sed -rn "s;^$cat:(.*)$;<option>\\1</option>;p" <<<"$taglist")
+        </select>"
+        done)
+      </div>"
+    done)
+      <div>
+        Order by:<select size="1" name="o">
+          <option>Name</option>
+          <option>Date</option>
+         <option>Length</option>
+        </select><br>
+        <input type="submit" value="Filter!">
+      </div>
+    </form>
+
+    <br/>
+    <h2>Most recent</h2>
+    $(uniq meta/recent |tail -n 10 |sed -r 's:^(.*)$:<a href="\1">\1</a><br/>:g')
+  </div>
+FilterEnd
+
+# vi:set filetype=html:
+
diff --git a/templates/frame.html.sh b/templates/frame.html.sh
new file mode 100755 (executable)
index 0000000..b6363d0
--- /dev/null
@@ -0,0 +1,53 @@
+# Copyright 2014 Paul Hänsch
+#
+# This file is part of Serve0
+# 
+# Serve0 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.
+# 
+# Serve0 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 Serve0  If not, see <http://www.gnu.org/licenses/>. 
+
+cat <<EOF
+<!Doctype HTML>
+
+<html>
+  <head>
+    <title>$($PAGE title)</title>
+    <style type="text/css">
+    <!--
+    $(. $PAGE css)
+    -->
+    </style>
+    <script type="text/javascript">
+    <!--
+    function show_block(id){
+      document.getElementById(id).style.display = "block";
+      try{document.getElementById('vid_'+id).play();}catch(foo){}
+    }
+    function show_inline(id){
+      document.getElementById(id).style.display = "inline";
+      try{document.getElementById('vid_'+id).play();}catch(foo){}
+    }
+    function hide_block(id){
+      try{document.getElementById('vid_'+id).pause();}catch(foo){}
+      document.getElementById(id).style.display = "none";
+    }
+    function hide_inline(id){ hide_block(id);}
+    -->
+    </script>
+  </head>
+  <body>
+    $(. $PAGE body)
+  </body>
+</html>
+EOF
+
+# vi:set filetype=html:
diff --git a/templates/tagger.html.sh b/templates/tagger.html.sh
new file mode 100755 (executable)
index 0000000..28fb1b8
--- /dev/null
@@ -0,0 +1,47 @@
+#!/bin/zsh    
+
+cat <<LOCATIONend
+  <div class="footer" id="foot">
+    <a class="panel" href="#foot" onclick="javascript:hide_block('foot');show_block('tagger');">Add Tags</a>
+    <span style="float:right;">
+      <b>Page:</b>
+      <a href="?o=$order&i=$info&p=$([ "$page" != 0 ] && echo $(($page - 1)) || echo 0)&f=$filter&s=$search#$anchor">&lt;&lt;</a>
+      <a href="?o=$order&i=&p=$page&f=$filter&s=$search#$anchor">$(($page + 1))</a>
+      <a href="?o=$order&i=$info&p=$(($page + 1))&f=$filter&s=$search#$anchor">&gt;&gt;</a>
+    </span>
+  </div>
+
+
+  <div class="footer" id="tagger" style="display: none;">
+    <a class="panel" href="#foot" onclick="javascript:hide_block('tagger');$(for n in $(seq 1 4); do echo "hide_inline('filter$n');"; done)show_block('foot')">Hide</a>
+    <hr>
+    <div>Add selectetd tags to selected videos.<br>
+      <!-- select name="category" size="12" onchange="${hideall}show_inline('${n}_'+this.options[this.options.selectedIndex].value)">
+        <option>none</option>
+        $(sed -rn 's;^([^:]+):.*$;<option>\1</option>;p' <<<"$taglist" |sort -u)
+      </select -->
+      <!-- input type="hidden" name="category" value="" -->
+      <div>None:<br>
+        <select name="ctag" size="12" multiple id="${n}_none">
+         $(sed -rn 's;^([^:]+)$;<option value="\1">\1</option>;p' <<<"$taglist")
+        </select>
+      </div>
+      $(sed -rn 's;^([^:]+):.*$;\1;p' <<<"$taglist" |sort -u |while read cat; do echo "
+      <div>${cat}:</br>
+        <input type=\"hidden\" name=\"category\" value=\"$cat\">
+        <select name=\"ctag\" size=\"12\" multiple id=\"${n}_$cat\" style=\"display:inline;\">
+         $(sed -rn "s;^${cat}:(.*)$;<option value=\"${cat}:\\1\">\\1</option>;p" <<<"$taglist")
+        </select>
+      </div>"
+      done)
+    </div>
+    <div>Additional Tags (one per line):<br>
+      <textarea name="tags" rows="2"></textarea>
+    </div>
+    <div><input type="submit" value="Add Tags!"></div>
+  </div>
+  <a name="foot"></a>
+LOCATIONend
+
+# vi:set filetype=html:
+
diff --git a/templates/videoview.css.sh b/templates/videoview.css.sh
new file mode 100755 (executable)
index 0000000..bf22dc2
--- /dev/null
@@ -0,0 +1,130 @@
+# Copyright 2014 Paul Hänsch
+#
+# This file is part of Serve0
+# 
+# Serve0 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.
+# 
+# Serve0 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 Serve0  If not, see <http://www.gnu.org/licenses/>. 
+
+cat <<EOF
+body {
+  padding: 0px;
+  margin: 0px;
+  background-color: #000;
+  color: #DDD;
+}
+a {
+  color: #EEE;
+}
+
+div.thumb {
+  width: 212px;
+  padding: 0px;
+  float: left;
+  margin: .1em;
+  white-space: normal;
+}
+div.thumbinfo {
+  /*height: 200px;*/
+  min-height: 150px;
+  max-height: 300px;
+  overflow: hidden;
+}
+
+*.coord {
+  margin: 0em 0em 0em 0em;
+  padding: 0em .2em 0em .2em;
+
+  background-color: #B8B8E0;
+  color: #000;
+
+  border-color: #000;
+  border-width: 1px;
+  border-style: solid;
+}
+*.tag {
+  white-space: nowrap;
+  margin: 0em 0em 0em 0em;
+  padding: 0em .2em 0em .2em;
+  line-height: 1.6em;
+
+  background-color: #DBB;
+  color: #000;
+
+  border-color: #000;
+  border-width: 1px;
+  border-style: solid;
+}
+
+div.panel {
+  overflow: hidden;
+  padding: .4em .5em .2em .5em;
+  background-color: #333;
+  border-style: none none solid none;
+  border-width: 1px;
+}
+a.panel {
+  font-weight: bold;
+  margin-left: 1em;
+  margin-right: 1em;
+  color: #EEE;
+}
+div.panel form div{
+  display: inline; float: left;
+  margin: .5em 0em 0em 1em;
+  padding: 0em .5em 0em 0em;
+  border-style: none solid none none;
+  border-width: 0px 1px 0px 0px;
+}
+div.panel form div select[multiple]{
+  width: 12em;
+}
+div.footer {
+  position: fixed;
+  bottom: 0px;
+  width: 99%;
+  overflow: hidden;
+  padding: .2em .5em .4em .5em;
+  background-color: #333;
+  border-style: solid none none none;
+  border-width: 1px;
+}
+div.footer div {
+  display: inline-block;
+  border-width: 0px 0px 0px 1px;
+  border-style: solid;
+  padding: .5em;
+  vertical-align: top;
+}
+div.footer select[name="category"] {
+  min-width: 8em;
+}
+div.footer select[name="ctag"] {
+  width: 10em;
+}
+
+.video {
+  display: inline; float: left;
+  width: 60%;
+}
+.video video {width: 100%;}
+.video embed {width: 100%; min-height:360px}
+.video iframe {width: 100%; min-height:360px}
+.videoinfo {
+  display: inline; float: left;
+  margin-left: 2%; width: 35%;
+}
+
+
+EOF
+
+# vi:set filetype=css:
diff --git a/templates/videoview.html.sh b/templates/videoview.html.sh
new file mode 100755 (executable)
index 0000000..504bfe0
--- /dev/null
@@ -0,0 +1,27 @@
+# Copyright 2014 Paul Hänsch
+#
+# This file is part of Serve0
+# 
+# Serve0 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.
+# 
+# Serve0 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 Serve0  If not, see <http://www.gnu.org/licenses/>. 
+
+cat <<EOF
+  $(filterdiag)
+  $(view)
+  <form action="multitag.cgi?f=$filter&amp;s=$search&amp;p=$page&amp;o=$order" method="post" accept-charset="UTF-8">
+  <div style="overflow:hidden;">$(thumblist)</div>
+  $(tagger)
+  </form>
+EOF
+
+# vi:set filetype=html:
diff --git a/templates/view.html.sh b/templates/view.html.sh
new file mode 100755 (executable)
index 0000000..c17284b
--- /dev/null
@@ -0,0 +1,54 @@
+#!/bin/zsh
+
+cat <<viewEND
+  <div class="panel" id="videoview">
+    <span style="float:right;"><a href="#" onclick="javascript:hide_block('videoview');" class="panel">Dismiss</a></span>
+    <div class="video">
+      <a href="$video">Full</a> <!-- a href="$reenc">Mobile</a --><br>
+      <!--iframe src="$video" width="100%" height="400px"-->
+      <video controls>
+        <!-- source src="$reenc" type='video/webm; codecs="vp8.0, mp3"' -->
+       <source src="$video" type='video/mp4; codecs="avc1.4D401E, mp3"'>"
+      </video><!--/iframe-->
+    </div>
+  
+    <div class="videoinfo" id="viewmeta">
+      <b>$info</b><a class="panel" href="#" onclick="javascript:hide_inline('viewmeta');show_inline('editmeta')">Edit</a><br>
+      <span class="coord">$(($length / 60)):$(($length % 60)) min</span>
+      <span class="coord">Width: $width</span><span class="coord">Height: $height</span><br>
+      <br><br>Tags:<span class="tag">$(sed 's,|$,,;s,|,</span> <span class="tag">,g' <<<"$tags")</span>
+      <br><br>$(_wiki <<<"$description")
+    </div>
+  
+    <div class="videoinfo" id="editmeta" style="display: none;">
+      <form action="meta.cgi?$info" method="post" accept-charset="UTF-8">
+        <input type="hidden" name="f" value="$filter"> <input type="hidden" name="s" value="$search"> <input type="hidden" name="p" value="$page">
+        <input type="hidden" name="length" value="$length"> <input type="hidden" name="width" value="$width">
+        <input type="hidden" name="height" value="$height">
+        <b>$info</b><a class="panel" href="#" onclick="javascript:hide_inline('editmeta');show_inline('viewmeta')">Cancel</a><br>
+        <span class="coord">$(($length / 60)):$(($length % 60)) min</span>
+        <span class="coord">Width: $width</span><span class="coord">Height: $height</span><br><br>
+  
+        <div>
+          Tags:<br>
+          <select name="tag" size="16" multiple>
+            $(echo "$taglist" |while read line; do
+              echo "<option $(egrep -q "(^|.*\|)$line(\|.*|$)" "$meta" && echo -n selected)>$line</option>"
+            done)
+          </select><br>
+        </div><div>
+          Additional Tags (one per line):<br>
+          <textarea name="tags" rows="16" style="width: 99%"></textarea><br><br>
+        </div>
+        Description:<br>
+        <textarea name="description" rows="4" style="width: 99%">$description</textarea><br>
+        <input type="submit" value="Submit">
+        <input type="submit" name="trash" value="Delete Video">
+        <!-- input type="submit" name="cancel" value="Cancel" -->
+      </form>
+    </div>
+  </div>
+viewEND
+
+# vi:set filetype=html:
+