From 25ae9b2dc4d2a2a5bd2e1920e1ee82dfbef4162e Mon Sep 17 00:00:00 2001 From: hallgren Date: Wed, 8 Jun 2011 15:29:50 +0000 Subject: [PATCH] gfse: initial support for grammars in the cloud This lets the user access the same set of grammars from multiple devices. Sharing grammars between multiple users is possible but discouraged at the moment. There is no version handling, so concurrent editing of the same grammar by different users might result in one user overwriting changes made by another user. (The same goes for cuncurrent editing on multiple devices by a single user, of course.) --- src/editor/simple/P/1306856253_weather_06.png | Bin 0 -> 2311 bytes src/editor/simple/P/1307545089_weather_04.png | Bin 0 -> 2376 bytes src/editor/simple/editor.css | 11 +- src/editor/simple/editor.js | 197 ++++++++++++++++-- src/editor/simple/save.hs | 15 +- src/editor/simple/upload.cgi | 110 +++++++--- 6 files changed, 277 insertions(+), 56 deletions(-) create mode 100644 src/editor/simple/P/1306856253_weather_06.png create mode 100644 src/editor/simple/P/1307545089_weather_04.png diff --git a/src/editor/simple/P/1306856253_weather_06.png b/src/editor/simple/P/1306856253_weather_06.png new file mode 100644 index 0000000000000000000000000000000000000000..3f01afcaaf37a95ae0f0c90432ddd06370a79224 GIT binary patch literal 2311 zcmeAS@N?(olHy`uVBq!ia0y~yU{C;I4mJh`hT^KKFANNfr!$?M13aCb6#|O#(=u~X z85k-UdnZ|YGdqg3`iF%GC@al!5)c#I7{Gb#kk{mh9}2D>V7(f;I}fYz*BfdyT8#Go)tC*tmm9VWLT8 z#)0*Hz5XkvPG8}qEOnvj)`m2LcmoNA)BKNrGVy(UxySj*uGJBiJ1ftMPwTTbk8S*W zTfV7l)8xyI4bG|y?bLQg7r1;{@St+?%qKHN*7&wBKGL&eZhy#4DuQY{8&17GY-~Hw5 zB(q&?Z@x0|?p9rE>JqN<_QA3xwmaYavWQuJY|8S}e$Q7tbNJbvYHP|kmEEB+`dak4 zO<$KIBG=;W=U0%SZ!Ir_Q(<1h(?(Men z_m@APeS1f*HL6+7&$>G8*_k=-t@~%jF8aSy^FLet@xH@_m6iWomsqLVEtYni`YUG@Lt_bmHDzrR(-B(Iws-;{HF)7`vJ5#~P2 z{|2>xzWLmJ&Z$>c4gRlRY~kVzi;R@a|NSU@)xI5Kr#H>pR(mSnv+;+$S68=&y1Gl( zq8--~I~O(_(^OD9da>iecYBlI>t|t4&;s*BoXGCfQu{@4TIb)4FN4jxcAa8P0P@d>qmnM>Z>C>N2FJFBOy{kDho_zn9~ z$8*|RT0)N{ZS?i0hl$&q`1zIdz{P?Vrb5Ph#}W=D_c3_4+J8vDoyQ`>=B|>qd`Upw zyV{axIoX=>Rlc{T7ez5;DWvA6rLl?H{Au9WY$M<^Pqoc}kBLF-jD=v6Kz)HNM}Z52 zrq_9o^hu|rGL^$Vz1_JtG~~*e=T}2lWZ@SUCZNJ#^V3mJCJJ^Ijrx3ip|sopp+M3Mx(=Jr>~9 zzB4sykDX&e6HCtLjXH-fm5Yn7|G)X+?O&UP{HOHKky)|o_RMMXqBbYF+MRvA`)zW_ z)Z+91n_Ql5Tpd!sD>~=?4x{EWyIHz6&m=z1uaVmM)BTZf9-Zr-O?(3qq*REXnP}&~Oysshu zcT=mPmzR&gbzgHHvm7q|)qT4knCh=t_HKjgTV^ZU-!68w#oPL`X76&D@?cfstVe4S zrI;l3m4luOnM9;dICZYYNpZ)%$v=JLoY!4iJG1!tB)O}uJ3>Q6{PNl-D$?tozs^+=f0Z#ZHK)x*g9s)@V2yR%#caB z?Zf8o5ji)WL`cNv&#OK zTHL-|);|%3675Zo8#@Xdizd2lUD45GquVuYO2~{)90of(%+@VsV`99*TU(XYFiX$< z#pmhQFFmk0pgtk_h=l&Xd+P&FwpFiO_)y68m`PPprO{2EE{|1pSNF=sD1V5vx&3C& z$(2b94^Ihajxn<5=i@Epu#5?GZn(ZbO638Q7AT!QnQ)|gX6HKo-P?5+%ddCQIF@hl|`NFGIx129?Wd`TVTPH^mfBz*8^p5X04Ns^=EC?T=appIma|C zzIR4;iTbLNMS(XK3hxP#=z6~S+7ms=;x!*6q~zTK8|@KJHzYj<;DgZouw+us*$@c-nnP_iD&z>U3xY$T8X_ozr=I>dzP;4 zBC_Whcimu?{?W+Jf5Fj7XrfSc&BCv{#eVAqo91$}{7enWjs6;aU266E4vM{Z6$_J5#P08{c&i!l& z63mqh%`8^eE?#^R;Wc3bi(;#x#1yxsEq-lLua>s(Ggwz`)??>gTe~DWM4fUFSc$ literal 0 HcmV?d00001 diff --git a/src/editor/simple/P/1307545089_weather_04.png b/src/editor/simple/P/1307545089_weather_04.png new file mode 100644 index 0000000000000000000000000000000000000000..8a7f1e3aeeead6c1c696a069cd223ee58cd42cc5 GIT binary patch literal 2376 zcmeAS@N?(olHy`uVBq!ia0y~yU{C;I4mJh`hT^KKFANNfr!$?M13aCb6#|O#(=u~X z85k-UdnZ|YGdqg3`iF%GC@al!5)c#I7{Gb#kk{mh9}2D>V7(f;I}fYz*BfdyT8#Go)tC*tmm9VWLT8 z#)0*Hz5XkvPG8}qEOnvj)`m2LcmoNA)BKNrGVy(UxySj*uGJBiJ1ftMPwTTbk8S*W zTfV7l)8xyI4bG|y?bLQg7r1;{@St+?%qKHN*7&wBKGL&eZhy#4DuQY{8&17GY-~Hw5 zB(q&?Z@x0|?p9rE>JqN<_QA3xwmaYavWQuJY|8S}e$Q7tbNJbvYHP|kmEEB+`dak4 zOO`ztH|8{LD^CkCcBjWjQSVbRj}mleO*Aai8>O zcCoMTSWeFLRSXpN-<&?b`rXaywSO(1hdrs6JGTGe{Vgl)uicW0RZ81nr?e@Cr<1kK zP=e*)@_n{-n>KGYu2=s5f5w5nyT8RlXFf~NnmVPG`>PH<3yk+&NU*iFEwmSk&vQ$|`xW3!**Q{Z>Q*hh|<^&-Jqa(-XSQVGL^vV8q*_15IZEZb&UjXO1%93AA zb?;uiTGhwAXX{qicW)vZf4PY~a4}O4J9EgaVP(fe#tdfrKcD{^Ff$&Q*%`TV%9bs6 zbe8-5|6tM+ckSQSc@rBlm%j5`F1>W|Uf-pW(kjARv%H?GI3yh9X$@%k&|DYr;0%Me z$?`%z52^A@`KeONpTA$cdUZZySop@xk%@0-EU?--?|4S-6)PXp`-cB(&cEPX_x<>y z9%GNva`}vzePQo%{w7_2SIe&&d{VeuTt8}m%1I^9D`BfOBJx`sMOI4*&zZRBCd1Nu zA8!`hu9?m;#p8ncnP=AX_Ez5A^}F8w*GKo|ruRgccHgu65OR3VukT^&a)ht#+qP^O zOWy^9riPmeGuA78jfsz$%IYt}f9+3&yh%l&-8 z{VU|}>67Q?{{5U4+_`Y;_carL?TQp~Jdv|!MWzOO&9OyB3Y>DA1*Xj8Sga;t?$XmS z<6_6BgR0ZKrn0oCakE-}eA^JSbH>j6)6>-LbiX?s>9VQ3yeMtu%5_1<&z8v)+J?J& zHEBsL3t4LV##&o!YQz~4VV9kU3u9AX@968AW3F7eTh92&gSpCTCrr)FyJvh7`8&;@ zao3lNCYMsgbElRq^Igi$nNbIz@I zMb1MhHtvR%Jqt`ULN^A4L~48tdtc!2`o(e|h9^a>H4D#e(h*(I?ZM)E{8oQY%;Z}s zL5Hd~nwRKz^z`+4Yo&Uag-_`0^kjX)JY}XyC)IjB}FaQ3|Y{Hb4>T79H*m^KDX)0oxsc)IcP!pnD+e(up_Z7@pWyCv1O z_}3&emUIK1M7`-xe_6iMHeV?Jqt;oxJ>f-H^Rwj3B5xO^sH;DH^Ygw+^9#NHw5OL& z?C5!9HBW~@;OVcI%Z-iN`uX;CEnViy&$94CNz3OCOD?SE-apfa?IbVXM2DR$$>I7k z>6ia}Jib6@4`*!G!hFkV3hWNk)tUK}cGM}W^{q%ewe+;4rc%+}gi{}^><>@ZKm2S` zPu$PV{kKoCY|Fj<%qc0Nxa(+>iP^HHyR35bri=5u?kZaG_(_!3)i!CTMHgUfYtQ+^MQp3%zA^ z<(>6G@$D?8P&cO4hrBwRLwygL2Z&9%6@3n2BT`g(> ztW0VL?$^DEkMACPWj|21N4MC5VKL7EZ zIbJ@#>UP(c2RGxV>1M`u2^~qP&)@$~fn`bC=;8t!E*mfShZ^3T76wd)g4B_Ho@IIg&7_42HHXGP>}x%OT4 z+OaIlpCOhhi>ot}$#jOf<(w&_&*@@chsg_czkj-!aAcO{ z);zH+zAQKQ0) get_file(i+".json",file_ok,file_err) + else { + local.count=new_count; + //alert("Download finished"); + setTimeout(function(){location.href="."},3000); + } + } + function download_files(count) { + new_count=count; + local.put("current",0); + download_files_from(count); + } + get_file("count.json",download_files); +} + +function download_from_cloud() { + var olddir=local.get("dir",null) + var newdir="/tmp/"+location.hash.substr(1) + if(newdir==olddir || confirm("Cloud grammars will replace your local grammars")) { + local.put("dir",newdir); + download_json(newdir) + } +} + +function timestamp(obj,prop) { + obj[prop || "timestamp"]=Date.now(); +} + +function draw_timestamp(obj) { + var t=obj.timestamp; + return node("small",{"class":"modtime"}, + [text(t ? " -- "+new Date(t).toLocaleString() : "")]); } /* -------------------------------------------------------------------------- */ @@ -919,5 +1074,7 @@ function touch_edit() { //document.body.appendChild(empty_id("div","debug")); -initial_view(); -touch_edit(); +if(editor) { + initial_view(); + touch_edit(); +} diff --git a/src/editor/simple/save.hs b/src/editor/simple/save.hs index 01d3ce270..e29287d33 100644 --- a/src/editor/simple/save.hs +++ b/src/editor/simple/save.hs @@ -1,12 +1,17 @@ -import Monad(zipWithM_) +import Monad(zipWithM) import System(getArgs) main = save =<< getArgs save [dir] = do fs@[ns,_] <- readIO =<< getContents - save_all fs - putStrLn $ unwords [n++".gf"|n<-ns] + nes <- save_all fs + putStrLn $ unwords nes where - save_all [ns,cs] = zipWithM_ write1 ns cs - write1 n = writeFile (dir++"/"++n++".gf") + save_all [ns,cs] = zipWithM write1 ns cs + write1 n c = + do writeFile (dir++"/"++ne) c + return ne + where + ne=if '.' `elem` n then n else n++".gf" + \ No newline at end of file diff --git a/src/editor/simple/upload.cgi b/src/editor/simple/upload.cgi index 9ef113ebf..ec6bdc476 100644 --- a/src/editor/simple/upload.cgi +++ b/src/editor/simple/upload.cgi @@ -12,7 +12,7 @@ style_url="editor.css" tmp="$documentRoot/tmp" make_dir() { - dir="$(mktemp -d "$tmp/gfse.XXXXXXXX")" + dir="$(mktemp -d "$tmp/gfse.XXXXXXXXXX")" # chmod a+rxw "$dir" chmod a+rx "$dir" cp "grammars.cgi" "$dir" @@ -25,30 +25,58 @@ check_grammar() { chgrp everyone "$dir" chmod g+ws "$dir" umask 002 - files=$(Reg from-url | LC_CTYPE=sv_SE.ISO8859-1 ./save "$dir") - cd $dir - begin pre - if gf -s -make $files 2>&1 ; then - end - h3 OK - begin dl - [ -z "$minibar_url" ] || { dt; echo "▸"; link "$minibar_url?/tmp/${dir##*/}/" "Minibar"; } - [ -z "$transquiz_url" ] || { dt; echo "▸"; link "$transquiz_url?/tmp/${dir##*/}/" "Translation Quiz"; } - [ -z "$gfshell_url" ] || { dt; echo "▸"; link "$gfshell_url?dir=${dir##*/}" "GF Shell"; } - dt ; echo "◂"; link "javascript:history.back()" "Back to Editor" + files=( $(Reg from-url | LC_CTYPE=sv_SE.ISO8859-1 ./save "$dir") ) + gffiles=( ) + otherfiles=( ) + for f in ${files[*]} ; do + case "$f" in + *.gf) gffiles=( ${gffiles[*]} "$f" ) ;; + *) otherfiles=( ${otherfiles[*]} "$f" ) ;; + esac + done - end - begin pre - ls -l *.pgf - else - end - begin h3 class=error_message; echo Error; end - for f in *.gf ; do - h4 "$f" - begin pre class=plain - cat -n "$f" + if [ ${#otherfiles} -gt 0 -a -n "$PATH_INFO" ] ; then + echo "Use the following link for shared access to your grammars from multiple devices:" + begin ul + case "$SERVER_PORT" in + 80) port="" ;; + *) port=":$SERVER_PORT" + esac + parent="http://$SERVER_NAME$port${REQUEST_URI%/upload.cgi/tmp/gfse.*}" + cloudurl="$parent/share.html#${dir##*/}" + li; link "$cloudurl" "$cloudurl" end - done + begin dl + dt ; echo "◂"; link "javascript:history.back()" "Back to Editor" + end + fi + + cd $dir + if [ ${#gffiles} -gt 0 ] ; then + begin pre + echo "gf -s -make ${gffiles[*]}" + if gf -s -make ${gffiles[*]} 2>&1 ; then + end + h3 OK + begin dl + [ -z "$minibar_url" ] || { dt; echo "▸"; link "$minibar_url?/tmp/${dir##*/}/" "Minibar"; } + [ -z "$transquiz_url" ] || { dt; echo "▸"; link "$transquiz_url?/tmp/${dir##*/}/" "Translation Quiz"; } + [ -z "$gfshell_url" ] || { dt; echo "▸"; link "$gfshell_url?dir=${dir##*/}" "GF Shell"; } + dt ; echo "◂"; link "javascript:history.back()" "Back to Editor" + + end + begin pre + ls -l *.pgf + else + end + begin h3 class=error_message; echo Error; end + for f in ${gffiles[*]} ; do + h4 "$f" + begin pre class=plain + cat -n "$f" + end + done + fi fi hr date @@ -56,6 +84,20 @@ check_grammar() { endall } +error400() { + echo "Status: 400" + pagestart "Error" + echo "What do you want?" + endall +} + +error404() { + echo "Status: 404" + pagestart "Not found" + echo "Not found" + endall +} + if [ -z "$tmp" ] || ! [ -d "$tmp" ] ; then pagestart "Error" begin pre @@ -87,11 +129,25 @@ case "$REQUEST_METHOD" in dir) make_dir ContentType="text/plain" cgiheaders - echo "/tmp/${dir##*/}" + echo_n "/tmp/${dir##*/}" ;; - *) pagestart "Error" - echo "What do you want?" - endall + download=*) + file=$(qparse "$QUERY_STRING" download) + case "$file" in + /tmp/gfse.*/*.json) # shouldn't allow .. in path !!! + path="$documentRoot$file" + if [ -r "$path" ] ; then + ContentType="text/javascript; charset=$charset" + cgiheaders + cat "$path" + else + error404 + fi + ;; + *) error400 + esac + ;; + *) error400 esac esac fi