--- /dev/null
+#!/bin/sh
+
+USER_REQUIREEMAIL=false
+
+. "${_EXEC:-${0%/*}}"/cgilite/cgilite.sh
+. "$_EXEC"/cgilite/session.sh nocookie
+. "$_EXEC"/cgilite/users.sh
+
+PATH_INFO="$(PATH "/${PATH_INFO#${_BASE}}")"
+
+export MD_HTML="false"
+if [ "$(which awk)" ]; then
+ markdown() { awk -f "$_EXEC/cgilite/markdown.awk"; }
+else
+ markdown() { busybox awk -f "$_EXEC/cgilite/markdown.awk"; }
+fi
+
+yield_page(){
+ title="${1:-RAW:NET}" page="$2"
+ printf '%s\r\n' 'Content-Type: text/html; charset=utf-8' \
+ "Content-Security-Policy: script-src 'none'" \
+ ''
+ { cat <<-EOF
+ [!DOCTYPE HTML]
+ [html [head
+ [meta name="viewport" content="width=device-width"]
+ [link rel="stylesheet" type="text/css" href="$_BASE/cgilite/common.css"]
+ [link rel="stylesheet" type="text/css" href="$_BASE/rawnet.css"]
+ [title . $(HTML "$title")]
+ ] [body class="$page"
+ [header
+ [form method=POST action="$_BASE/search/"
+ [input name=search placeholder="Search"]
+ ]
+ $( [ ! "$USER_ID" ] \
+ && printf '[div #user_login [a href="%s/login/" Login]]' "$_BASE" \
+ || w_user_login
+ )
+ ][main
+ EOF
+ cat
+ printf ']]]'
+ } |"$_EXEC/cgilite/html-sh.sed" -u
+}
+
+case ${PATH_INFO} in
+ /favicon.ico) printf '%s\r\n' 'Content-Length: 0' '';;
+ *.css)
+ . "${_EXEC}/cgilite/file.sh"
+ FILE "${_EXEC}/${PATH_INFO}"
+ ;;
+ /login/)
+ if [ "$USER_ID" ]; then
+ REDIRECT "${_BASE}/"
+ else
+ yield_page 'RAW:NET Login' login <<-EOF
+ $(w_user_login)
+ EOF
+ fi
+ ;;
+ /register/)
+ yield_page 'RAW:NET Register User' register <<-EOF
+ $(w_user_register)
+ EOF
+ ;;
+ /recover/)
+ yield_page 'RAW:NET Recover Account' recover <<-EOF
+ $(w_user_recover)
+ EOF
+ ;;
+ /|/channel/*) . "${_EXEC}/page_channel.sh";;
+ /playlist/*) . "${_EXEC}/page_playlist.sh";;
+ /search/*) . "${_EXEC}/page_search.sh";;
+ *) . "${_EXEC}/page_404.sh";;
+esac
+
+exit 0
--- /dev/null
+#!/bin/sh
+
+chan_db="$_DATA/channels.db"
+
+channel='' video='' action=''
+path_info="$PATH_INFO"
+path_info="${path_info#/channel/}"
+if [ "$(checkid "${path_info%%/*}")" ]; then
+ channel="${path_info%%/*}"
+ path_info="${path_info#*/}"
+fi
+if [ "$(checkid "${path_info%%/*}")" ]; then
+ video="${path_info%%/*}"
+ path_info="${path_info#*/}"
+fi
+action="${path_info}"
+unset path_info
+
+# Channel
+# ID NAME DESCRIPTION LOGO THEME AUTHORS DESCR_CACHE FUTUREUSE
+
+if [ "$channel" -a -f "$chan_db" -a -r "$chan_db" ]; then
+ read -r CHANNEL_ID CHANNEL_NAME CHANNEL_DESCRIPTION CHANNEL_LOGO \
+ CHANNEL_THEME CHANNEL_AUTHORS CHANNEL_DESCR_CACHE \
+ CHANNEL_FUTUREUSE <<-EOF
+ $(grep "^${channel} " "${chan_db}")
+ EOF
+ if [ "$CHANNEL_ID" ]; then
+ CHANNEL_NAME="$(UNSTRING "${CHANNEL_NAME}")"
+ CHANNEL_DESCRIPTION="$(UNSTRING "$CHANNEL_DESCRIPTION")"
+ CHANNEL_AUTHORS="$(UNSTRING "$CHANNEL_AUTHORS")"
+ CHANNEL_DESCR_CACHE="$(UNSTRING "$CHANNEL_DESCR_CACHE")"
+ vid_db="${_DATA}/${CHANNEL_ID}/videos.db"
+ else
+ channel=''
+ fi
+fi
+
+update_channel(){
+ local id="${1}" name="${2}" description="${3}" logo="${4}" theme="${5}" \
+ authors="${6}" descr_cache="${7}" futureuse="${8}"
+ local ID INFO
+ if LOCK "$chan_db"; then
+ while read -r ID INFO; do
+ if [ "$id" = "$ID" ]; then
+ printf '%s %s %s %s %s %s %s %s\n' \
+ "$id" "$(STRING "$name")" "$(STRING "$description")" \
+ "${logo:-\\}" "${theme:-\\}" "$(STRING "$authors")" \
+ "$(printf %s "$description" |markdown |STRING)" \
+ "${futureuse:-\\}"
+ else
+ printf '%s %s\n' "$ID" "$INFO"
+ fi
+ done <"$chan_db" >"${chan_db}.$$"
+ mv -- "${chan_db}.$$" "${chan_db}"
+ RELEASE "$chan_db"
+ else
+ return 1
+ fi
+}
+
+# Video
+# ID NAME DESCRIPTION RESX RESY LENGTH COVER STATUS UPLOADER HITS
+
+[ "$REQUEST_METHOD" = POST ] && case "$(POST action)" in
+ newchannel)
+ channel="$(POST channel |checkid)"
+ if [ ! "$USER_ID" ]; then
+ REDIRECT "${_BASE}/channel/#ERROR_NEWCHANNEL_NOTALLOWED"
+ elif LOCK "$chan_db"; then
+ if grep -q '^${channel} ' "$chan_db"; then
+ RELEASE "$chan_db"
+ REDIRECT "${_BASE}/channel/#ERROR_NEWCHANNEL_EXISTS"
+ else
+ printf '%s \\ \\ \\ \\ %s \\ \\\n' \
+ "$channel" "$(STRING "$USER_ID")" \
+ >>"$chan_db"
+ RELEASE "$chan_db"
+ REDIRECT "${_BASE}/channel/${channel}/edit"
+ fi
+ else
+ REDIRECT "${_BASE}/channel/#ERROR_NEWCHANNEL_NOLOCK"
+ fi
+ ;;
+ update_channel)
+ if [ ! "$channel" ]; then
+ REDIRECT "${_BASE}/channel/#ERROR_NOCHANNEL"
+ elif [ ! "$USER_ID" ]; then
+ REDIRECT "${_BASE}/channel/${channel}/#ERROR_NOTLOGGEDIN"
+ elif [ "${CHANNEL_AUTHORS##*${USER_ID}*}" ]; then
+ REDIRECT "${_BASE}/channel/${channel}/#ERROR_UPDATE_NOTALLOWED"
+ elif update_channel "$channel" "$(POST name)" "$(POST description)" \
+ "" "" "$USER_ID" "" ""; then
+ REDIRECT "${_BASE}/channel/${channel}/"
+ else
+ REDIRECT "${_BASE}/channel/${channel}/#ERROR_UPDATE_NOLOCK"
+ fi
+ ;;
+ newvideo)
+ video="$(POST video |checkid)"
+ # database video create
+ REDIRECT "${_BASE}/channel/${channel}/${video}/"
+ ;;
+esac
+
+w_video(){
+ local CID="$1" thumb
+ local ID NAME DESCRIPTION RESX RESY LENGTH COVER STATUS UPLOADER HITS FUTUREUSE
+ if read -r ID NAME DESCRIPTION RESX RESY LENGTH COVER STATUS UPLOADER HITS FUTUREUSE; then
+ thumb="${_BASE}/${CID}/thumb_${ID}.jpg"
+ cat <<-EOF
+ [div .video
+ [h3 . $(UNSTRING "$NAME" |HTML)]
+ [img href="${thumb}" alt="$(UNSTRING "$DESCRIPTION" |HTML)"]
+ ]
+ EOF
+ else
+ return 1
+ fi
+}
+
+w_channel(){
+ local vid_db
+ local ID NAME DESCRIPTION LOGO THEME AUTHORS DESCR_CACHE FUTUREUSE
+ if read -r ID NAME DESCRIPTION LOGO THEME AUTHORS DESCR_CACHE FUTUREUSE; then
+ vid_db="${_DATA}/${ID}/videos.db"
+ [ "$NAME" = \\ ] && NAME="(UNNAMED CHANNEL)"
+ cat <<-EOF
+ [div .channel
+ [h2 [a href="${_BASE}/channel/${ID}/" $(UNSTRING "${NAME}" |HTML)]]
+ [div .description . $(UNSTRING "$DESCR_CACHE")]
+ $( [ -f "$vid_db" -a -r "$vid_db" ] \
+ && while w_video "$ID"; do :; done <"$vid_db"
+ )
+ ]
+ EOF
+ else
+ return 1
+ fi
+}
+
+w_channel_list(){
+ if [ $USER_ID ]; then
+ printf '
+ [form .channel .newchannel method=POST
+ [hidden "channel" "%s"]
+ [submit "action" "newchannel" New Channel]
+ ]' "$(timeid)"
+ fi
+ [ -f "$chan_db" -a -r "$chan_db" ] \
+ && while w_channel; do :; done <"$chan_db"
+}
+
+if [ "$channel" -a "$video" ]; then
+ . ${_EXEC}/page_video.sh
+elif [ "$channel" -a "$action" = edit ]; then
+ [ "$USER_ID" -a ! "${CHANNEL_AUTHORS##*${USER_ID}*}" ] \
+ || REDIRECT "${_BASE}/${channel}/#ERROR_EDIT_NOTALLOWED"
+ yield_page "$CHANNEL_NAME - Edit" "channel edit" <<-EOF
+ [form .channel .edit method=POST
+ [input name="name" value="$(HTML "$CHANNEL_NAME")" placeholder="Channel Name"]
+ [textarea name="description" placeholder="Description" . $(HTML "$CHANNEL_DESCRIPTION")]
+ [submit "action" "update_channel" . Update]
+ ]
+ EOF
+elif [ "$channel" ]; then
+ yield_page "$CHANNEL_NAME" "channel" <<-EOF
+ [h1 .name $(HTML "$CHANNEL_NAME")]
+ $( [ "$USER_ID" -a ! "${CHANNEL_AUTHORS##*${USER_ID}*}" ] \
+ && printf '[a href="edit" edit]'
+ )
+ [div .description . ${CHANNEL_DESCR_CACHE}]
+ [div .videos
+ $( [ -f "$vid_db" -a -r "$vid_db" ] \
+ && while w_video "$ID"; do :; done <"$vid_db"
+ )
+ ]
+ EOF
+else
+ yield_page "Channels" "channels" <<-EOF
+ $(w_channel_list)
+ EOF
+fi
--- /dev/null
+body {
+ background-size: 4pt 4pt;
+ background-image: /* #6AF #6FF */
+ linear-gradient( 0deg, transparent 25%, rgba(128,128,128,.5) 25% 50%, transparent 50% 75%, rgba(192,192,192,.5) 75%),
+ linear-gradient(90deg, transparent 25%, rgba(128,128,128,.5) 25% 50%, transparent 50% 75%, rgba(192,192,192,.5) 75%);
+}
+
+header {
+ background-color: rgba(0,0,0,.75);
+ padding: .25em;
+ border-bottom: 1pt solid;
+ box-shadow: #000 0 .25em .5em;
+ text-align: center;
+}
+header > * {
+ display: inline-block;
+}
+
+header #user_login {
+ float: right;
+ margin: .125em .5em;
+}
+header #user_login > p {
+ display: inline-block;
+ color: #EEE;
+ font-size: .875em; line-height: 1.125em;
+ max-width: 12em;
+}
+
+main {
+ background-color: rgba(255,255,255,.75);
+ margin: 1em; padding: 1em;
+ box-shadow: #000 .125em .125em 1em;
+}
+
+body.channel main h1.name {
+ text-align: center;
+}
+body.channel main .description,
+body.channel main form.edit.channel {
+ max-width: 40em;
+ margin: auto;
+}
+
+body.channel main form.edit.channel input[name=name],
+body.channel main form.edit.channel textarea[name=description] {
+ display: block;
+ width: 100%;
+ margin-bottom: .5em;
+}
+
+body.channels main .channel {
+ border: 1pt solid;
+ border-radius: 4pt;
+ padding: .5em;
+ margin-bottom: .5em;
+}
+
+body.channels main .channel > h2,
+body.channels main .channel > .description {
+ margin: 0;
+ width: 140pt;
+ background-color: #FFF;
+}