7 # printf 'POST: %s\n' "$cgilite_post" >>debug
8 # printf 'action: %s\n' "$(GET action)" >>debug
11 wget(){ "$wget" -T 5 -t 1 -q -U '' $@; }
12 checkid(){ grep -m 1 -xE '[0-9a-zA-Z:_]{12}'; }
16 head -c9 /dev/urandom \
18 | sed -n '2{y;+/;:_;;p}'
22 # generate time based ID
25 while [ "$d" -gt 0 ]; do
26 printf \\%o $((d % 256))
33 | sed -n '2{y;+/;:_;;p}'
41 domain="${domain%%/*}"
42 ubase="${prot}://${domain}"
43 file="${BDB}/favicons/${bid}.ico"
45 mkdir -p "${BDB}/favicons/" && chmod a+rx "${BDB}/favicons/"
51 's;^.*(<[Ll][Ii][Nn][Kk]( [^>]*)? [Rr][Re][Ll]='\''([Ss][Hh][Oo][Rr][Tt][Cc][Uu][Tt] )?[Ii][Cc][Oo][Nn]'\''[^>]*>).*$;\1;;
52 s;^.*(<[Ll][Ii][Nn][Kk]( [^>]*)? [Rr][Re][Ll]="([Ss][Hh][Oo][Rr][Tt][Cc][Uu][Tt] )?[Ii][Cc][Oo][Nn]"[^>]*>).*$;\1;;
54 s;^.*<([^>]+) [Hh][Rr][Ee][Ff]="([^"]+)".*$:\2;;
55 s;^.*<([^>]+) [Hh][Rr][Ee][Ff]='\''([^'\'']+)'\''.*$:\2;;
60 # printf 'Shortcut icon for %s is %s\n' "$url" "$favinfo" >>debug
61 [ -z "$favinfo" ] && favinfo="${ubase}/favicon.ico"
63 http://*|https://*|//*) wget -O "$file" "$favinfo"
65 /*) wget -O "$file" "${ubase}/${favinfo}"
67 *) wget -O "$file" "${url%/*}/${favinfo}"
70 [ -f "${file}.1" ] && mv "${file}.1" "$file"
75 head -qn1 "${BDB}"/????????????.bm \
83 | while read fid nan; do
84 file="${BDB}/${fid}.bm"
85 sed -ri "1s;^(([^\t]+\t){2})[^\t]+(.*)$;\1${n}\3;;" "$file"
90 COKID="$(COOKIE id |checkid)"
91 QRYID="$(GET id |checkid)"
94 if [ -n "$QRYID" ]; then
95 printf '%s 303 See Other\r\n' "$SERVER_PROTOCOL"
96 printf 'Location: %s\r\n' "${SCRIPT_NAME}?${QUERY_STRING#id=*&}"
97 SET_COOKIE +8640000 "id=${QRYID}"
100 elif [ -z "$COKID" -a -z "$QRYID" ]; then
101 printf 'Content-Type: text/html; charset=utf-8\r\n\r\n'
106 <title>Bookman - New Collection</title>
107 </head><body id="newcollection">
108 <h1>You have not yet set up a collection on this server.</h1>
109 Click <a href="${SCRIPT_NAME}?action=newid">here</a> to start a new collection.
113 elif ! [ -d "${BDB}" ]; then
114 printf '%s 404 Not Found\r\n' "$SERVER_PROTOCOL"
115 printf 'Content-Type: text/html; charset=utf-8\r\n\r\n'
120 <title>Bookman - 404</title>
121 </head><body id="missingcollection">
122 <h1>The collection you requested does not exist on this server.</h1>
123 Click <a href="${SCRIPT_NAME}?action=newid">here</a> to start a new collection.
129 case "$(GET action)" in
133 { git init "users/${NEWID}" || mkdir -p "users/${NEWID}"; } >&-
135 printf '%s 303 See Other\r\n' "$SERVER_PROTOCOL"
136 printf 'Location: %s\r\n' "${SCRIPT_NAME}?id=${NEWID}"
137 SET_COOKIE +8640000 "id=${NEWID}"
142 name="$(POST name |head -n1)"
145 head -qn1 "${BDB}"/????????????.bm \
151 order="$(((order + 1000) / 1000 * 1000))"
152 if [ -n "$name" -a -d "${BDB}" ]; then
153 printf '%s\t%s\t%s\n' "$fid" "$(HTML "$name")" "$order" >"${BDB}/${fid}.bm"
154 git -C "${BDB}" add "${fid}.bm" >&-
155 git -C "${BDB}" commit -m "New bookmark folder: ${name} (${fid})" -- "${fid}.bm" >&-
157 REDIRECT "${SCRIPT_NAME}#${fid}"
160 name="$(POST name |head -n1)"
161 fid="$(POST fid | checkid)"
162 file="${BDB}/${fid}.bm"
163 if [ "$(POST control)" = confirm -a -n "$name" -a -f "$file" ]; then
164 sed -ri "1s'^(${fid}\t)[^\t]+(\t.+)$'\1${name}\2';" "$file"
165 git -C "${BDB}" add "${fid}.bm" >&-
166 git -C "${BDB}" commit -m "Renamed folder ${fid} to '${name}'" -- "${fid}.bm" >&-
168 REDIRECT "${SCRIPT_NAME}#${fid}"
171 fid="$(POST fid | checkid)"
172 target="$(POST target | checkid)"
173 file="${BDB}/${fid}.bm"
174 tfile="${BDB}/${target}.bm"
175 if [ "$(POST control)" = confirm -a -f "$file" ]; then
176 if [ "$target" = "____________" ]; then
178 git -C "${BDB}" commit -m "Deleted folder ${fid}" -- "${fid}.bm" >&-
179 elif tail -n+2 "$file" >>"$tfile"; then
181 git -C "${BDB}" commit -m "Deleted folder ${fid}" -- "${fid}.bm" "${target}.bm" >&-
184 REDIRECT "${SCRIPT_NAME}#${target}"
187 fid="$(POST fid | checkid)"
188 target="$(POST target | checkid)"
189 file="${BDB}/${fid}.bm"
190 tfile="${BDB}/${target}.bm"
191 if [ "$target" = "____________" -a -f "$file" -a "$(POST control)" = confirm ]; then
192 read nan1 nan2 last nan3 <"${BDB}/$(list_folders |tail -n1 |cut -f1).bm"
193 sed -ri "1s;^(([^\t]+\t){2})[^\t]+(.*)$;\1$((${last:-0} + 1000))\3;;" "$file"
194 elif [ -f "$tfile" -a -f "$file" -a "$(POST control)" = confirm ]; then
195 read nan1 nan2 tid nan3 <"$tfile"
196 sed -ri "1s;^(([^\t]+\t){2})[^\t]+(.*)$;\1$((${tid:-1} -1))\2;;" "$file"
199 git -C "${BDB}" commit -a -m "Modified folder order (moved ${fid})" >&-
200 REDIRECT "${SCRIPT_NAME}#${fid}"
203 fid="$(POST fid | checkid)"
204 name="$(POST name |head -n1)"
205 url="$(POST url |head -n1)"
206 file="${BDB}/${fid}.bm"
208 ctl="$(POST control)"
209 [ "$url" = "${url#*://}" ] && url="http://$url"
211 if [ -n "$name" -a -n "$url" -a -f "${file}" -a "$ctl" = "confirm" ]; then
212 printf '%s\t%s\t%s\n' "$bid" "$(HTML "$name")" "$url" >>"${file}"
213 git -C "${BDB}" commit -m "New Bookmark: ${name} in ${fid}" -- "${fid}.bm" >&-
214 getFavicon "$url" "$bid"
215 REDIRECT "${SCRIPT_NAME}#${fid}"
216 elif [ "$ctl" = "confirm" ]; then
217 REDIRECT "${SCRIPT_NAME}?newbm=${fid}&nbmurl=${url}&nbmname=${name}"
219 REDIRECT "${SCRIPT_NAME}#${fid}"
223 bid="$(POST bid | checkid)"
224 name="$(POST name |head -n1)"
225 url="$(POST url |head -n1)"
226 file="$(grep -lm1 "^${bid}" "${BDB}"/????????????.bm |head -n1)"
227 if [ -n "$name" -a -n "$url" -a "$(POST control)" = confirm -a -w "$file" ]; then
228 sed -rni "/^${bid}\t/!p; /^${bid}\t/i${bid}\t$(HTML "$name")\t${url}" "$file"
229 git -C "${BDB}" commit -m "Modified Bookmark: ${name} (${bid}) in ${file##*/}" -- "${file##*/}" >&-
231 getFavicon "$url" "$bid"
232 REDIRECT "${SCRIPT_NAME}#${fid}"
235 bid="$(POST bid | checkid)"
236 fid="$(POST target | checkid)"
237 sfile="$(grep -lm1 "^${bid}" "${BDB}"/????????????.bm |head -n1)"
238 tfile="${BDB}/${fid}.bm"
240 if [ "$(POST control)" = confirm -a -n "$bid" -a -w "$sfile" -a -w "$tfile" ]; then
241 grep -m1 "^${bid}" "$sfile" >>"$tfile" \
242 && sed -ri "0,/^${bid}/{/^${bid}/d;}" "$sfile"
243 git -C "${BDB}" commit -m "Moved Bookmark ${bid} from ${sfile##*/} to ${tfile##*/}" \
244 -- "${sfile##*/}" "${tfile##*/}" >&-
246 REDIRECT "${SCRIPT_NAME}#${fid}"
249 fid="$(GET fid |checkid)"
250 bid="$(GET bid |checkid)"
251 file="${BDB}/${fid}.bm"
253 if [ -n "$bid" -a -n "$fid" ] && grep -q "^${bid}" "$file"; then
254 sed -ri ":X;\$bY;N;bX;:Y; s;(\n[^\n]+)(\n${bid}\t[^\n]+);\2\1;;" "$file"
255 git -C "${BDB}" commit -m "Modified bookmark order in ${fid} (raised ${bid})" -- "${fid}.bm" >&-
257 REDIRECT "${SCRIPT_NAME}#${fid}"
260 fid="$(GET fid |checkid)"
261 bid="$(GET bid |checkid)"
262 file="${BDB}/${fid}.bm"
264 if [ -n "$bid" -a -n "$fid" ] && grep -q "^${bid}" "$file"; then
265 sed -ri ":X;\$bY;N;bX;:Y; s;(\n${bid}\t[^\n]+)(\n[^\n]+);\2\1;;" "$file"
266 git -C "${BDB}" commit -m "Modified bookmark order in ${fid} (lowered ${bid})" -- "${fid}.bm" >&-
268 REDIRECT "${SCRIPT_NAME}#${fid}"
271 fid="$(POST fid |checkid)"
272 bid="$(POST bid |checkid)"
273 file="${BDB}/${fid}.bm"
274 query="$(URL "$(POST query)")"
277 url="$(grep -m1 "^${bid}" "$file" |cut -f3-)"
278 urlpfx="${url%\{@\}*}"
279 urlsfx="${url#*\{@\}}"
281 REDIRECT "${urlpfx}${query}${urlsfx}"
286 fid="$(GET newbm |checkid)"
287 name="$(GET nbmname)"
289 file="${BDB}/${fid}.bm"
291 [ "$url" = "${url#*://}" ] && url="http://$url"
292 if [ -z "$name" -a -n "$url" ]; then
293 name="$(wget -O- "$url" \
295 | sed -rn ':X;$bY;N;bX;:Y; s;^.*<title[^>]*>([^<]+)<.*$;\1;p;'
299 if [ -n "$fid" -o -n "$name" -o -n "$url" ]; then
301 <form class="dialog newbookmark" method="POST" action="${SCRIPT_NAME}?action=newbookmark">
302 <h1>New Bookmark</h1>
303 <label>Folder:</label>
305 $(list_folders |while read id n; do
307 && printf '<option value="%s" selected="selected">%s</option>' "$id" "$n" \
308 || printf '<option value="%s">%s</option>' "$id" "$n"
310 $(printf '<option value="%s">%s</option>' $(list_folders))
313 <input type="text" name="name" value="$(HTML ${name})")" placeholder="Name" />
315 <input type="text" name="url" value="$(HTML "${url}")")" placeholder="URL" />
316 <button type="submit" name="control" value="confirm">OK</button>
317 <button type="submit" name="control" value="cancel">Cancel</button>
324 bmod="$(GET bmodify |checkid)"
325 bmove="$(GET bmove |checkid)"
327 if [ -n "$bmod" ]; then
328 file="$(grep -lm1 "^${bmod}" "${BDB}/"????????????.bm |head -n1)"
329 read bid name url <<-EOF
330 $(grep -m1 "^${bmod}" "$file")
333 <form class="dialog modbookmark" method="POST" action="${SCRIPT_NAME}?action=modbookmark">
334 <input type="hidden" name="bid" value="${bid}" />
335 <h1>Modify: ${name}</h1>
336 <label class="tab">Modify</label>
337 <a class="tab" href="${SCRIPT_NAME}?bmove=${bid}">Move</a>
339 <input type="text" name="name" value="${name}")" placeholder="Name" />
341 <input type="text" name="url" value="$(HTML "${url}")")" placeholder="URL" />
342 <button type="submit" name="control" value="confirm">OK</button>
343 <button type="submit" name="control" value="cancel">Cancel</button>
346 elif [ -n "$bmove" ]; then
347 file="$(grep -lm1 "^${bmove}" "${BDB}/"????????????.bm |head -n1)"
348 read bid name url <<-EOF
349 $(grep -m1 "^${bmove}" "$file")
352 <form class="dialog modbookmark" method="POST" action="${SCRIPT_NAME}?action=movebookmark">
353 <input type="hidden" name="bid" value="${bid}" />
354 <h1>Move: ${name}</h1>
355 <a class="tab" href="${SCRIPT_NAME}?bmodify=${bid}">Modify</a>
356 <label class="tab">Move</label>
357 <label>Move to Folder:</label>
358 <select name="target">
359 $(printf '<option value="%s">%s</option>' $(list_folders))
361 <button type="submit" name="control" value="confirm">OK</button>
362 <button type="submit" name="control" value="cancel">Cancel</button>
370 bmodify="$(GET bmodify |checkid)"
372 tail -n+2 "${BDB}/${fid}.bm" \
373 | while read bid name url; do
374 if [ "${url%\{@\}*}" = "${url}" ]; then
376 <div class="bookmark">
377 <a class="modify" href="${SCRIPT_NAME}?bmodify=${bid}">Modify</a>
378 <a class="link" target="_blank" href="$(HTML "${url}")")">
379 <img alt="@" src="${BDB}/favicons/${bid}.ico"/>${name}
381 <a class="bmove" href="${SCRIPT_NAME}?action=bmup&fid=${fid}&bid=${bid}">Move up</a>
382 <a class="bmove" href="${SCRIPT_NAME}?action=bmdn&fid=${fid}&bid=${bid}">Move down</a>
387 <form class="bookmark" target="_blank" method="POST" action="${SCRIPT_NAME}?action=query">
388 <a class="modify" href="${SCRIPT_NAME}?bmodify=${bid}">Modify</a>
389 <input type="hidden" name="fid" value="$fid" />
390 <input type="hidden" name="bid" value="$bid" />
391 <img alt="${name}" src="${BDB}/favicons/${bid}.ico"/>
392 <input name="query" placeholder="$name"/>
393 <a class="bmove" href="${SCRIPT_NAME}?action=bmup&fid=${fid}&bid=${bid}">Move up</a>
394 <a class="bmove" href="${SCRIPT_NAME}?action=bmdn&fid=${fid}&bid=${bid}">Move down</a>
402 fmodify="$(GET fmodify |checkid )"
403 fdelete="$(GET fdelete |checkid )"
404 fmove="$(GET fmove |checkid )"
406 if [ -n "$fmodify" ]; then
407 read fid fname order <"${BDB}/${fmodify}.bm"
409 <form class="dialog modfolder rename" method="POST" action="${SCRIPT_NAME}?action=modfolder">
410 <h1>Rename Folder: ${fname}</h1>
411 <input type="hidden" name="fid" value="${fid}" />
412 <label class="tab">Rename</label>
414 href="${SCRIPT_NAME}?fdelete=${fid}">Delete</a>
416 href="${SCRIPT_NAME}?fmove=${fid}">Move</a>
417 <input type="text" name="name" value="${fname}" />
418 <button type="submit" name="control" value="confirm">OK</button>
419 <button type="submit" name="control" value="cancel">Cancel</button>
422 elif [ -n "$fdelete" ]; then
423 read fid fname order <"${BDB}/${fdelete}.bm"
425 <form class="dialog modfolder delete" method="POST" action="${SCRIPT_NAME}?action=delfolder">
426 <h1>Delete Folder: ${fname}</h1>
427 <input type="hidden" name="fid" value="${fid}" />
428 <a class="tab" href="${SCRIPT_NAME}?fmodify=${fid}">Rename</a>
429 <label class="tab">Delete</label>
431 href="${SCRIPT_NAME}?fmove=${fid}">Move</a>
432 <label>Pass Bookmarks on to:</label>
433 <select name="target">
434 $(printf '<option value="%s">%s</option>' $(list_folders |grep -v "^${fid}"))
435 <option value="____________">(discard)</option>
437 <button type="submit" name="control" value="confirm">OK</button>
438 <button type="submit" name="control" value="cancel">Cancel</button>
441 elif [ -n "$fmove" ]; then
442 read fid fname order <"${BDB}/${fmove}.bm"
444 <form class="dialog modfolder move" method="POST" action="${SCRIPT_NAME}?action=movefolder">
445 <h1>Move Folder: ${fname}</h1>
446 <input type="hidden" name="fid" value="${fid}" />
447 <a class="tab" href="${SCRIPT_NAME}?fmodify=${fid}">Rename</a>
448 <a class="tab" href="${SCRIPT_NAME}?fdelete=${fid}">Delete</a>
449 <label class="tab">Move</label>
450 <label>Move before folder:</label>
451 <select name="target">
452 $(printf '<option value="%s">%s</option>' $(list_folders |grep -v "^${fid}"))
453 <option value="____________">(last)</option>
455 <button type="submit" name="control" value="confirm">OK</button>
456 <button type="submit" name="control" value="cancel">Cancel</button>
464 | while read fid fname order; do
465 file="${BDB}/${fid}.bm"
466 cache="${BDB}/${fid}.cache"
467 if [ "${cache}" -nt "${file}" -a "${cache}" -nt "$0" ]; then
471 <section class="folder" id="${fid}">
473 <a class="modify" href="${SCRIPT_NAME}?fmodify=${fid}">Modify folder "${fname}"</a>
474 $(show_bookmarks "$fid")
475 <a class="new bookmark" href="${SCRIPT_NAME}?newbm=${fid}">New Bookmark</a>
482 SET_COOKIE +8640000 "id=${COKID}" # Refresh Cookie
483 printf 'Content-Type: text/html; charset=utf-8\r\n\r\n'
488 <title>Bookman - Your Collection</title>
489 <link rel="stylesheet" type="text/css" href="bookmarks.css" />
490 </head><body id="collection">
495 <form class="newfolder" method="POST" action="${SCRIPT_NAME}?action=newfolder">
496 <input type="text" name="name" value="" placeholder="New Folder" />
497 <button type="submit">New</button>