Index: Makefile ================================================================== --- Makefile +++ Makefile @@ -95,10 +95,14 @@ $(PREFIX)/share/docs/megatest_manual.html : docs/manual/megatest_manual.html mkdir -p $(PREFIX)/share/docs $(INSTALL) docs/manual/megatest_manual.html $(PREFIX)/share/docs/megatest_manual.html for png in $(PNGFILES);do $(INSTALL) docs/manual/$$png $(PREFIX)/share/docs/$$png;done +js : java-script-lib/jquery-3.1.0.slim.min.js + mkdir -p $(PREFIX)/share/js + cp java-script-lib/jquery-3.1.0.slim.min.js $(PREFIX)/share/js/jquery-3.1.0.slim.min.js + $(PREFIX)/share/db/mt-pg.sql : mt-pg.sql mkdir -p $(PREFIX)/share/db $(INSTALL) mt-pg.sql $(PREFIX)/share/db/mt-pg.sql #multi-dboard : multi-dboard.scm $(OFILES) $(GOFILES) @@ -237,12 +241,14 @@ $(INSTALL) dboard $(PREFIX)/bin/.$(ARCHSTR)/dboard install : $(PREFIX)/bin/.$(ARCHSTR) $(PREFIX)/bin/.$(ARCHSTR)/mtest $(PREFIX)/bin/megatest \ $(PREFIX)/bin/.$(ARCHSTR)/dboard $(PREFIX)/bin/dashboard $(HELPERS) $(PREFIX)/bin/nbfake \ $(PREFIX)/bin/nbfind $(PREFIX)/bin/loadrunner $(PREFIX)/bin/viewscreen $(PREFIX)/bin/mt_xterm \ + $(PREFIX)/share/docs/megatest_manual.html $(PREFIX)/bin/remrun \ $(PREFIX)/share/docs/megatest_manual.html $(PREFIX)/bin/remrun $(PREFIX)/bin/mtutil \ - $(PREFIX)/bin/tcmt $(PREFIX)/share/db/mt-pg.sql + $(PREFIX)/bin/tcmt $(PREFIX)/share/db/mt-pg.sql \ + js # $(PREFIX)/bin/.$(ARCHSTR)/ndboard # $(PREFIX)/bin/newdashboard $(PREFIX)/bin/.$(ARCHSTR) : @@ -320,15 +326,23 @@ datashare-testing/spublish : spublish.scm $(OFILES) csc $(CSCOPTS) spublish.scm $(OFILES) -o datashare-testing/spublish datashare-testing/sretrieve : sretrieve.scm megatest-version.o margs.o configf.o process.o csc $(CSCOPTS) sretrieve.scm megatest-version.o margs.o configf.o process.o -o datashare-testing/sretrieve + +datashare-testing/sauthorize : sretrieve.scm megatest-version.o margs.o configf.o process.o common.o + csc sauthorize.scm megatest-version.o margs.o configf.o process.o common.o -o datashare-testing/sauthorize + + +datashare-testing/sauthorize : sretrieve.scm megatest-version.o margs.o configf.o process.o common.o + csc sauthorize.scm megatest-version.o margs.o configf.o process.o common.o -o datashare-testing/sauthorize + sretrieve/sretrieve : datashare-testing/sretrieve csc $(CSCOPTS) -deploy -deployed sretrieve.scm megatest-version.o margs.o configf.o process.o chicken-install -keep-installed $(PROXY) -deploy -prefix sretrieve defstruct srfi-18 format sql-de-lite \ - srfi-1 posix regex regex-case srfi-69 + srfi-1 posix regex regex-case srfi-69 # base64 dot-locking \ # csv-xml z3 # "(define (toplevel-command . a) #f)" Index: datashare-testing/.sretrieve.config ================================================================== --- datashare-testing/.sretrieve.config +++ datashare-testing/.sretrieve.config @@ -1,8 +1,8 @@ [settings] base-dir /tmp/delme_data -allowed-users matt +allowed-users matt allowed-chars [0-9a-zA-Z\-\.]+ allowed-sub-paths [0-9a-zA-Z\-\.]+ [database] location #{scheme (create-directory "/tmp/#{getenv USER}" #t)} Index: http-transport.scm ================================================================== --- http-transport.scm +++ http-transport.scm @@ -7,10 +7,11 @@ ;; This program is distributed WITHOUT ANY WARRANTY; without even the ;; implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ;; PURPOSE. (require-extension (srfi 18) extras tcp s11n) + (use srfi-1 posix regex regex-case srfi-69 hostinfo md5 message-digest posix-extras) (use spiffy uri-common intarweb http-client spiffy-request-vars intarweb spiffy-directory-listing) @@ -29,11 +30,13 @@ (declare (uses portlogger)) (declare (uses rmt)) (include "common_records.scm") (include "db_records.scm") +(include "js-path.scm") +(require-library stml) (define (http-transport:make-server-url hostport) (if (not hostport) #f (conc "http://" (car hostport) ":" (cadr hostport)))) @@ -103,12 +106,24 @@ '(/ any)) (send-response body: "hey there!\n" headers: '((content-type text/plain)))) ((equal? (uri-path (request-uri (current-request))) '(/ "hey")) - (send-response body: "hey there!\n" + (send-response body: "hey there!\n" headers: '((content-type text/plain)))) + ((equal? (uri-path (request-uri (current-request))) + '(/ "jquery3.1.0.js")) + (send-response body: (http-transport:show-jquery) + headers: '((content-type application/javascript)))) + ((equal? (uri-path (request-uri (current-request))) + '(/ "test_log")) + (send-response body: (http-transport:html-test-log $) + headers: '((content-type text/HTML)))) + ((equal? (uri-path (request-uri (current-request))) + '(/ "dashboard")) + (send-response body: (http-transport:html-dboard $) + headers: '((content-type text/HTML)))) (else (continue)))))))) (with-output-to-file start-file (lambda ()(print (current-process-id)))) (http-transport:try-start-server ipaddrstr start-port))) ;; This is recursively run by http-transport:run until sucessful @@ -559,15 +574,49 @@ ;; (exit 4)) ;; "exit on ^C timer"))) ;; (thread-start! th2) ;; (thread-start! th1) ;; (thread-join! th2)))) + +;;=============================================== +;; Java script +;;=============================================== +(define (http-transport:show-jquery) + (let* ((data (tests:readlines *java-script-lib*))) +(string-join data "\n"))) + + ;;====================================================================== ;; web pages ;;====================================================================== +(define (http-transport:html-test-log $) + (let* ((run-id ($ 'runid)) + (test-item ($ 'testname)) + (parts (string-split test-item ":")) + (test-name (car parts)) + + (item-name (if (equal? (length parts) 1) + "" + (cadr parts)))) + ;(print $) +(tests:get-test-log run-id test-name item-name))) + + +(define (http-transport:html-dboard $) + (let* ((page ($ 'page)) + (oup (open-output-string)) + (bdy "--------------------------") + + (ret (tests:dynamic-dboard page))) + (s:output-new oup ret) + (close-output-port oup) + + (set! bdy (get-output-string oup)) + (conc "

Dashboard

" bdy "

" ))) + (define (http-transport:main-page) (let ((linkpath (root-path))) (conc "

" (pathname-strip-directory *toppath*) "

" "" "Run area: " *toppath* ADDED java-script-lib/jquery-3.1.0.slim.min.js Index: java-script-lib/jquery-3.1.0.slim.min.js ================================================================== --- /dev/null +++ java-script-lib/jquery-3.1.0.slim.min.js @@ -0,0 +1,4 @@ +/*! jQuery v3.1.0 -ajax,-ajax/jsonp,-ajax/load,-ajax/parseXML,-ajax/script,-ajax/var/location,-ajax/var/nonce,-ajax/var/rquery,-ajax/xhr,-manipulation/_evalUrl,-event/ajax,-effects,-effects/Tween,-effects/animatedSelector,-deprecated | (c) jQuery Foundation | jquery.org/license */ +!function(a,b){"use strict";"object"==typeof module&&"object"==typeof module.exports?module.exports=a.document?b(a,!0):function(a){if(!a.document)throw new Error("jQuery requires a window with a document");return b(a)}:b(a)}("undefined"!=typeof window?window:this,function(a,b){"use strict";var c=[],d=a.document,e=Object.getPrototypeOf,f=c.slice,g=c.concat,h=c.push,i=c.indexOf,j={},k=j.toString,l=j.hasOwnProperty,m=l.toString,n=m.call(Object),o={};function p(a,b){b=b||d;var c=b.createElement("script");c.text=a,b.head.appendChild(c).parentNode.removeChild(c)}var q="3.1.0 -ajax,-ajax/jsonp,-ajax/load,-ajax/parseXML,-ajax/script,-ajax/var/location,-ajax/var/nonce,-ajax/var/rquery,-ajax/xhr,-manipulation/_evalUrl,-event/ajax,-effects,-effects/Tween,-effects/animatedSelector,-deprecated",r=function(a,b){return new r.fn.init(a,b)},s=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,t=/^-ms-/,u=/-([a-z])/g,v=function(a,b){return b.toUpperCase()};r.fn=r.prototype={jquery:q,constructor:r,length:0,toArray:function(){return f.call(this)},get:function(a){return null!=a?a<0?this[a+this.length]:this[a]:f.call(this)},pushStack:function(a){var b=r.merge(this.constructor(),a);return b.prevObject=this,b},each:function(a){return r.each(this,a)},map:function(a){return this.pushStack(r.map(this,function(b,c){return a.call(b,c,b)}))},slice:function(){return this.pushStack(f.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(a){var b=this.length,c=+a+(a<0?b:0);return this.pushStack(c>=0&&c0&&b-1 in a)}var x=function(a){var b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u="sizzle"+1*new Date,v=a.document,w=0,x=0,y=ha(),z=ha(),A=ha(),B=function(a,b){return a===b&&(l=!0),0},C={}.hasOwnProperty,D=[],E=D.pop,F=D.push,G=D.push,H=D.slice,I=function(a,b){for(var c=0,d=a.length;c+~]|"+K+")"+K+"*"),S=new RegExp("="+K+"*([^\\]'\"]*?)"+K+"*\\]","g"),T=new RegExp(N),U=new RegExp("^"+L+"$"),V={ID:new RegExp("^#("+L+")"),CLASS:new RegExp("^\\.("+L+")"),TAG:new RegExp("^("+L+"|[*])"),ATTR:new RegExp("^"+M),PSEUDO:new RegExp("^"+N),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+K+"*(even|odd|(([+-]|)(\\d*)n|)"+K+"*(?:([+-]|)"+K+"*(\\d+)|))"+K+"*\\)|)","i"),bool:new RegExp("^(?:"+J+")$","i"),needsContext:new RegExp("^"+K+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+K+"*((?:-\\d)?\\d*)"+K+"*\\)|)(?=[^-]|$)","i")},W=/^(?:input|select|textarea|button)$/i,X=/^h\d$/i,Y=/^[^{]+\{\s*\[native \w/,Z=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,$=/[+~]/,_=new RegExp("\\\\([\\da-f]{1,6}"+K+"?|("+K+")|.)","ig"),aa=function(a,b,c){var d="0x"+b-65536;return d!==d||c?b:d<0?String.fromCharCode(d+65536):String.fromCharCode(d>>10|55296,1023&d|56320)},ba=/([\0-\x1f\x7f]|^-?\d)|^-$|[^\x80-\uFFFF\w-]/g,ca=function(a,b){return b?"\0"===a?"\ufffd":a.slice(0,-1)+"\\"+a.charCodeAt(a.length-1).toString(16)+" ":"\\"+a},da=function(){m()},ea=ta(function(a){return a.disabled===!0},{dir:"parentNode",next:"legend"});try{G.apply(D=H.call(v.childNodes),v.childNodes),D[v.childNodes.length].nodeType}catch(fa){G={apply:D.length?function(a,b){F.apply(a,H.call(b))}:function(a,b){var c=a.length,d=0;while(a[c++]=b[d++]);a.length=c-1}}}function ga(a,b,d,e){var f,h,j,k,l,o,r,s=b&&b.ownerDocument,w=b?b.nodeType:9;if(d=d||[],"string"!=typeof a||!a||1!==w&&9!==w&&11!==w)return d;if(!e&&((b?b.ownerDocument||b:v)!==n&&m(b),b=b||n,p)){if(11!==w&&(l=Z.exec(a)))if(f=l[1]){if(9===w){if(!(j=b.getElementById(f)))return d;if(j.id===f)return d.push(j),d}else if(s&&(j=s.getElementById(f))&&t(b,j)&&j.id===f)return d.push(j),d}else{if(l[2])return G.apply(d,b.getElementsByTagName(a)),d;if((f=l[3])&&c.getElementsByClassName&&b.getElementsByClassName)return G.apply(d,b.getElementsByClassName(f)),d}if(c.qsa&&!A[a+" "]&&(!q||!q.test(a))){if(1!==w)s=b,r=a;else if("object"!==b.nodeName.toLowerCase()){(k=b.getAttribute("id"))?k=k.replace(ba,ca):b.setAttribute("id",k=u),o=g(a),h=o.length;while(h--)o[h]="#"+k+" "+sa(o[h]);r=o.join(","),s=$.test(a)&&qa(b.parentNode)||b}if(r)try{return G.apply(d,s.querySelectorAll(r)),d}catch(x){}finally{k===u&&b.removeAttribute("id")}}}return i(a.replace(P,"$1"),b,d,e)}function ha(){var a=[];function b(c,e){return a.push(c+" ")>d.cacheLength&&delete b[a.shift()],b[c+" "]=e}return b}function ia(a){return a[u]=!0,a}function ja(a){var b=n.createElement("fieldset");try{return!!a(b)}catch(c){return!1}finally{b.parentNode&&b.parentNode.removeChild(b),b=null}}function ka(a,b){var c=a.split("|"),e=c.length;while(e--)d.attrHandle[c[e]]=b}function la(a,b){var c=b&&a,d=c&&1===a.nodeType&&1===b.nodeType&&a.sourceIndex-b.sourceIndex;if(d)return d;if(c)while(c=c.nextSibling)if(c===b)return-1;return a?1:-1}function ma(a){return function(b){var c=b.nodeName.toLowerCase();return"input"===c&&b.type===a}}function na(a){return function(b){var c=b.nodeName.toLowerCase();return("input"===c||"button"===c)&&b.type===a}}function oa(a){return function(b){return"label"in b&&b.disabled===a||"form"in b&&b.disabled===a||"form"in b&&b.disabled===!1&&(b.isDisabled===a||b.isDisabled!==!a&&("label"in b||!ea(b))!==a)}}function pa(a){return ia(function(b){return b=+b,ia(function(c,d){var e,f=a([],c.length,b),g=f.length;while(g--)c[e=f[g]]&&(c[e]=!(d[e]=c[e]))})})}function qa(a){return a&&"undefined"!=typeof a.getElementsByTagName&&a}c=ga.support={},f=ga.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return!!b&&"HTML"!==b.nodeName},m=ga.setDocument=function(a){var b,e,g=a?a.ownerDocument||a:v;return g!==n&&9===g.nodeType&&g.documentElement?(n=g,o=n.documentElement,p=!f(n),v!==n&&(e=n.defaultView)&&e.top!==e&&(e.addEventListener?e.addEventListener("unload",da,!1):e.attachEvent&&e.attachEvent("onunload",da)),c.attributes=ja(function(a){return a.className="i",!a.getAttribute("className")}),c.getElementsByTagName=ja(function(a){return a.appendChild(n.createComment("")),!a.getElementsByTagName("*").length}),c.getElementsByClassName=Y.test(n.getElementsByClassName),c.getById=ja(function(a){return o.appendChild(a).id=u,!n.getElementsByName||!n.getElementsByName(u).length}),c.getById?(d.find.ID=function(a,b){if("undefined"!=typeof b.getElementById&&p){var c=b.getElementById(a);return c?[c]:[]}},d.filter.ID=function(a){var b=a.replace(_,aa);return function(a){return a.getAttribute("id")===b}}):(delete d.find.ID,d.filter.ID=function(a){var b=a.replace(_,aa);return function(a){var c="undefined"!=typeof a.getAttributeNode&&a.getAttributeNode("id");return c&&c.value===b}}),d.find.TAG=c.getElementsByTagName?function(a,b){return"undefined"!=typeof b.getElementsByTagName?b.getElementsByTagName(a):c.qsa?b.querySelectorAll(a):void 0}:function(a,b){var c,d=[],e=0,f=b.getElementsByTagName(a);if("*"===a){while(c=f[e++])1===c.nodeType&&d.push(c);return d}return f},d.find.CLASS=c.getElementsByClassName&&function(a,b){if("undefined"!=typeof b.getElementsByClassName&&p)return b.getElementsByClassName(a)},r=[],q=[],(c.qsa=Y.test(n.querySelectorAll))&&(ja(function(a){o.appendChild(a).innerHTML="",a.querySelectorAll("[msallowcapture^='']").length&&q.push("[*^$]="+K+"*(?:''|\"\")"),a.querySelectorAll("[selected]").length||q.push("\\["+K+"*(?:value|"+J+")"),a.querySelectorAll("[id~="+u+"-]").length||q.push("~="),a.querySelectorAll(":checked").length||q.push(":checked"),a.querySelectorAll("a#"+u+"+*").length||q.push(".#.+[+~]")}),ja(function(a){a.innerHTML="";var b=n.createElement("input");b.setAttribute("type","hidden"),a.appendChild(b).setAttribute("name","D"),a.querySelectorAll("[name=d]").length&&q.push("name"+K+"*[*^$|!~]?="),2!==a.querySelectorAll(":enabled").length&&q.push(":enabled",":disabled"),o.appendChild(a).disabled=!0,2!==a.querySelectorAll(":disabled").length&&q.push(":enabled",":disabled"),a.querySelectorAll("*,:x"),q.push(",.*:")})),(c.matchesSelector=Y.test(s=o.matches||o.webkitMatchesSelector||o.mozMatchesSelector||o.oMatchesSelector||o.msMatchesSelector))&&ja(function(a){c.disconnectedMatch=s.call(a,"*"),s.call(a,"[s!='']:x"),r.push("!=",N)}),q=q.length&&new RegExp(q.join("|")),r=r.length&&new RegExp(r.join("|")),b=Y.test(o.compareDocumentPosition),t=b||Y.test(o.contains)?function(a,b){var c=9===a.nodeType?a.documentElement:a,d=b&&b.parentNode;return a===d||!(!d||1!==d.nodeType||!(c.contains?c.contains(d):a.compareDocumentPosition&&16&a.compareDocumentPosition(d)))}:function(a,b){if(b)while(b=b.parentNode)if(b===a)return!0;return!1},B=b?function(a,b){if(a===b)return l=!0,0;var d=!a.compareDocumentPosition-!b.compareDocumentPosition;return d?d:(d=(a.ownerDocument||a)===(b.ownerDocument||b)?a.compareDocumentPosition(b):1,1&d||!c.sortDetached&&b.compareDocumentPosition(a)===d?a===n||a.ownerDocument===v&&t(v,a)?-1:b===n||b.ownerDocument===v&&t(v,b)?1:k?I(k,a)-I(k,b):0:4&d?-1:1)}:function(a,b){if(a===b)return l=!0,0;var c,d=0,e=a.parentNode,f=b.parentNode,g=[a],h=[b];if(!e||!f)return a===n?-1:b===n?1:e?-1:f?1:k?I(k,a)-I(k,b):0;if(e===f)return la(a,b);c=a;while(c=c.parentNode)g.unshift(c);c=b;while(c=c.parentNode)h.unshift(c);while(g[d]===h[d])d++;return d?la(g[d],h[d]):g[d]===v?-1:h[d]===v?1:0},n):n},ga.matches=function(a,b){return ga(a,null,null,b)},ga.matchesSelector=function(a,b){if((a.ownerDocument||a)!==n&&m(a),b=b.replace(S,"='$1']"),c.matchesSelector&&p&&!A[b+" "]&&(!r||!r.test(b))&&(!q||!q.test(b)))try{var d=s.call(a,b);if(d||c.disconnectedMatch||a.document&&11!==a.document.nodeType)return d}catch(e){}return ga(b,n,null,[a]).length>0},ga.contains=function(a,b){return(a.ownerDocument||a)!==n&&m(a),t(a,b)},ga.attr=function(a,b){(a.ownerDocument||a)!==n&&m(a);var e=d.attrHandle[b.toLowerCase()],f=e&&C.call(d.attrHandle,b.toLowerCase())?e(a,b,!p):void 0;return void 0!==f?f:c.attributes||!p?a.getAttribute(b):(f=a.getAttributeNode(b))&&f.specified?f.value:null},ga.escape=function(a){return(a+"").replace(ba,ca)},ga.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)},ga.uniqueSort=function(a){var b,d=[],e=0,f=0;if(l=!c.detectDuplicates,k=!c.sortStable&&a.slice(0),a.sort(B),l){while(b=a[f++])b===a[f]&&(e=d.push(f));while(e--)a.splice(d[e],1)}return k=null,a},e=ga.getText=function(a){var b,c="",d=0,f=a.nodeType;if(f){if(1===f||9===f||11===f){if("string"==typeof a.textContent)return a.textContent;for(a=a.firstChild;a;a=a.nextSibling)c+=e(a)}else if(3===f||4===f)return a.nodeValue}else while(b=a[d++])c+=e(b);return c},d=ga.selectors={cacheLength:50,createPseudo:ia,match:V,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(_,aa),a[3]=(a[3]||a[4]||a[5]||"").replace(_,aa),"~="===a[2]&&(a[3]=" "+a[3]+" "),a.slice(0,4)},CHILD:function(a){return a[1]=a[1].toLowerCase(),"nth"===a[1].slice(0,3)?(a[3]||ga.error(a[0]),a[4]=+(a[4]?a[5]+(a[6]||1):2*("even"===a[3]||"odd"===a[3])),a[5]=+(a[7]+a[8]||"odd"===a[3])):a[3]&&ga.error(a[0]),a},PSEUDO:function(a){var b,c=!a[6]&&a[2];return V.CHILD.test(a[0])?null:(a[3]?a[2]=a[4]||a[5]||"":c&&T.test(c)&&(b=g(c,!0))&&(b=c.indexOf(")",c.length-b)-c.length)&&(a[0]=a[0].slice(0,b),a[2]=c.slice(0,b)),a.slice(0,3))}},filter:{TAG:function(a){var b=a.replace(_,aa).toLowerCase();return"*"===a?function(){return!0}:function(a){return a.nodeName&&a.nodeName.toLowerCase()===b}},CLASS:function(a){var b=y[a+" "];return b||(b=new RegExp("(^|"+K+")"+a+"("+K+"|$)"))&&y(a,function(a){return b.test("string"==typeof a.className&&a.className||"undefined"!=typeof a.getAttribute&&a.getAttribute("class")||"")})},ATTR:function(a,b,c){return function(d){var e=ga.attr(d,a);return null==e?"!="===b:!b||(e+="","="===b?e===c:"!="===b?e!==c:"^="===b?c&&0===e.indexOf(c):"*="===b?c&&e.indexOf(c)>-1:"$="===b?c&&e.slice(-c.length)===c:"~="===b?(" "+e.replace(O," ")+" ").indexOf(c)>-1:"|="===b&&(e===c||e.slice(0,c.length+1)===c+"-"))}},CHILD:function(a,b,c,d,e){var f="nth"!==a.slice(0,3),g="last"!==a.slice(-4),h="of-type"===b;return 1===d&&0===e?function(a){return!!a.parentNode}:function(b,c,i){var j,k,l,m,n,o,p=f!==g?"nextSibling":"previousSibling",q=b.parentNode,r=h&&b.nodeName.toLowerCase(),s=!i&&!h,t=!1;if(q){if(f){while(p){m=b;while(m=m[p])if(h?m.nodeName.toLowerCase()===r:1===m.nodeType)return!1;o=p="only"===a&&!o&&"nextSibling"}return!0}if(o=[g?q.firstChild:q.lastChild],g&&s){m=q,l=m[u]||(m[u]={}),k=l[m.uniqueID]||(l[m.uniqueID]={}),j=k[a]||[],n=j[0]===w&&j[1],t=n&&j[2],m=n&&q.childNodes[n];while(m=++n&&m&&m[p]||(t=n=0)||o.pop())if(1===m.nodeType&&++t&&m===b){k[a]=[w,n,t];break}}else if(s&&(m=b,l=m[u]||(m[u]={}),k=l[m.uniqueID]||(l[m.uniqueID]={}),j=k[a]||[],n=j[0]===w&&j[1],t=n),t===!1)while(m=++n&&m&&m[p]||(t=n=0)||o.pop())if((h?m.nodeName.toLowerCase()===r:1===m.nodeType)&&++t&&(s&&(l=m[u]||(m[u]={}),k=l[m.uniqueID]||(l[m.uniqueID]={}),k[a]=[w,t]),m===b))break;return t-=e,t===d||t%d===0&&t/d>=0}}},PSEUDO:function(a,b){var c,e=d.pseudos[a]||d.setFilters[a.toLowerCase()]||ga.error("unsupported pseudo: "+a);return e[u]?e(b):e.length>1?(c=[a,a,"",b],d.setFilters.hasOwnProperty(a.toLowerCase())?ia(function(a,c){var d,f=e(a,b),g=f.length;while(g--)d=I(a,f[g]),a[d]=!(c[d]=f[g])}):function(a){return e(a,0,c)}):e}},pseudos:{not:ia(function(a){var b=[],c=[],d=h(a.replace(P,"$1"));return d[u]?ia(function(a,b,c,e){var f,g=d(a,null,e,[]),h=a.length;while(h--)(f=g[h])&&(a[h]=!(b[h]=f))}):function(a,e,f){return b[0]=a,d(b,null,f,c),b[0]=null,!c.pop()}}),has:ia(function(a){return function(b){return ga(a,b).length>0}}),contains:ia(function(a){return a=a.replace(_,aa),function(b){return(b.textContent||b.innerText||e(b)).indexOf(a)>-1}}),lang:ia(function(a){return U.test(a||"")||ga.error("unsupported lang: "+a),a=a.replace(_,aa).toLowerCase(),function(b){var c;do if(c=p?b.lang:b.getAttribute("xml:lang")||b.getAttribute("lang"))return c=c.toLowerCase(),c===a||0===c.indexOf(a+"-");while((b=b.parentNode)&&1===b.nodeType);return!1}}),target:function(b){var c=a.location&&a.location.hash;return c&&c.slice(1)===b.id},root:function(a){return a===o},focus:function(a){return a===n.activeElement&&(!n.hasFocus||n.hasFocus())&&!!(a.type||a.href||~a.tabIndex)},enabled:oa(!1),disabled:oa(!0),checked:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&!!a.checked||"option"===b&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},empty:function(a){for(a=a.firstChild;a;a=a.nextSibling)if(a.nodeType<6)return!1;return!0},parent:function(a){return!d.pseudos.empty(a)},header:function(a){return X.test(a.nodeName)},input:function(a){return W.test(a.nodeName)},button:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&"button"===a.type||"button"===b},text:function(a){var b;return"input"===a.nodeName.toLowerCase()&&"text"===a.type&&(null==(b=a.getAttribute("type"))||"text"===b.toLowerCase())},first:pa(function(){return[0]}),last:pa(function(a,b){return[b-1]}),eq:pa(function(a,b,c){return[c<0?c+b:c]}),even:pa(function(a,b){for(var c=0;c=0;)a.push(d);return a}),gt:pa(function(a,b,c){for(var d=c<0?c+b:c;++d1?function(b,c,d){var e=a.length;while(e--)if(!a[e](b,c,d))return!1;return!0}:a[0]}function va(a,b,c){for(var d=0,e=b.length;d-1&&(f[j]=!(g[j]=l))}}else r=wa(r===g?r.splice(o,r.length):r),e?e(null,g,r,i):G.apply(g,r)})}function ya(a){for(var b,c,e,f=a.length,g=d.relative[a[0].type],h=g||d.relative[" "],i=g?1:0,k=ta(function(a){return a===b},h,!0),l=ta(function(a){return I(b,a)>-1},h,!0),m=[function(a,c,d){var e=!g&&(d||c!==j)||((b=c).nodeType?k(a,c,d):l(a,c,d));return b=null,e}];i1&&ua(m),i>1&&sa(a.slice(0,i-1).concat({value:" "===a[i-2].type?"*":""})).replace(P,"$1"),c,i0,e=a.length>0,f=function(f,g,h,i,k){var l,o,q,r=0,s="0",t=f&&[],u=[],v=j,x=f||e&&d.find.TAG("*",k),y=w+=null==v?1:Math.random()||.1,z=x.length;for(k&&(j=g===n||g||k);s!==z&&null!=(l=x[s]);s++){if(e&&l){o=0,g||l.ownerDocument===n||(m(l),h=!p);while(q=a[o++])if(q(l,g||n,h)){i.push(l);break}k&&(w=y)}c&&((l=!q&&l)&&r--,f&&t.push(l))}if(r+=s,c&&s!==r){o=0;while(q=b[o++])q(t,u,g,h);if(f){if(r>0)while(s--)t[s]||u[s]||(u[s]=E.call(i));u=wa(u)}G.apply(i,u),k&&!f&&u.length>0&&r+b.length>1&&ga.uniqueSort(i)}return k&&(w=y,j=v),t};return c?ia(f):f}return h=ga.compile=function(a,b){var c,d=[],e=[],f=A[a+" "];if(!f){b||(b=g(a)),c=b.length;while(c--)f=ya(b[c]),f[u]?d.push(f):e.push(f);f=A(a,za(e,d)),f.selector=a}return f},i=ga.select=function(a,b,e,f){var i,j,k,l,m,n="function"==typeof a&&a,o=!f&&g(a=n.selector||a);if(e=e||[],1===o.length){if(j=o[0]=o[0].slice(0),j.length>2&&"ID"===(k=j[0]).type&&c.getById&&9===b.nodeType&&p&&d.relative[j[1].type]){if(b=(d.find.ID(k.matches[0].replace(_,aa),b)||[])[0],!b)return e;n&&(b=b.parentNode),a=a.slice(j.shift().value.length)}i=V.needsContext.test(a)?0:j.length;while(i--){if(k=j[i],d.relative[l=k.type])break;if((m=d.find[l])&&(f=m(k.matches[0].replace(_,aa),$.test(j[0].type)&&qa(b.parentNode)||b))){if(j.splice(i,1),a=f.length&&sa(j),!a)return G.apply(e,f),e;break}}}return(n||h(a,o))(f,b,!p,e,!b||$.test(a)&&qa(b.parentNode)||b),e},c.sortStable=u.split("").sort(B).join("")===u,c.detectDuplicates=!!l,m(),c.sortDetached=ja(function(a){return 1&a.compareDocumentPosition(n.createElement("fieldset"))}),ja(function(a){return a.innerHTML="","#"===a.firstChild.getAttribute("href")})||ka("type|href|height|width",function(a,b,c){if(!c)return a.getAttribute(b,"type"===b.toLowerCase()?1:2)}),c.attributes&&ja(function(a){return a.innerHTML="",a.firstChild.setAttribute("value",""),""===a.firstChild.getAttribute("value")})||ka("value",function(a,b,c){if(!c&&"input"===a.nodeName.toLowerCase())return a.defaultValue}),ja(function(a){return null==a.getAttribute("disabled")})||ka(J,function(a,b,c){var d;if(!c)return a[b]===!0?b.toLowerCase():(d=a.getAttributeNode(b))&&d.specified?d.value:null}),ga}(a);r.find=x,r.expr=x.selectors,r.expr[":"]=r.expr.pseudos,r.uniqueSort=r.unique=x.uniqueSort,r.text=x.getText,r.isXMLDoc=x.isXML,r.contains=x.contains,r.escapeSelector=x.escape;var y=function(a,b,c){var d=[],e=void 0!==c;while((a=a[b])&&9!==a.nodeType)if(1===a.nodeType){if(e&&r(a).is(c))break;d.push(a)}return d},z=function(a,b){for(var c=[];a;a=a.nextSibling)1===a.nodeType&&a!==b&&c.push(a);return c},A=r.expr.match.needsContext,B=/^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i,C=/^.[^:#\[\.,]*$/;function D(a,b,c){if(r.isFunction(b))return r.grep(a,function(a,d){return!!b.call(a,d,a)!==c});if(b.nodeType)return r.grep(a,function(a){return a===b!==c});if("string"==typeof b){if(C.test(b))return r.filter(b,a,c);b=r.filter(b,a)}return r.grep(a,function(a){return i.call(b,a)>-1!==c&&1===a.nodeType})}r.filter=function(a,b,c){var d=b[0];return c&&(a=":not("+a+")"),1===b.length&&1===d.nodeType?r.find.matchesSelector(d,a)?[d]:[]:r.find.matches(a,r.grep(b,function(a){return 1===a.nodeType}))},r.fn.extend({find:function(a){var b,c,d=this.length,e=this;if("string"!=typeof a)return this.pushStack(r(a).filter(function(){for(b=0;b1?r.uniqueSort(c):c},filter:function(a){return this.pushStack(D(this,a||[],!1))},not:function(a){return this.pushStack(D(this,a||[],!0))},is:function(a){return!!D(this,"string"==typeof a&&A.test(a)?r(a):a||[],!1).length}});var E,F=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]+))$/,G=r.fn.init=function(a,b,c){var e,f;if(!a)return this;if(c=c||E,"string"==typeof a){if(e="<"===a[0]&&">"===a[a.length-1]&&a.length>=3?[null,a,null]:F.exec(a),!e||!e[1]&&b)return!b||b.jquery?(b||c).find(a):this.constructor(b).find(a);if(e[1]){if(b=b instanceof r?b[0]:b,r.merge(this,r.parseHTML(e[1],b&&b.nodeType?b.ownerDocument||b:d,!0)),B.test(e[1])&&r.isPlainObject(b))for(e in b)r.isFunction(this[e])?this[e](b[e]):this.attr(e,b[e]);return this}return f=d.getElementById(e[2]),f&&(this[0]=f,this.length=1),this}return a.nodeType?(this[0]=a,this.length=1,this):r.isFunction(a)?void 0!==c.ready?c.ready(a):a(r):r.makeArray(a,this)};G.prototype=r.fn,E=r(d);var H=/^(?:parents|prev(?:Until|All))/,I={children:!0,contents:!0,next:!0,prev:!0};r.fn.extend({has:function(a){var b=r(a,this),c=b.length;return this.filter(function(){for(var a=0;a-1:1===c.nodeType&&r.find.matchesSelector(c,a))){f.push(c);break}return this.pushStack(f.length>1?r.uniqueSort(f):f)},index:function(a){return a?"string"==typeof a?i.call(r(a),this[0]):i.call(this,a.jquery?a[0]:a):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(a,b){return this.pushStack(r.uniqueSort(r.merge(this.get(),r(a,b))))},addBack:function(a){return this.add(null==a?this.prevObject:this.prevObject.filter(a))}});function J(a,b){while((a=a[b])&&1!==a.nodeType);return a}r.each({parent:function(a){var b=a.parentNode;return b&&11!==b.nodeType?b:null},parents:function(a){return y(a,"parentNode")},parentsUntil:function(a,b,c){return y(a,"parentNode",c)},next:function(a){return J(a,"nextSibling")},prev:function(a){return J(a,"previousSibling")},nextAll:function(a){return y(a,"nextSibling")},prevAll:function(a){return y(a,"previousSibling")},nextUntil:function(a,b,c){return y(a,"nextSibling",c)},prevUntil:function(a,b,c){return y(a,"previousSibling",c)},siblings:function(a){return z((a.parentNode||{}).firstChild,a)},children:function(a){return z(a.firstChild)},contents:function(a){return a.contentDocument||r.merge([],a.childNodes)}},function(a,b){r.fn[a]=function(c,d){var e=r.map(this,b,c);return"Until"!==a.slice(-5)&&(d=c),d&&"string"==typeof d&&(e=r.filter(d,e)),this.length>1&&(I[a]||r.uniqueSort(e),H.test(a)&&e.reverse()),this.pushStack(e)}});var K=/\S+/g;function L(a){var b={};return r.each(a.match(K)||[],function(a,c){b[c]=!0}),b}r.Callbacks=function(a){a="string"==typeof a?L(a):r.extend({},a);var b,c,d,e,f=[],g=[],h=-1,i=function(){for(e=a.once,d=b=!0;g.length;h=-1){c=g.shift();while(++h-1)f.splice(c,1),c<=h&&h--}),this},has:function(a){return a?r.inArray(a,f)>-1:f.length>0},empty:function(){return f&&(f=[]),this},disable:function(){return e=g=[],f=c="",this},disabled:function(){return!f},lock:function(){return e=g=[],c||b||(f=c=""),this},locked:function(){return!!e},fireWith:function(a,c){return e||(c=c||[],c=[a,c.slice?c.slice():c],g.push(c),b||i()),this},fire:function(){return j.fireWith(this,arguments),this},fired:function(){return!!d}};return j};function M(a){return a}function N(a){throw a}function O(a,b,c){var d;try{a&&r.isFunction(d=a.promise)?d.call(a).done(b).fail(c):a&&r.isFunction(d=a.then)?d.call(a,b,c):b.call(void 0,a)}catch(a){c.call(void 0,a)}}r.extend({Deferred:function(b){var c=[["notify","progress",r.Callbacks("memory"),r.Callbacks("memory"),2],["resolve","done",r.Callbacks("once memory"),r.Callbacks("once memory"),0,"resolved"],["reject","fail",r.Callbacks("once memory"),r.Callbacks("once memory"),1,"rejected"]],d="pending",e={state:function(){return d},always:function(){return f.done(arguments).fail(arguments),this},"catch":function(a){return e.then(null,a)},pipe:function(){var a=arguments;return r.Deferred(function(b){r.each(c,function(c,d){var e=r.isFunction(a[d[4]])&&a[d[4]];f[d[1]](function(){var a=e&&e.apply(this,arguments);a&&r.isFunction(a.promise)?a.promise().progress(b.notify).done(b.resolve).fail(b.reject):b[d[0]+"With"](this,e?[a]:arguments)})}),a=null}).promise()},then:function(b,d,e){var f=0;function g(b,c,d,e){return function(){var h=this,i=arguments,j=function(){var a,j;if(!(b=f&&(d!==N&&(h=void 0,i=[a]),c.rejectWith(h,i))}};b?k():(r.Deferred.getStackHook&&(k.stackTrace=r.Deferred.getStackHook()),a.setTimeout(k))}}return r.Deferred(function(a){c[0][3].add(g(0,a,r.isFunction(e)?e:M,a.notifyWith)),c[1][3].add(g(0,a,r.isFunction(b)?b:M)),c[2][3].add(g(0,a,r.isFunction(d)?d:N))}).promise()},promise:function(a){return null!=a?r.extend(a,e):e}},f={};return r.each(c,function(a,b){var g=b[2],h=b[5];e[b[1]]=g.add,h&&g.add(function(){d=h},c[3-a][2].disable,c[0][2].lock),g.add(b[3].fire),f[b[0]]=function(){return f[b[0]+"With"](this===f?void 0:this,arguments),this},f[b[0]+"With"]=g.fireWith}),e.promise(f),b&&b.call(f,f),f},when:function(a){var b=arguments.length,c=b,d=Array(c),e=f.call(arguments),g=r.Deferred(),h=function(a){return function(c){d[a]=this,e[a]=arguments.length>1?f.call(arguments):c,--b||g.resolveWith(d,e)}};if(b<=1&&(O(a,g.done(h(c)).resolve,g.reject),"pending"===g.state()||r.isFunction(e[c]&&e[c].then)))return g.then();while(c--)O(e[c],h(c),g.reject);return g.promise()}});var P=/^(Eval|Internal|Range|Reference|Syntax|Type|URI)Error$/;r.Deferred.exceptionHook=function(b,c){a.console&&a.console.warn&&b&&P.test(b.name)&&a.console.warn("jQuery.Deferred exception: "+b.message,b.stack,c)},r.readyException=function(b){a.setTimeout(function(){throw b})};var Q=r.Deferred();r.fn.ready=function(a){return Q.then(a)["catch"](function(a){r.readyException(a)}),this},r.extend({isReady:!1,readyWait:1,holdReady:function(a){a?r.readyWait++:r.ready(!0)},ready:function(a){(a===!0?--r.readyWait:r.isReady)||(r.isReady=!0,a!==!0&&--r.readyWait>0||Q.resolveWith(d,[r]))}}),r.ready.then=Q.then;function R(){d.removeEventListener("DOMContentLoaded",R),a.removeEventListener("load",R),r.ready()}"complete"===d.readyState||"loading"!==d.readyState&&!d.documentElement.doScroll?a.setTimeout(r.ready):(d.addEventListener("DOMContentLoaded",R), +a.addEventListener("load",R));var S=function(a,b,c,d,e,f,g){var h=0,i=a.length,j=null==c;if("object"===r.type(c)){e=!0;for(h in c)S(a,b,h,c[h],!0,f,g)}else if(void 0!==d&&(e=!0,r.isFunction(d)||(g=!0),j&&(g?(b.call(a,d),b=null):(j=b,b=function(a,b,c){return j.call(r(a),c)})),b))for(;h1,null,!0)},removeData:function(a){return this.each(function(){W.remove(this,a)})}}),r.extend({queue:function(a,b,c){var d;if(a)return b=(b||"fx")+"queue",d=V.get(a,b),c&&(!d||r.isArray(c)?d=V.access(a,b,r.makeArray(c)):d.push(c)),d||[]},dequeue:function(a,b){b=b||"fx";var c=r.queue(a,b),d=c.length,e=c.shift(),f=r._queueHooks(a,b),g=function(){r.dequeue(a,b)};"inprogress"===e&&(e=c.shift(),d--),e&&("fx"===b&&c.unshift("inprogress"),delete f.stop,e.call(a,g,f)),!d&&f&&f.empty.fire()},_queueHooks:function(a,b){var c=b+"queueHooks";return V.get(a,c)||V.access(a,c,{empty:r.Callbacks("once memory").add(function(){V.remove(a,[b+"queue",c])})})}}),r.fn.extend({queue:function(a,b){var c=2;return"string"!=typeof a&&(b=a,a="fx",c--),arguments.length\x20\t\r\n\f]+)/i,ja=/^$|\/(?:java|ecma)script/i,ka={option:[1,""],thead:[1,"","
"],col:[2,"","
"],tr:[2,"","
"],td:[3,"","
"],_default:[0,"",""]};ka.optgroup=ka.option,ka.tbody=ka.tfoot=ka.colgroup=ka.caption=ka.thead,ka.th=ka.td;function la(a,b){var c="undefined"!=typeof a.getElementsByTagName?a.getElementsByTagName(b||"*"):"undefined"!=typeof a.querySelectorAll?a.querySelectorAll(b||"*"):[];return void 0===b||b&&r.nodeName(a,b)?r.merge([a],c):c}function ma(a,b){for(var c=0,d=a.length;c-1)e&&e.push(f);else if(j=r.contains(f.ownerDocument,f),g=la(l.appendChild(f),"script"),j&&ma(g),c){k=0;while(f=g[k++])ja.test(f.type||"")&&c.push(f)}return l}!function(){var a=d.createDocumentFragment(),b=a.appendChild(d.createElement("div")),c=d.createElement("input");c.setAttribute("type","radio"),c.setAttribute("checked","checked"),c.setAttribute("name","t"),b.appendChild(c),o.checkClone=b.cloneNode(!0).cloneNode(!0).lastChild.checked,b.innerHTML="",o.noCloneChecked=!!b.cloneNode(!0).lastChild.defaultValue}();var pa=d.documentElement,qa=/^key/,ra=/^(?:mouse|pointer|contextmenu|drag|drop)|click/,sa=/^([^.]*)(?:\.(.+)|)/;function ta(){return!0}function ua(){return!1}function va(){try{return d.activeElement}catch(a){}}function wa(a,b,c,d,e,f){var g,h;if("object"==typeof b){"string"!=typeof c&&(d=d||c,c=void 0);for(h in b)wa(a,h,c,d,b[h],f);return a}if(null==d&&null==e?(e=c,d=c=void 0):null==e&&("string"==typeof c?(e=d,d=void 0):(e=d,d=c,c=void 0)),e===!1)e=ua;else if(!e)return a;return 1===f&&(g=e,e=function(a){return r().off(a),g.apply(this,arguments)},e.guid=g.guid||(g.guid=r.guid++)),a.each(function(){r.event.add(this,b,e,d,c)})}r.event={global:{},add:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,n,o,p,q=V.get(a);if(q){c.handler&&(f=c,c=f.handler,e=f.selector),e&&r.find.matchesSelector(pa,e),c.guid||(c.guid=r.guid++),(i=q.events)||(i=q.events={}),(g=q.handle)||(g=q.handle=function(b){return"undefined"!=typeof r&&r.event.triggered!==b.type?r.event.dispatch.apply(a,arguments):void 0}),b=(b||"").match(K)||[""],j=b.length;while(j--)h=sa.exec(b[j])||[],n=p=h[1],o=(h[2]||"").split(".").sort(),n&&(l=r.event.special[n]||{},n=(e?l.delegateType:l.bindType)||n,l=r.event.special[n]||{},k=r.extend({type:n,origType:p,data:d,handler:c,guid:c.guid,selector:e,needsContext:e&&r.expr.match.needsContext.test(e),namespace:o.join(".")},f),(m=i[n])||(m=i[n]=[],m.delegateCount=0,l.setup&&l.setup.call(a,d,o,g)!==!1||a.addEventListener&&a.addEventListener(n,g)),l.add&&(l.add.call(a,k),k.handler.guid||(k.handler.guid=c.guid)),e?m.splice(m.delegateCount++,0,k):m.push(k),r.event.global[n]=!0)}},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,n,o,p,q=V.hasData(a)&&V.get(a);if(q&&(i=q.events)){b=(b||"").match(K)||[""],j=b.length;while(j--)if(h=sa.exec(b[j])||[],n=p=h[1],o=(h[2]||"").split(".").sort(),n){l=r.event.special[n]||{},n=(d?l.delegateType:l.bindType)||n,m=i[n]||[],h=h[2]&&new RegExp("(^|\\.)"+o.join("\\.(?:.*\\.|)")+"(\\.|$)"),g=f=m.length;while(f--)k=m[f],!e&&p!==k.origType||c&&c.guid!==k.guid||h&&!h.test(k.namespace)||d&&d!==k.selector&&("**"!==d||!k.selector)||(m.splice(f,1),k.selector&&m.delegateCount--,l.remove&&l.remove.call(a,k));g&&!m.length&&(l.teardown&&l.teardown.call(a,o,q.handle)!==!1||r.removeEvent(a,n,q.handle),delete i[n])}else for(n in i)r.event.remove(a,n+b[j],c,d,!0);r.isEmptyObject(i)&&V.remove(a,"handle events")}},dispatch:function(a){var b=r.event.fix(a),c,d,e,f,g,h,i=new Array(arguments.length),j=(V.get(this,"events")||{})[b.type]||[],k=r.event.special[b.type]||{};for(i[0]=b,c=1;c-1:r.find(e,this,null,[i]).length),d[e]&&d.push(f);d.length&&g.push({elem:i,handlers:d})}return h\x20\t\r\n\f]*)[^>]*)\/>/gi,ya=/\s*$/g;function Ca(a,b){return r.nodeName(a,"table")&&r.nodeName(11!==b.nodeType?b:b.firstChild,"tr")?a.getElementsByTagName("tbody")[0]||a:a}function Da(a){return a.type=(null!==a.getAttribute("type"))+"/"+a.type,a}function Ea(a){var b=Aa.exec(a.type);return b?a.type=b[1]:a.removeAttribute("type"),a}function Fa(a,b){var c,d,e,f,g,h,i,j;if(1===b.nodeType){if(V.hasData(a)&&(f=V.access(a),g=V.set(b,f),j=f.events)){delete g.handle,g.events={};for(e in j)for(c=0,d=j[e].length;c1&&"string"==typeof q&&!o.checkClone&&za.test(q))return a.each(function(e){var f=a.eq(e);s&&(b[0]=q.call(this,e,f.html())),Ha(f,b,c,d)});if(m&&(e=oa(b,a[0].ownerDocument,!1,a,d),f=e.firstChild,1===e.childNodes.length&&(e=f),f||d)){for(h=r.map(la(e,"script"),Da),i=h.length;l")},clone:function(a,b,c){var d,e,f,g,h=a.cloneNode(!0),i=r.contains(a.ownerDocument,a);if(!(o.noCloneChecked||1!==a.nodeType&&11!==a.nodeType||r.isXMLDoc(a)))for(g=la(h),f=la(a),d=0,e=f.length;d0&&ma(g,!i&&la(a,"script")),h},cleanData:function(a){for(var b,c,d,e=r.event.special,f=0;void 0!==(c=a[f]);f++)if(T(c)){if(b=c[V.expando]){if(b.events)for(d in b.events)e[d]?r.event.remove(c,d):r.removeEvent(c,d,b.handle);c[V.expando]=void 0}c[W.expando]&&(c[W.expando]=void 0)}}}),r.fn.extend({detach:function(a){return Ia(this,a,!0)},remove:function(a){return Ia(this,a)},text:function(a){return S(this,function(a){return void 0===a?r.text(this):this.empty().each(function(){1!==this.nodeType&&11!==this.nodeType&&9!==this.nodeType||(this.textContent=a)})},null,a,arguments.length)},append:function(){return Ha(this,arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=Ca(this,a);b.appendChild(a)}})},prepend:function(){return Ha(this,arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=Ca(this,a);b.insertBefore(a,b.firstChild)}})},before:function(){return Ha(this,arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this)})},after:function(){return Ha(this,arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this.nextSibling)})},empty:function(){for(var a,b=0;null!=(a=this[b]);b++)1===a.nodeType&&(r.cleanData(la(a,!1)),a.textContent="");return this},clone:function(a,b){return a=null!=a&&a,b=null==b?a:b,this.map(function(){return r.clone(this,a,b)})},html:function(a){return S(this,function(a){var b=this[0]||{},c=0,d=this.length;if(void 0===a&&1===b.nodeType)return b.innerHTML;if("string"==typeof a&&!ya.test(a)&&!ka[(ia.exec(a)||["",""])[1].toLowerCase()]){a=r.htmlPrefilter(a);try{for(;c1)}}),r.fn.delay=function(b,c){return b=r.fx?r.fx.speeds[b]||b:b,c=c||"fx",this.queue(c,function(c,d){var e=a.setTimeout(c,b);d.stop=function(){a.clearTimeout(e)}})},function(){var a=d.createElement("input"),b=d.createElement("select"),c=b.appendChild(d.createElement("option"));a.type="checkbox",o.checkOn=""!==a.value,o.optSelected=c.selected,a=d.createElement("input"),a.value="t",a.type="radio",o.radioValue="t"===a.value}();var Xa,Ya=r.expr.attrHandle;r.fn.extend({attr:function(a,b){return S(this,r.attr,a,b,arguments.length>1)},removeAttr:function(a){return this.each(function(){r.removeAttr(this,a)})}}),r.extend({attr:function(a,b,c){var d,e,f=a.nodeType;if(3!==f&&8!==f&&2!==f)return"undefined"==typeof a.getAttribute?r.prop(a,b,c):(1===f&&r.isXMLDoc(a)||(e=r.attrHooks[b.toLowerCase()]||(r.expr.match.bool.test(b)?Xa:void 0)),void 0!==c?null===c?void r.removeAttr(a,b):e&&"set"in e&&void 0!==(d=e.set(a,c,b))?d:(a.setAttribute(b,c+""),c):e&&"get"in e&&null!==(d=e.get(a,b))?d:(d=r.find.attr(a,b),null==d?void 0:d))},attrHooks:{type:{set:function(a,b){if(!o.radioValue&&"radio"===b&&r.nodeName(a,"input")){var c=a.value;return a.setAttribute("type",b),c&&(a.value=c),b}}}},removeAttr:function(a,b){var c,d=0,e=b&&b.match(K);if(e&&1===a.nodeType)while(c=e[d++])a.removeAttribute(c)}}),Xa={set:function(a,b,c){return b===!1?r.removeAttr(a,c):a.setAttribute(c,c),c}},r.each(r.expr.match.bool.source.match(/\w+/g),function(a,b){var c=Ya[b]||r.find.attr;Ya[b]=function(a,b,d){var e,f,g=b.toLowerCase();return d||(f=Ya[g],Ya[g]=e,e=null!=c(a,b,d)?g:null,Ya[g]=f),e}});var Za=/^(?:input|select|textarea|button)$/i,$a=/^(?:a|area)$/i;r.fn.extend({prop:function(a,b){return S(this,r.prop,a,b,arguments.length>1)},removeProp:function(a){return this.each(function(){delete this[r.propFix[a]||a]})}}),r.extend({prop:function(a,b,c){var d,e,f=a.nodeType;if(3!==f&&8!==f&&2!==f)return 1===f&&r.isXMLDoc(a)||(b=r.propFix[b]||b,e=r.propHooks[b]),void 0!==c?e&&"set"in e&&void 0!==(d=e.set(a,c,b))?d:a[b]=c:e&&"get"in e&&null!==(d=e.get(a,b))?d:a[b]},propHooks:{tabIndex:{get:function(a){var b=r.find.attr(a,"tabindex");return b?parseInt(b,10):Za.test(a.nodeName)||$a.test(a.nodeName)&&a.href?0:-1}}},propFix:{"for":"htmlFor","class":"className"}}),o.optSelected||(r.propHooks.selected={get:function(a){var b=a.parentNode;return b&&b.parentNode&&b.parentNode.selectedIndex,null},set:function(a){var b=a.parentNode;b&&(b.selectedIndex,b.parentNode&&b.parentNode.selectedIndex)}}),r.each(["tabIndex","readOnly","maxLength","cellSpacing","cellPadding","rowSpan","colSpan","useMap","frameBorder","contentEditable"],function(){r.propFix[this.toLowerCase()]=this});var _a=/[\t\r\n\f]/g;function ab(a){return a.getAttribute&&a.getAttribute("class")||""}r.fn.extend({addClass:function(a){var b,c,d,e,f,g,h,i=0;if(r.isFunction(a))return this.each(function(b){r(this).addClass(a.call(this,b,ab(this)))});if("string"==typeof a&&a){b=a.match(K)||[];while(c=this[i++])if(e=ab(c),d=1===c.nodeType&&(" "+e+" ").replace(_a," ")){g=0;while(f=b[g++])d.indexOf(" "+f+" ")<0&&(d+=f+" ");h=r.trim(d),e!==h&&c.setAttribute("class",h)}}return this},removeClass:function(a){var b,c,d,e,f,g,h,i=0;if(r.isFunction(a))return this.each(function(b){r(this).removeClass(a.call(this,b,ab(this)))});if(!arguments.length)return this.attr("class","");if("string"==typeof a&&a){b=a.match(K)||[];while(c=this[i++])if(e=ab(c),d=1===c.nodeType&&(" "+e+" ").replace(_a," ")){g=0;while(f=b[g++])while(d.indexOf(" "+f+" ")>-1)d=d.replace(" "+f+" "," ");h=r.trim(d),e!==h&&c.setAttribute("class",h)}}return this},toggleClass:function(a,b){var c=typeof a;return"boolean"==typeof b&&"string"===c?b?this.addClass(a):this.removeClass(a):r.isFunction(a)?this.each(function(c){r(this).toggleClass(a.call(this,c,ab(this),b),b)}):this.each(function(){var b,d,e,f;if("string"===c){d=0,e=r(this),f=a.match(K)||[];while(b=f[d++])e.hasClass(b)?e.removeClass(b):e.addClass(b)}else void 0!==a&&"boolean"!==c||(b=ab(this),b&&V.set(this,"__className__",b),this.setAttribute&&this.setAttribute("class",b||a===!1?"":V.get(this,"__className__")||""))})},hasClass:function(a){var b,c,d=0;b=" "+a+" ";while(c=this[d++])if(1===c.nodeType&&(" "+ab(c)+" ").replace(_a," ").indexOf(b)>-1)return!0;return!1}});var bb=/\r/g,cb=/[\x20\t\r\n\f]+/g;r.fn.extend({val:function(a){var b,c,d,e=this[0];{if(arguments.length)return d=r.isFunction(a),this.each(function(c){var e;1===this.nodeType&&(e=d?a.call(this,c,r(this).val()):a,null==e?e="":"number"==typeof e?e+="":r.isArray(e)&&(e=r.map(e,function(a){return null==a?"":a+""})),b=r.valHooks[this.type]||r.valHooks[this.nodeName.toLowerCase()],b&&"set"in b&&void 0!==b.set(this,e,"value")||(this.value=e))});if(e)return b=r.valHooks[e.type]||r.valHooks[e.nodeName.toLowerCase()],b&&"get"in b&&void 0!==(c=b.get(e,"value"))?c:(c=e.value,"string"==typeof c?c.replace(bb,""):null==c?"":c)}}}),r.extend({valHooks:{option:{get:function(a){var b=r.find.attr(a,"value");return null!=b?b:r.trim(r.text(a)).replace(cb," ")}},select:{get:function(a){for(var b,c,d=a.options,e=a.selectedIndex,f="select-one"===a.type,g=f?null:[],h=f?e+1:d.length,i=e<0?h:f?e:0;i-1)&&(c=!0);return c||(a.selectedIndex=-1),f}}}}),r.each(["radio","checkbox"],function(){r.valHooks[this]={set:function(a,b){if(r.isArray(b))return a.checked=r.inArray(r(a).val(),b)>-1}},o.checkOn||(r.valHooks[this].get=function(a){return null===a.getAttribute("value")?"on":a.value})});var db=/^(?:focusinfocus|focusoutblur)$/;r.extend(r.event,{trigger:function(b,c,e,f){var g,h,i,j,k,m,n,o=[e||d],p=l.call(b,"type")?b.type:b,q=l.call(b,"namespace")?b.namespace.split("."):[];if(h=i=e=e||d,3!==e.nodeType&&8!==e.nodeType&&!db.test(p+r.event.triggered)&&(p.indexOf(".")>-1&&(q=p.split("."),p=q.shift(),q.sort()),k=p.indexOf(":")<0&&"on"+p,b=b[r.expando]?b:new r.Event(p,"object"==typeof b&&b),b.isTrigger=f?2:3,b.namespace=q.join("."),b.rnamespace=b.namespace?new RegExp("(^|\\.)"+q.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,b.result=void 0,b.target||(b.target=e),c=null==c?[b]:r.makeArray(c,[b]),n=r.event.special[p]||{},f||!n.trigger||n.trigger.apply(e,c)!==!1)){if(!f&&!n.noBubble&&!r.isWindow(e)){for(j=n.delegateType||p,db.test(j+p)||(h=h.parentNode);h;h=h.parentNode)o.push(h),i=h;i===(e.ownerDocument||d)&&o.push(i.defaultView||i.parentWindow||a)}g=0;while((h=o[g++])&&!b.isPropagationStopped())b.type=g>1?j:n.bindType||p,m=(V.get(h,"events")||{})[b.type]&&V.get(h,"handle"),m&&m.apply(h,c),m=k&&h[k],m&&m.apply&&T(h)&&(b.result=m.apply(h,c),b.result===!1&&b.preventDefault());return b.type=p,f||b.isDefaultPrevented()||n._default&&n._default.apply(o.pop(),c)!==!1||!T(e)||k&&r.isFunction(e[p])&&!r.isWindow(e)&&(i=e[k],i&&(e[k]=null),r.event.triggered=p,e[p](),r.event.triggered=void 0,i&&(e[k]=i)),b.result}},simulate:function(a,b,c){var d=r.extend(new r.Event,c,{type:a,isSimulated:!0});r.event.trigger(d,null,b)}}),r.fn.extend({trigger:function(a,b){return this.each(function(){r.event.trigger(a,b,this)})},triggerHandler:function(a,b){var c=this[0];if(c)return r.event.trigger(a,b,c,!0)}}),r.each("blur focus focusin focusout resize scroll click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup contextmenu".split(" "),function(a,b){r.fn[b]=function(a,c){return arguments.length>0?this.on(b,null,a,c):this.trigger(b)}}),r.fn.extend({hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)}}),o.focusin="onfocusin"in a,o.focusin||r.each({focus:"focusin",blur:"focusout"},function(a,b){var c=function(a){r.event.simulate(b,a.target,r.event.fix(a))};r.event.special[b]={setup:function(){var d=this.ownerDocument||this,e=V.access(d,b);e||d.addEventListener(a,c,!0),V.access(d,b,(e||0)+1)},teardown:function(){var d=this.ownerDocument||this,e=V.access(d,b)-1;e?V.access(d,b,e):(d.removeEventListener(a,c,!0),V.remove(d,b))}}});var eb=/\[\]$/,fb=/\r?\n/g,gb=/^(?:submit|button|image|reset|file)$/i,hb=/^(?:input|select|textarea|keygen)/i;function ib(a,b,c,d){var e;if(r.isArray(b))r.each(b,function(b,e){c||eb.test(a)?d(a,e):ib(a+"["+("object"==typeof e&&null!=e?b:"")+"]",e,c,d)});else if(c||"object"!==r.type(b))d(a,b);else for(e in b)ib(a+"["+e+"]",b[e],c,d)}r.param=function(a,b){var c,d=[],e=function(a,b){var c=r.isFunction(b)?b():b;d[d.length]=encodeURIComponent(a)+"="+encodeURIComponent(null==c?"":c)};if(r.isArray(a)||a.jquery&&!r.isPlainObject(a))r.each(a,function(){e(this.name,this.value)});else for(c in a)ib(c,a[c],b,e); +return d.join("&")},r.fn.extend({serialize:function(){return r.param(this.serializeArray())},serializeArray:function(){return this.map(function(){var a=r.prop(this,"elements");return a?r.makeArray(a):this}).filter(function(){var a=this.type;return this.name&&!r(this).is(":disabled")&&hb.test(this.nodeName)&&!gb.test(a)&&(this.checked||!ha.test(a))}).map(function(a,b){var c=r(this).val();return null==c?null:r.isArray(c)?r.map(c,function(a){return{name:b.name,value:a.replace(fb,"\r\n")}}):{name:b.name,value:c.replace(fb,"\r\n")}}).get()}}),r.fn.extend({wrapAll:function(a){var b;return this[0]&&(r.isFunction(a)&&(a=a.call(this[0])),b=r(a,this[0].ownerDocument).eq(0).clone(!0),this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstElementChild)a=a.firstElementChild;return a}).append(this)),this},wrapInner:function(a){return r.isFunction(a)?this.each(function(b){r(this).wrapInner(a.call(this,b))}):this.each(function(){var b=r(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){var b=r.isFunction(a);return this.each(function(c){r(this).wrapAll(b?a.call(this,c):a)})},unwrap:function(a){return this.parent(a).not("body").each(function(){r(this).replaceWith(this.childNodes)}),this}}),r.expr.pseudos.hidden=function(a){return!r.expr.pseudos.visible(a)},r.expr.pseudos.visible=function(a){return!!(a.offsetWidth||a.offsetHeight||a.getClientRects().length)},o.createHTMLDocument=function(){var a=d.implementation.createHTMLDocument("").body;return a.innerHTML="
",2===a.childNodes.length}(),r.parseHTML=function(a,b,c){if("string"!=typeof a)return[];"boolean"==typeof b&&(c=b,b=!1);var e,f,g;return b||(o.createHTMLDocument?(b=d.implementation.createHTMLDocument(""),e=b.createElement("base"),e.href=d.location.href,b.head.appendChild(e)):b=d),f=B.exec(a),g=!c&&[],f?[b.createElement(f[1])]:(f=oa([a],b,g),g&&g.length&&r(g).remove(),r.merge([],f.childNodes))};function jb(a){return r.isWindow(a)?a:9===a.nodeType&&a.defaultView}r.offset={setOffset:function(a,b,c){var d,e,f,g,h,i,j,k=r.css(a,"position"),l=r(a),m={};"static"===k&&(a.style.position="relative"),h=l.offset(),f=r.css(a,"top"),i=r.css(a,"left"),j=("absolute"===k||"fixed"===k)&&(f+i).indexOf("auto")>-1,j?(d=l.position(),g=d.top,e=d.left):(g=parseFloat(f)||0,e=parseFloat(i)||0),r.isFunction(b)&&(b=b.call(a,c,r.extend({},h))),null!=b.top&&(m.top=b.top-h.top+g),null!=b.left&&(m.left=b.left-h.left+e),"using"in b?b.using.call(a,m):l.css(m)}},r.fn.extend({offset:function(a){if(arguments.length)return void 0===a?this:this.each(function(b){r.offset.setOffset(this,a,b)});var b,c,d,e,f=this[0];if(f)return f.getClientRects().length?(d=f.getBoundingClientRect(),d.width||d.height?(e=f.ownerDocument,c=jb(e),b=e.documentElement,{top:d.top+c.pageYOffset-b.clientTop,left:d.left+c.pageXOffset-b.clientLeft}):d):{top:0,left:0}},position:function(){if(this[0]){var a,b,c=this[0],d={top:0,left:0};return"fixed"===r.css(c,"position")?b=c.getBoundingClientRect():(a=this.offsetParent(),b=this.offset(),r.nodeName(a[0],"html")||(d=a.offset()),d={top:d.top+r.css(a[0],"borderTopWidth",!0),left:d.left+r.css(a[0],"borderLeftWidth",!0)}),{top:b.top-d.top-r.css(c,"marginTop",!0),left:b.left-d.left-r.css(c,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var a=this.offsetParent;while(a&&"static"===r.css(a,"position"))a=a.offsetParent;return a||pa})}}),r.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(a,b){var c="pageYOffset"===b;r.fn[a]=function(d){return S(this,function(a,d,e){var f=jb(a);return void 0===e?f?f[b]:a[d]:void(f?f.scrollTo(c?f.pageXOffset:e,c?e:f.pageYOffset):a[d]=e)},a,d,arguments.length)}}),r.each(["top","left"],function(a,b){r.cssHooks[b]=Na(o.pixelPosition,function(a,c){if(c)return c=Ma(a,b),Ka.test(c)?r(a).position()[b]+"px":c})}),r.each({Height:"height",Width:"width"},function(a,b){r.each({padding:"inner"+a,content:b,"":"outer"+a},function(c,d){r.fn[d]=function(e,f){var g=arguments.length&&(c||"boolean"!=typeof e),h=c||(e===!0||f===!0?"margin":"border");return S(this,function(b,c,e){var f;return r.isWindow(b)?0===d.indexOf("outer")?b["inner"+a]:b.document.documentElement["client"+a]:9===b.nodeType?(f=b.documentElement,Math.max(b.body["scroll"+a],f["scroll"+a],b.body["offset"+a],f["offset"+a],f["client"+a])):void 0===e?r.css(b,c,h):r.style(b,c,e,h)},b,g?e:void 0,g)}})}),"function"==typeof define&&define.amd&&define("jquery",[],function(){return r});var kb=a.jQuery,lb=a.$;return r.noConflict=function(b){return a.$===r&&(a.$=lb),b&&a.jQuery===r&&(a.jQuery=kb),r},b||(a.jQuery=a.$=r),r}); ADDED js-path.scm Index: js-path.scm ================================================================== --- /dev/null +++ js-path.scm @@ -0,0 +1,1 @@ +(define *java-script-lib* (conc (common:get-install-area) "/share/js/jquery-3.1.0.slim.min.js")) ADDED sample-sauth-paths.scm Index: sample-sauth-paths.scm ================================================================== --- /dev/null +++ sample-sauth-paths.scm @@ -0,0 +1,5 @@ +(define *db-path* "/path/to/db") +(define *exe-path* "/path/to/store/suids") +(define *exe-src* "/path/to/spublish/and/sretrieve/executables") +(define *sauth-path* "/path/to/production/sauthorize/exe") +(define *super-users* '("user1" "user2")) ADDED sauth-common.scm Index: sauth-common.scm ================================================================== --- /dev/null +++ sauth-common.scm @@ -0,0 +1,302 @@ + +;; Create the sqlite db +(define (sauthorize:db-do proc) + (if (or (not *db-path*) + (not (file-exists? *db-path*))) + (begin + (print 0 "[database]\nlocation " *db-path* " \n\n Is missing from the config file!") + (exit 1))) + (if (and *db-path* + (directory? *db-path*) + (file-read-access? *db-path*)) + (let* ((dbpath (conc *db-path* "/sauthorize.db")) + (writeable (file-write-access? dbpath)) + (dbexists (file-exists? dbpath))) + (handle-exceptions + exn + (begin + (debug:print 2 "ERROR: problem accessing db " dbpath + ((condition-property-accessor 'exn 'message) exn)) + (exit 1)) + ;(print "calling proc " proc "db path " dbpath ) + (call-with-database + dbpath + (lambda (db) + ;(print 0 "calling proc " proc " on db " db) + (set-busy-handler! db (busy-timeout 10000)) ;; 10 sec timeout + (if (not dbexists)(sauthorize:initialize-db db)) + (proc db))))) + (print 0 "ERROR: invalid path for storing database: " *db-path*))) + +;;execute a query +(define (sauthorize:db-qry db qry) + ;(print qry) + (exec (sql db qry))) + + +(define (sauthorize:do-as-calling-user proc) + (let ((eid (current-effective-user-id)) + (cid (current-user-id))) + (if (not (eq? eid cid)) ;; running suid + (set! (current-effective-user-id) cid)) + ;(print 0 "cid " cid " eid:" eid) + (proc) + (if (not (eq? eid cid)) + (set! (current-effective-user-id) eid)))) + + +(define (run-cmd cmd arg-list) + ; (print (current-effective-user-id)) + ;(handle-exceptions +; exn +; (print 0 "ERROR: failed to run script " cmd " with params " arg-list " " (exn assert)) + (let ((pid (process-run cmd arg-list))) + (process-wait pid)) +) +;) + + +(define (regster-log inl usr-id area-id cmd) + (sauth-common:shell-do-as-adm + (lambda () + (sauthorize:db-do (lambda (db) + (sauthorize:db-qry db (conc "INSERT INTO actions (cmd,user_id,area_id,action_type ) VALUES ('sretrieve " inl "'," usr-id "," area-id ", 'cat' )"))))))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; Check user types +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + + + +;;check if a user is an admin +(define (is-admin username) + (let* ((admin #f)) + (sauthorize:db-do (lambda (db) + (let* ((data-row (query fetch (sql db (conc "SELECT users.is_admin FROM users where users.username = '" username "'"))))) + (if (not (null? data-row)) + (let ((col (car data-row))) + (if (equal? col "yes") + (set! admin #t))))))) +admin)) + + +;;check if a user is an read-admin +(define (is-read-admin username) + (let* ((admin #f)) + (sauthorize:db-do (lambda (db) + (let* ((data-row (query fetch (sql db (conc "SELECT users.is_admin FROM users where users.username = '" username "'"))))) + (if (not (null? data-row)) + (let ((col (car data-row))) + (if (equal? col "read-admin") + (set! admin #t))))))) +admin)) + + +;;check if user has specifc role for a area +(define (is-user role username area) + (let* ((has-access #f)) + (sauthorize:db-do (lambda (db) + (let* ((data-row (query fetch (sql db (conc "SELECT permissions.access_type, permissions.expiration FROM users , areas, permissions where permissions.user_id = users.id and permissions.area_id = areas.id and users.username = '" username "' and areas.code = '" area "'"))))) + (if (not (null? data-row)) + (begin + (let* ((access-type (car data-row)) + (exdate (cadr data-row))) + (if (not (null? exdate)) + (begin + (let ((valid (is-access-valid exdate))) + ;(print valid) + (if (and (equal? access-type role) + (equal? valid #t)) + (set! has-access #t)))) + (print "Access expired")))))))) + ;(print has-access) +has-access)) + +(define (is-access-valid exp-str) + (let* ((ret-val #f ) + (date-parts (string-split exp-str "/")) + (yr (string->number (car date-parts))) + (month (string->number(car (cdr date-parts)))) + (day (string->number(caddr date-parts))) + (exp-date (make-date 0 0 0 0 day month yr ))) + ;(print exp-date) + ;(print (current-date)) + (if (> (date-compare exp-date (current-date)) 0) + (set! ret-val #t)) + ;(print ret-val) + ret-val)) + + +;check if area exists +(define (area-exists area) + (let* ((area-defined #f)) + (sauthorize:db-do (lambda (db) + (let* ((data-row (query fetch (sql db (conc "SELECT id FROM areas where areas.code = '" area "'"))))) + (if (not (null? data-row)) + (set! area-defined #t))))) +area-defined)) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; Get Record from database +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;gets area id by code +(define (get-area area) + (let* ((area-defined '())) + (sauthorize:db-do (lambda (db) + (let* ((data-row (query fetch (sql db (conc "SELECT id FROM areas where areas.code = '" area "'"))))) + (set! area-defined data-row)))) +area-defined)) + +;get id of users table by user name +(define (get-user user) + (let* ((user-defined '())) + (sauthorize:db-do (lambda (db) + (let* ((data-row (query fetch (sql db (conc "SELECT id FROM users where users.username = '" user "'"))))) + (set! user-defined data-row)))) +user-defined)) + +;get permissions id by userid and area id +(define (get-perm userid areaid) + (let* ((user-defined '())) + (sauthorize:db-do (lambda (db) + (let* ((data-row (query fetch (sql db (conc "SELECT id FROM permissions where user_id = " userid " and area_id = " areaid))))) + (set! user-defined data-row)))) + +user-defined)) + +(define (get-restrictions base-path usr) +(let* ((user-defined '())) + (sauthorize:db-do (lambda (db) + (let* ((data-row (query fetch (sql db (conc "SELECT restriction FROM areas, users, permissions where areas.id = permissions.area_id and users.id = permissions.user_id and users.username = '" usr "' and areas.basepath = '" base-path "'"))))) + ;(print data-row) + (set! user-defined data-row)))) + ; (print user-defined) + (if (null? user-defined) + "" + (car user-defined)))) + + +(define (get-obj-by-path path) + (let* ((obj '())) + (sauthorize:db-do (lambda (db) + (let* ((data-row (query fetch (sql db (conc "SELECT code,exe_name, id, basepath FROM areas where areas.basepath = '" path "'"))))) + (set! obj data-row)))) +obj)) + +(define (get-obj-by-code code ) + (let* ((obj '())) + (sauthorize:db-do (lambda (db) + ;(print (conc "SELECT code, exe_name, id, basepath, required_grps FROM areas where areas.code = '" code "'")) + (let* ((data-row (query fetch (sql db (conc "SELECT code, exe_name, id, basepath, required_grps FROM areas where areas.code = '" code "'"))))) + ;(print data-row) + (set! obj data-row) + ;(print obj) + ))) + (if (not (null? obj)) + (begin + (let* ((req-grp (caddr (cddr obj)))) + (sauthorize:do-as-calling-user + (lambda () + (sauth-common:check-user-groups req-grp)))))) +obj)) + +(define (sauth-common:check-user-groups req-grp) +(let* ((current-groups (get-groups) ) + (req-grp-list (string-split req-grp ","))) + ;(print req-grp-list) + (for-each (lambda (grp) + (let ((grp-info (group-information grp))) + ;(print grp-info " " grp) + (if (not (equal? grp-info #f)) + (begin + (if (not (member (caddr grp-info) current-groups)) + (begin + (sauth:print-error (conc "Please wash " grp " group in your xterm!! " )) + (exit 1))))))) + req-grp-list))) + +(define (get-obj-by-code-no-grp-validation code ) + (let* ((obj '())) + (sauthorize:db-do (lambda (db) + (let* ((data-row (query fetch (sql db (conc "SELECT code, exe_name, id, basepath FROM areas where areas.code = '" code "'"))))) + (set! obj data-row)))) +;(print obj) +obj)) + + + + +;; function to validate the users input for target path and resolve the path +;; TODO: Check for restriction in subpath +(define (sauth-common:resolve-path new current allowed-sheets) + (let* ((target-path (append current (string-split new "/"))) + (target-path-string (string-join target-path "/")) + (normal-path (normalize-pathname target-path-string)) + (normal-list (string-split normal-path "/")) + (ret '())) + (if (string-contains normal-path "..") + (begin + (print "ERROR: Path " new " resolved outside target area ") + #f) + (if(equal? normal-path ".") + ret + (if (not (member (car normal-list) allowed-sheets)) + (begin + (print "ERROR: Permision denied to " new ) + #f) + normal-list))))) + +(define (sauth-common:get-target-path base-path-list ext-path top-areas base-path) + (let* ((resolved-path (sauth-common:resolve-path ext-path base-path-list top-areas )) + (usr (current-user-name) ) ) + (if (not (equal? resolved-path #f)) + (if (null? resolved-path) + #f + (let* ((sheet (car resolved-path)) + (restricted-areas (get-restrictions base-path usr)) + (restrictions (conc ".*" (string-join (string-split restricted-areas ",") ".*|.*") ".*")) + (target-path (if (null? (cdr resolved-path)) + base-path + (conc base-path "/" (string-join (cdr resolved-path) "/"))))) + + + (if (and (not (equal? restricted-areas "" )) + (string-match (regexp restrictions) target-path)) + (begin + (sauth:print-error "Access denied to " (string-join resolved-path "/")) + ;(exit 1) + #f) + target-path) + +)) + #f))) + +(define (sauth-common:shell-ls-cmd base-path-list ext-path top-areas base-path tail-cmd-list) + (if (and (null? base-path-list) (equal? ext-path "") ) + (print (string-intersperse top-areas " ")) + (let* ((resolved-path (sauth-common:resolve-path ext-path base-path-list top-areas ))) + ;(print resolved-path) + (if (not (equal? resolved-path #f)) + (if (null? resolved-path) + (print (string-intersperse top-areas " ")) + (let* ((target-path (sauth-common:get-target-path base-path-list ext-path top-areas base-path))) + (print target-path) + (if (not (equal? target-path #f)) + (begin + (cond + ((null? tail-cmd-list) + (run (pipe + (ls "-lrt" ,target-path)))) + ((not (equal? (car tail-cmd-list) "|")) + (print "ls cmd cannot accept " (string-join tail-cmd-list) " as an argument!!")) + (else + (run (pipe + (ls "-lrt" ,target-path) + (begin (system (string-join (cdr tail-cmd-list)))))))))))))))) + +(define (sauth:print-error msg) + (with-output-to-port (current-error-port) + (lambda () + (print (conc "ERROR: " msg))))) + ADDED sauthorize.scm Index: sauthorize.scm ================================================================== --- /dev/null +++ sauthorize.scm @@ -0,0 +1,643 @@ + +;; Copyright 2006-2013, Matthew Welland. +;; +;; This program is made available under the GNU GPL version 2.0 or +;; greater. See the accompanying file COPYING for details. +;; +;; This program is distributed WITHOUT ANY WARRANTY; without even the +;; implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +;; PURPOSE. + +(use defstruct) +(use scsh-process) + +(use srfi-18) +(use srfi-19) +(use refdb) + +(use sql-de-lite srfi-1 posix regex regex-case srfi-69) +(declare (uses common)) + +(declare (uses configf)) +(declare (uses margs)) +(declare (uses megatest-version)) + +(include "megatest-fossil-hash.scm") +;;; please create this file before using sautherise. For sample file is avaliable sample-sauth-paths.scm. +(include "sauth-paths.scm") +(include "sauth-common.scm") + +;; +;; GLOBALS +;; +(define *verbosity* 1) +(define *logging* #f) +(define *exe-name* (pathname-file (car (argv)))) +(define *sretrieve:current-tab-number* 0) +(define *args-hash* (make-hash-table)) +(define sauthorize:help (conc "Usage: " *exe-name* " [action [params ...]] + + list : list areas $USER's can access + log : get listing of recent activity. + sauth list-area-user : list the users that can access the area. + sauth open --group : Open up an area. User needs to be the owner of the area to open it. + --code + --retrieve|--publish [--additional-grps ] + sauth update --retrieve|--publish : update the binaries with the lates changes + sauth grant --area : Grant permission to read or write to a area that is alrady opend up. + --expiration yyyy/mm/dd --retrieve|--publish + [--restrict ] + sauth read-shell : Open sretrieve shell for reading. + sauth write-shell : Open spublish shell for writing. + +Part of the Megatest tool suite. +Learn more at http://www.kiatoa.com/fossils/megatest + +Version: " megatest-fossil-hash)) ;; " + +;;====================================================================== +;; RECORDS +;;====================================================================== + +;;====================================================================== +;; DB +;;====================================================================== + +;; replace (strftime('%s','now')), with datetime('now')) +(define (sauthorize:initialize-db db) + (for-each + (lambda (qry) + (exec (sql db qry))) + (list + "CREATE TABLE IF NOT EXISTS actions + (id INTEGER PRIMARY KEY, + cmd TEXT NOT NULL, + user_id INTEGER NOT NULL, + datetime TIMESTAMP DEFAULT (datetime('now','localtime')), + area_id INTEGER NOT NULL, + comment TEXT DEFAULT '' NOT NULL, + action_type TEXT NOT NULL);" + "CREATE TABLE IF NOT EXISTS users + (id INTEGER PRIMARY KEY, + username TEXT NOT NULL, + is_admin TEXT NOT NULL, + datetime TIMESTAMP DEFAULT (datetime('now','localtime')) + );" + "CREATE TABLE IF NOT EXISTS areas + (id INTEGER PRIMARY KEY, + basepath TEXT NOT NULL, + code TEXT NOT NULL, + exe_name TEXT NOT NULL, + required_grps TEXT DEFAULT '' NOT NULL, + datetime TIMESTAMP DEFAULT (datetime('now','localtime')) + );" + "CREATE TABLE IF NOT EXISTS permissions + (id INTEGER PRIMARY KEY, + access_type TEXT NOT NULL, + user_id INTEGER NOT NULL, + datetime TIMESTAMP DEFAULT (datetime('now','localtime')), + area_id INTEGER NOT NULL, + restriction TEXT DEFAULT '' NOT NULL, + expiration TIMESTAMP DEFAULT NULL);" + ))) + + + + +(define (get-access-type args) + (let loop ((hed (car args)) + (tal (cdr args))) + (cond + ((equal? hed "--retrieve") + "retrieve") + ((equal? hed "--publish") + "publish") + ((equal? hed "--area-admin") + "area-admin") + ((equal? hed "--writer-admin") + "writer-admin") + ((equal? hed "--read-admin") + "read-admin") + + ((null? tal) + #f) + (else + (loop (car tal)(cdr tal)))))) + + + +;; check if user can gran access to an area +(define (can-grant-perm username access-type area) + (let* ((isadmin (is-admin username)) + (is-area-admin (is-user "area-admin" username area )) + (is-read-admin (is-user "read-admin" username area) ) + (is-writer-admin (is-user "writer-admin" username area) ) ) + (cond + ((equal? isadmin #t) + #t) + ((equal? is-area-admin #t ) + #t) + ((and (equal? is-writer-admin #t ) (equal? access-type "retrieve")) + #t) + ((and (equal? is-read-admin #t ) (equal? access-type "retrieve")) + #t) + + (else + #f)))) + +(define (sauthorize:list-areausers area ) + (sauthorize:db-do (lambda (db) + (print "Users having access to " area ":") + (query (for-each-row + (lambda (row) + (let* ((exp-date (cadr row))) + (if (is-access-valid exp-date) + (apply print (intersperse row " | ")))))) + (sql db (conc "SELECT users.username, permissions.expiration, permissions.access_type FROM users, areas, permissions where permissions.user_id = users.id and permissions.area_id = areas.id and areas.code = '" area "'")))))) + + + + +; check if executable exists +(define (exe-exist exe access-type) + (let* ((filepath (conc *exe-path* "/" access-type "/" exe))) + ; (print filepath) + (if (file-exists? filepath) + #t + #f))) + +(define (copy-exe access-type exe-name group) + (run-cmd "/bin/chmod" (list "g+w" (conc *exe-path* "/" access-type))) + (let* ((spath (conc *exe-src* "/s" access-type)) + (dpath (conc *exe-path* "/" access-type "/" exe-name))) + (sauthorize:do-as-calling-user + (lambda () + (run-cmd "/bin/cp" (list spath dpath )) + (if (equal? access-type "publish") + (run-cmd "/bin/chmod" (list "u+s,o+rx" dpath)) + (begin + (if (equal? group "none") + (run-cmd "/bin/chmod" (list "u+s,o+rx" dpath)) + (begin + (run-cmd "/bin/chgrp" (list group dpath)) + (run-cmd "/bin/chmod" (list "g+s,o+rx" dpath)))))))) + (run-cmd "chmod" (list "g-w" (conc *exe-path* "/" access-type))))) + +(define (get-exe-name path group) + (let ((name "")) + (sauthorize:do-as-calling-user + (lambda () + (if (equal? (current-effective-user-id) (file-owner path)) + (set! name (conc (current-user-name) "_" group)) + (begin + (print "You cannot open areas that you dont own!!") + (exit 1))))) +name)) + +(define (sauthorize:valid-unix-user username) + (let* ((ret-val #f)) + (let-values (((inp oup pid) + (process "/usr/bin/id" (list username)))) + (let loop ((inl (read-line inp))) + (if (string? inl) + (if (string-contains inl "No such user") + (set! ret-val #f) + (set! ret-val #t))) + (if (eof-object? inl) + (begin + (close-input-port inp) + (close-output-port oup)) + (loop (read-line inp))))) + ret-val)) + + +;check if a paths/codes are vaid and if area is alrady open +(define (open-area group path code access-type other-grps) + (let* ((exe-name (get-exe-name path group)) + (path-obj (get-obj-by-path path)) + (code-obj (get-obj-by-code-no-grp-validation code))) + ;(print path-obj) + (cond + ((not (null? path-obj)) + (if (equal? code (car path-obj)) + (begin + (if (equal? exe-name (cadr path-obj)) + (begin + (if (not (exe-exist exe-name access-type)) + (copy-exe access-type exe-name group) + (begin + (print "Area already open!!") + (exit 1)))) + (begin + (if (not (exe-exist exe-name access-type)) + (copy-exe access-type exe-name group)) + ;; update exe-name in db + (sauthorize:db-do (lambda (db) + (sauthorize:db-qry db (conc "update areas set exe_name = '" exe-name "' where id = " (caddr path-obj))))) + ))) + (begin + (print "Path " path " is registered with --code " (car path-obj) ". To open this area please execute following cmd: \n sauthorize open " path " --group " group " --code " (car path-obj) " --" access-type ) + (exit 1)))) + + ((not (null? code-obj)) + (print "Code " code " is used for diffrent path. Please try diffrent value of --code" ) + (exit 1)) + (else + ; (print (exe-exist exe-name access-type)) + (if (not (exe-exist exe-name access-type)) + (copy-exe access-type exe-name group)) + (sauthorize:db-do (lambda (db) + (print conc "insert into areas (code, basepath, exe_name, required_grps) values ('" code "', '" path "', '" exe-name "', '" other-grps "') ") + (sauthorize:db-qry db (conc "insert into areas (code, basepath, exe_name, required_grps) values ('" code "', '" path "', '" exe-name "', '" other-grps "') ")))))))) + +(define (user-has-open-perm user path access) + (let* ((has-access #f) + (eid (current-user-id))) + (cond + ((is-admin user) + (set! has-access #t )) + ((and (is-read-admin user) (equal? access "retrieve")) + (set! has-access #t )) + (else + (print "User " user " does not have permission to open areas"))) + has-access)) + + +;;check if user has group access +(define (is-group-washed req_grpid current-grp-list) + (let loop ((hed (car current-grp-list)) + (tal (cdr current-grp-list))) + (cond + ((equal? hed req_grpid) + #t) + ((null? tal) + #f) + (else + (loop (car tal)(cdr tal)))))) + +;create executables with appropriate suids +(define (sauthorize:open user path group code access-type other-groups) + (let* ((gpid (group-information group)) + (req_grpid (if (equal? group "none") + group + (if (equal? gpid #f) + #f + (caddr gpid)))) + (current-grp-list (get-groups)) + (valid-grp (if (equal? group "none") + group + (is-group-washed req_grpid current-grp-list)))) + (if (and (not (equal? group "none")) (equal? valid-grp #f )) + (begin + (print "Group " group " is not washed in the current xterm!!") + (exit 1)))) + (if (not (file-write-access? path)) + (begin + (print "You can open areas owned by yourself. You do not have permissions to open path." path) + (exit 1))) + (if (user-has-open-perm user path access-type) + (begin + ;(print "here") + (open-area group path code access-type other-groups) + (sauthorize:grant user user code "2017/12/25" "read-admin" "") + (sauthorize:db-do (lambda (db) + (sauthorize:db-qry db (conc "INSERT INTO actions (cmd,user_id,area_id,action_type ) VALUES ('sauthorize open " path " --code " code " --group " group " --" access-type "'," (car (get-user user)) "," (car (get-area code)) ", 'open' )")))) + (print "Area has " path " been opened for " access-type )))) + +(define (sauthorize:update username exe area access-type) + (let* ((parts (string-split exe "_")) + (owner (car parts)) + (group (cadr parts)) + (gpid (group-information group)) + (req_grpid (if (equal? group "none") + group + (if (equal? gpid #f) + #f + (caddr gpid)))) + + (current-grp-list (get-groups)) + (valid-grp (if (equal? group "none") + group + (is-group-washed req_grpid current-grp-list)))) + (if (not (equal? username owner)) + (begin + (print "You cannot update " area ". Only " owner " can update this area!!") + (exit 1))) + (copy-exe access-type exe group) + (print "recording action..") + (sauthorize:db-do (lambda (db) + + (sauthorize:db-qry db (conc "INSERT INTO actions (cmd,user_id,area_id,action_type ) VALUES ('sauthorize update " area " --" access-type "'," (car (get-user username)) "," (car (get-area area)) ", 'update' )")))) + (print "Area has " area " been update!!" ))) + +(define (sauthorize:grant auser guser area exp-date access-type restrict) + ; check if user exist in db + (let* ((area-obj (get-area area)) + (auser-obj (get-user auser)) + (user-obj (get-user guser))) + + (if (null? user-obj) + (begin + ;; is guser a valid unix user + (if (not (sauthorize:valid-unix-user guser)) + (begin + (print "User " guser " is Invalid unix user!!") + (exit 1))) + (sauthorize:db-do (lambda (db) + (sauthorize:db-qry db (conc "insert into users (username, is_admin) values ('" guser "', 'no') ")))) + (set! user-obj (get-user guser)))) + (let* ((perm-obj (get-perm (car user-obj) (car area-obj)))) + (if(null? perm-obj) + (begin + ;; insert permissions + (sauthorize:db-do (lambda (db) + (sauthorize:db-qry db (conc "insert into permissions (access_type, user_id, area_id, restriction, expiration ) values ('" access-type "', " (car user-obj) ", " (car area-obj) ", '" restrict "', '" exp-date "')"))))) + (begin + ;update permissions + (sauthorize:db-do (lambda (db) + (sauthorize:db-qry db (conc "update permissions set access_type = '" access-type "' , restriction = '" restrict "', expiration = '" exp-date "' where user_id = " (car user-obj) " and area_id = " (car area-obj))))))) + (sauthorize:db-do (lambda (db) + (sauthorize:db-qry db (conc "INSERT INTO actions (cmd,user_id,area_id,action_type ) VALUES ('sauthorize grant " guser " --area " area " --expiration " exp-date " --" access-type " --restrict " restrict "'," (car auser-obj) "," (car area-obj) ", 'grant' )")))) + (print "Permission has been sucessfully granted to user " guser)))) + +(define (sauthorize:process-action username action . args) + (case (string->symbol action) + ((grant) + (if (< (length args) 6) + (begin + (print "ERROR: Missing arguments; " (string-intersperse args ", ")) + (exit 1))) + (let* ((remargs (args:get-args args '("--area" "--expiration" "--restrict") '() args:arg-hash 0)) + (guser (car args)) + (restrict (or (args:get-arg "--restrict") "")) + (area (or (args:get-arg "--area") "")) + (exp-date (or (args:get-arg "--expiration") "")) + (access-type (get-access-type remargs))) + ; (print "version " guser " restrict " restrict ) + ; (print "area " area " exp-date " exp-date " access-type " access-type) + (cond + ((equal? guser "") + (print "Username not found!! Try \"sauthorize help\" for useage ") + (exit 1)) + ((equal? area "") + (print "Area not found!! Try \"sauthorize help\" for useage ") + (exit 1)) + ((equal? access-type #f) + (print "Access type not found!! Try \"sauthorize help\" for useage ") + (exit 1)) + ((equal? exp-date "") + (print "Date of expiration not found!! Try \"sauthorize help\" for useage ") + (exit 1))) + (if (not (area-exists area)) + (begin + (print "Area does not exisit!!") + (exit 1))) + (if (can-grant-perm username access-type area) + (begin + (print "calling sauthorize:grant ") + (sauthorize:grant username guser area exp-date access-type restrict)) + (begin + (print "User " username " does not have permission to grant permissions to area " area "!!") + (exit 1))))) + ((list-area-user) + (if (not (equal? (length args) 1)) + (begin + (print "Missing argument area code to list-area-user ") + (exit 1))) + (let* ((area (car args))) + (if (not (area-exists area)) + (begin + (print "Area does not exisit!!") + (exit 1))) + + (sauthorize:list-areausers area ) + )) + ((read-shell) + (if (not (equal? (length args) 1)) + (begin + (print "Missing argument area code to read-shell ") + (exit 1))) + (let* ((area (car args)) + (code-obj (get-obj-by-code area))) + (if (or (null? code-obj) + (not (exe-exist (cadr code-obj) "retrieve"))) + (begin + (print "Area " area " is not open for reading!!") + (exit 1))) + (sauthorize:do-as-calling-user + (lambda () + (run-cmd (conc *exe-path* "/retrieve/" (cadr code-obj) ) (list "shell" area )))))) + ((write-shell) + (if (not (equal? (length args) 1)) + (begin + (print "Missing argument area code to read-shell ") + (exit 1))) + (let* ((area (car args)) + (code-obj (get-obj-by-code area))) + (if (or (null? code-obj) + (not (exe-exist (cadr code-obj) "publish"))) + (begin + (print "Area " area " is not open for Writing!!") + (exit 1))) + (sauthorize:do-as-calling-user + (lambda () + (run-cmd (conc *exe-path* "/publish/" (cadr code-obj) ) (list "shell" area)))))) + ((publish) + (if (< (length args) 2) + (begin + (print "Missing argument to publish. \n publish [opts] ") + (exit 1))) + + (let* ((action (car args)) + (area (cadr args)) + (cmd-args (cddr args)) + (code-obj (get-obj-by-code area))) + ;(print "area " area) + ;(print "code: " code-obj) + ;(print (exe-exist (cadr code-obj) "publish")) + (if (or (null? code-obj) + (not (exe-exist (cadr code-obj) "publish"))) + (begin + (print "Area " area " is not open for writing!!") + (exit 1))) + ;(print "hear") + (sauthorize:do-as-calling-user + (lambda () + ; (print *exe-path* "/publish/" (cadr code-obj) action area cmd-args ) + (run-cmd (conc *exe-path* "/publish/" (cadr code-obj) ) (append (list action area ) cmd-args)))))) + + ((retrieve) + (if (< (length args) 2) + (begin + (print "Missing argument to publish. \n publish [opts] ") + (exit 1))) + (let* ((action (car args)) + (area (cadr args)) + (cmd-args (cddr args)) + (code-obj (get-obj-by-code area))) + (if (or (null? code-obj) + (not (exe-exist (cadr code-obj) "retrieve"))) + (begin + (print "Area " area " is not open for reading!!") + (exit 1))) + (print (conc *exe-path* "/retrieve/" (cadr code-obj) " " action " " area " " (string-join cmd-args))) + (sauthorize:do-as-calling-user + (lambda () + (run-cmd (conc *exe-path* "/retrieve/" (cadr code-obj) ) (append (list action area ) cmd-args)))))) + + + + ((open) + (if (< (length args) 6) + (begin + (print "sauthorize open cmd takes 6 arguments!! \n Useage: sauthorize open --group --code --retrieve|--publish") + (exit 1))) + (let* ((remargs (args:get-args args '("--group" "--code" "--additional-grps") '() args:arg-hash 0)) + (path (car args)) + (group (or (args:get-arg "--group") "")) + (area (or (args:get-arg "--code") "")) + (other-grps (or (args:get-arg "--additional-grps") "")) + (access-type (get-access-type remargs))) + + (cond + ((equal? path "") + (print "path not found!! Try \"sauthorize help\" for useage ") + (exit 1)) + ((equal? area "") + (print "--code not found!! Try \"sauthorize help\" for useage ") + (exit 1)) + ((equal? access-type #f) + (print "Access type not found!! Try \"sauthorize help\" for useage ") + (exit 1)) + ((and (not (equal? access-type "publish")) + (not (equal? access-type "retrieve"))) + (print "Access type can be eiter --retrieve or --publish !! Try \"sauthorize help\" for useage ") + (exit 1))) + ; (print other-grps) + (sauthorize:open username path group area access-type other-grps))) + ((update) + (if (< (length args) 2) + (begin + (print "sauthorize update cmd takes 2 arguments!! \n Useage: sauthorize update --retrieve|--publish") + (exit 1))) + (let* ((area (car args)) + (code-obj (get-obj-by-code area)) + (access-type (get-access-type (cdr args)))) + (if (and (not (equal? access-type "publish")) (not (equal? access-type "retrieve"))) + (begin + (print "Access type can be --retrieve|--publish ") + (exit 1))) + (if (or (null? code-obj) + (not (exe-exist (cadr code-obj) access-type))) + (begin + (print "Area " area " is not open for reading!!") + (exit 1))) + (sauthorize:update username (cadr code-obj) area access-type ))) + ((area-admin) + (let* ((usr (car args)) + (usr-obj (get-user usr)) + (user-id (car (get-user username)))) + + (if (is-admin username) + (begin + ; (print usr-obj) + (if (null? usr-obj) + (begin + (sauthorize:db-do (lambda (db) + ;(print (conc "INSERT INTO users (username,is_admin) VALUES ( '" usr "', 'read-admin' )")) + (sauthorize:db-qry db (conc "INSERT INTO users (username,is_admin) VALUES ( '" usr "', 'read-admin' )"))))) + (begin + ; (print (conc "update users set is_admin = 'no' where id = " (car usr-obj) )) + (sauthorize:db-do (lambda (db) + (sauthorize:db-qry db (conc "update users set is_admin = 'read-admin' where id = " (car usr-obj))))))) + (print "User " usr " is updated with area-admin access!")) + (print "Admin only function")) + (sauthorize:db-do (lambda (db) + (sauthorize:db-qry db (conc "INSERT INTO actions (cmd,user_id,area_id,action_type ) VALUES ('area-admin " usr " ', " user-id ",0, 'area-admin ')" )))))) + ((mk-admin) + (let* ((usr (car args)) + (usr-obj (get-user usr)) + (user-id (car (get-user username)))) + (if (not (sauthorize:valid-unix-user usr)) + (begin + (print "User " usr " is Invalid unix user!!") + (exit 1))) + + (if (member username *super-users*) + (begin + (if (null? usr-obj) + (begin + (sauthorize:db-do (lambda (db) + (sauthorize:db-qry db (conc "INSERT INTO users (username,is_admin) VALUES ( '" usr "', 'yes' )"))))) + (begin + (sauthorize:db-do (lambda (db) + (sauthorize:db-qry db (conc "update users set is_admin = 'yes' where id = " (car usr-obj))))))) + (print "User " usr " is updated with admin access!")) + (print "Super-Admin only function")) + (sauthorize:db-do (lambda (db) + (sauthorize:db-qry db (conc "INSERT INTO actions (cmd,user_id,area_id,action_type ) VALUES ('mk-admin " usr " ', " user-id ",0, 'mk-admin ')" )))))) + + ((register-log) + (if (< (length args) 4) + (print "Invalid arguments")) + ;(print args) + (let* ((cmd-line (car args)) + (user-id (cadr args)) + (area-id (caddr args)) + (user-obj (get-user username)) + (cmd (cadddr args))) + + (if (and (not (null? user-obj)) (equal? user-id (number->string(car user-obj)))) + (begin + (sauthorize:db-do (lambda (db) + (sauthorize:db-qry db (conc "INSERT INTO actions (cmd,user_id,area_id,action_type ) VALUES ('" cmd-line"', " user-id "," area-id ", '" cmd "')" ))))) + (print "You ar not authorised to run this cmd") + +))) + + + (else (print 0 "Unrecognised command " action)))) + +(define (main) + (let* ((args (argv)) + (prog (car args)) + (rema (cdr args)) + (username (current-user-name))) + ;; preserve the exe data in the config file + (cond + ;; one-word commands + ((eq? (length rema) 1) + (case (string->symbol (car rema)) + ((help -h -help --h --help) + (print sauthorize:help)) + ((list) + + (sauthorize:db-do (lambda (db) + (print "My Area accesses: ") + (query (for-each-row + (lambda (row) + (let* ((exp-date (car row))) + (if (is-access-valid exp-date) + (apply print (intersperse (cdr row) " | ")))))) + (sql db (conc "SELECT permissions.expiration, areas.basepath, areas.code, permissions.access_type FROM users, areas, permissions where permissions.user_id = users.id and permissions.area_id = areas.id and users.username = '" username "'")))))) + + ((log) + (sauthorize:db-do (lambda (db) + (print "Logs : ") + (query (for-each-row + (lambda (row) + + (apply print (intersperse row " | ")))) + (sql db "SELECT actions.cmd, users.username, actions.action_type, actions.datetime, areas.code FROM actions, users, areas where actions.user_id = users.id and actions.area_id = areas.id "))))) + (else + (print "ERROR: Unrecognised command. Try \"sauthorize help\"")))) + ;; multi-word commands + ((null? rema)(print sauthorize:help)) + ((>= (length rema) 2) + (apply sauthorize:process-action username (car rema)(cdr rema))) + (else (debug:print 0 "ERROR: Unrecognised command. Try \"sauthorize help\""))))) + +(main) + + + Index: spublish.scm ================================================================== --- spublish.scm +++ spublish.scm @@ -7,61 +7,48 @@ ;; This program is distributed WITHOUT ANY WARRANTY; without even the ;; implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ;; PURPOSE. (use defstruct) - -;; (use ssax) -;; (use sxml-serializer) -;; (use sxml-modifications) -;; (use regex) -;; (use srfi-69) -;; (use regex-case) -;; (use posix) -;; (use json) -;; (use csv) +(use scsh-process) +(use refdb) (use srfi-18) +(use srfi-19) (use format) - -;; (require-library ini-file) -;; (import (prefix ini-file ini:)) - (use sql-de-lite srfi-1 posix regex regex-case srfi-69) -;; (import (prefix sqlite3 sqlite3:)) -;; + (declare (uses configf)) ;; (declare (uses tree)) (declare (uses margs)) -;; (declare (uses dcommon)) -;; (declare (uses launch)) -;; (declare (uses gutils)) -;; (declare (uses db)) -;; (declare (uses synchash)) -;; (declare (uses server)) + (declare (uses megatest-version)) ;; (declare (uses tbd)) (include "megatest-fossil-hash.scm") +;;; please create this file before using sautherise. For sample file is avaliable sample-sauth-paths.scm. +(include "sauth-paths.scm") +(include "sauth-common.scm") +(define (toplevel-command . args) #f) +(use readline) ;; ;; GLOBALS ;; (define *spublish:current-tab-number* 0) (define *args-hash* (make-hash-table)) -(define spublish:help (conc "Usage: spublish [action [params ...]] - - ls : list contents of target area - cp|publish : copy file to target area - mkdir : maks directory in target area - rm : remove file from target area - ln : creates a symlink - log : - +(define spublish:help (conc "Usage: spublish [action [params ...]] + + ls : list contents of target area + cp|publish : copy file to target area + mkdir : maks directory in target area + rm : remove file from target area + ln : creates a symlink + options: -m \"message\" : describe what was done - +Note: All the target locations relative to base path Part of the Megatest tool suite. Learn more at http://www.kiatoa.com/fossils/megatest Version: " megatest-fossil-hash)) ;; " @@ -71,237 +58,240 @@ ;;====================================================================== ;; DB ;;====================================================================== -(define (spublish:initialize-db db) - (for-each - (lambda (qry) - (exec (sql db qry))) - (list - "CREATE TABLE IF NOT EXISTS actions - (id INTEGER PRIMARY KEY, - action TEXT NOT NULL, - submitter TEXT NOT NULL, - datetime TIMESTAMP DEFAULT (strftime('%s','now')), - srcpath TEXT NOT NULL, - comment TEXT DEFAULT '' NOT NULL, - state TEXT DEFAULT 'new');" - ))) - -(define (spublish:register-action db action submitter source-path comment) - (exec (sql db "INSERT INTO actions (action,submitter,srcpath,comment) - VALUES(?,?,?,?)") - action - submitter - source-path - comment)) +(define *default-log-port* (current-error-port)) +(define *verbosity* 1) + +;(define (spublish:initialize-db db) +; (for-each +; (lambda (qry) +; (exec (sql db qry))) +; (list +; "CREATE TABLE IF NOT EXISTS actions +; (id INTEGER PRIMARY KEY, +; action TEXT NOT NULL, +; submitter TEXT NOT NULL, +; datetime TIMESTAMP DEFAULT (strftime('%s','now')), +; srcpath TEXT NOT NULL, +; comment TEXT DEFAULT '' NOT NULL, +; state TEXT DEFAULT 'new');" +; ))) + +;(define (spublish:register-action db action submitter source-path comment) +; (exec (sql db "INSERT INTO actions (action,submitter,srcpath,comment) +; VALUES(?,?,?,?)") +; action +; submitter +; source-path +; comment)) ;; (call-with-database ;; (lambda (db) ;; (set-busy-handler! db (busy-timeout 10000)) ; 10 second timeout ;; ...)) ;; Create the sqlite db -(define (spublish:db-do configdat proc) - (let ((path (configf:lookup configdat "database" "location"))) - (if (not path) - (begin - (print "[database]\nlocation /some/path\n\n Is missing from the config file!") - (exit 1))) - (if (and path - (directory? path) - (file-read-access? path)) - (let* ((dbpath (conc path "/spublish.db")) - (writeable (file-write-access? dbpath)) - (dbexists (file-exists? dbpath))) - (handle-exceptions - exn - (begin - (debug:print 2 *default-log-port* "ERROR: problem accessing db " dbpath - ((condition-property-accessor 'exn 'message) exn)) - (exit 1)) - (call-with-database - dbpath - (lambda (db) - ;; (print "calling proc " proc " on db " db) - (set-busy-handler! db (busy-timeout 10000)) ;; 10 sec timeout - (if (not dbexists)(spublish:initialize-db db)) - (proc db))))) - (print "ERROR: invalid path for storing database: " path)))) - -;; copy in file to dest, validation is done BEFORE calling this -;; -(define (spublish:cp configdat submitter source-path target-dir targ-file dest-dir comment) - (let ((dest-dir-path (conc target-dir "/" dest-dir)) - (targ-path (conc target-dir "/" dest-dir "/" targ-file))) - (if (file-exists? targ-path) - (begin - (print "ERROR: target file already exists, remove it before re-publishing") - (exit 1))) - (if (not(file-exists? dest-dir-path)) - (begin - (print "ERROR: target directory " dest-dir-path " does not exists." ) - (exit 1))) - - (spublish:db-do - configdat - (lambda (db) - (spublish:register-action db "cp" submitter source-path comment))) - (let* (;; (target-path (configf:lookup "settings" "target-path")) - (th1 (make-thread - (lambda () - (file-copy source-path targ-path #t)) - (print " ... file " targ-path " copied to" targ-path) - ;; (let ((pid (process-run "cp" (list source-path target-dir)))) - ;; (process-wait pid))) - "copy thread")) - (th2 (make-thread - (lambda () - (let loop () - (thread-sleep! 15) - (display ".") - (flush-output) - (loop))) - "action is happening thread"))) - (thread-start! th1) - (thread-start! th2) - (thread-join! th1)) - (cons #t "Successfully saved data"))) - -;; copy directory to dest, validation is done BEFORE calling this -;; - -(define (spublish:tar configdat submitter target-dir dest-dir comment) - (let ((dest-dir-path (conc target-dir "/" dest-dir))) - (if (not(file-exists? dest-dir-path)) - (begin - (print "ERROR: target directory " dest-dir-path " does not exists." ) - (exit 1))) - ;;(print dest-dir-path ) - (spublish:db-do - configdat - (lambda (db) - (spublish:register-action db "tar" submitter dest-dir-path comment))) - (change-directory dest-dir-path) - (process-wait (process-run "/bin/tar" (list "xf" "-"))) - (print "Data copied to " dest-dir-path) - - (cons #t "Successfully saved data"))) - - -(define (spublish:validate target-dir targ-mk) - (let* ((normal-path (normalize-pathname targ-mk)) - (targ-path (conc target-dir "/" normal-path))) - (if (string-contains normal-path "..") - (begin - (print "ERROR: Path " targ-mk " resolved outside target area " target-dir ) - (exit 1))) - - (if (not (string-contains targ-path target-dir)) - (begin - (print "ERROR: You cannot update data outside " target-dir ".") - (exit 1))) - (print "Path " targ-mk " is valid.") - )) +;(define (spublish:db-do configdat proc) +; (let ((path (configf:lookup configdat "database" "location"))) +; (if (not path) +; (begin +; (print "[database]\nlocation /some/path\n\n Is missing from the config file!") +; (exit 1))) +; (if (and path +; (directory? path) +; (file-read-access? path)) +; (let* ((dbpath (conc path "/spublish.db")) +; (writeable (file-write-access? dbpath)) +; (dbexists (file-exists? dbpath))) +; (handle-exceptions +; exn +; (begin +; (debug:print 2 *default-log-port* "ERROR: problem accessing db " dbpath +; ((condition-property-accessor 'exn 'message) exn)) +; (exit 1)) +; (call-with-database +; dbpath +; (lambda (db) +; ;; (print "calling proc " proc " on db " db) +; (set-busy-handler! db (busy-timeout 10000)) ;; 10 sec timeout +; (if (not dbexists)(spublish:initialize-db db)) +; (proc db))))) +; (print "ERROR: invalid path for storing database: " path)))) +; +;;; copy in file to dest, validation is done BEFORE calling this +;;; +;(define (spublish:cp configdat submitter source-path target-dir targ-file dest-dir comment) +; (let ((dest-dir-path (conc target-dir "/" dest-dir)) +; (targ-path (conc target-dir "/" dest-dir "/" targ-file))) +; (if (file-exists? targ-path) +; (begin +; (print "ERROR: target file already exists, remove it before re-publishing") +; (exit 1))) +; (if (not(file-exists? dest-dir-path)) +; (begin +; (print "ERROR: target directory " dest-dir-path " does not exists." ) +; (exit 1))) +; +; (spublish:db-do +; configdat +; (lambda (db) +; (spublish:register-action db "cp" submitter source-path comment))) +; (let* (;; (target-path (configf:lookup "settings" "target-path")) +; (th1 (make-thread +; (lambda () +; (file-copy source-path targ-path #t)) +; (print " ... file " targ-path " copied to " targ-path) +; ;; (let ((pid (process-run "cp" (list source-path target-dir)))) +; ;; (process-wait pid))) +; "copy thread")) +; (th2 (make-thread +; (lambda () +; (let loop () +; (thread-sleep! 15) +; (display ".") +; (flush-output) +; (loop))) +; "action is happening thread"))) +; (thread-start! th1) +; (thread-start! th2) +; (thread-join! th1)) +; (cons #t "Successfully saved data"))) +; +;;; copy directory to dest, validation is done BEFORE calling this +;;; +; +;(define (spublish:tar configdat submitter target-dir dest-dir comment) +; (let ((dest-dir-path (conc target-dir "/" dest-dir))) +; (if (not(file-exists? dest-dir-path)) +; (begin +; (print "ERROR: target directory " dest-dir-path " does not exists." ) +; (exit 1))) +; ;;(print dest-dir-path ) +; (spublish:db-do +; configdat +; (lambda (db) +; (spublish:register-action db "tar" submitter dest-dir-path comment))) +; (change-directory dest-dir-path) +; (process-wait (process-run "/bin/tar" (list "xf" "-"))) +; (print "Data copied to " dest-dir-path) +; +; (cons #t "Successfully saved data"))) + + +;(define (spublish:validate target-dir targ-mk) +; (let* ((normal-path (normalize-pathname targ-mk)) +; (targ-path (conc target-dir "/" normal-path))) +; (if (string-contains normal-path "..") +; (begin +; (print "ERROR: Path " targ-mk " resolved outside target area " target-dir ) +; (exit 1))) +; +; (if (not (string-contains targ-path target-dir)) +; (begin +; (print "ERROR: You cannot update data outside " target-dir ".") +; (exit 1))) +; (print "Path " targ-mk " is valid.") +; )) ;; make directory in dest ;; -(define (spublish:mkdir configdat submitter target-dir targ-mk comment) - (let ((targ-path (conc target-dir "/" targ-mk))) - - (if (file-exists? targ-path) - (begin - (print "ERROR: target Directory " targ-path " already exist!!") - (exit 1))) - (spublish:db-do - configdat - (lambda (db) - (spublish:register-action db "mkdir" submitter targ-mk comment))) - (let* ((th1 (make-thread - (lambda () - (create-directory targ-path #t) - (print " ... dir " targ-path " created")) - "mkdir thread")) - (th2 (make-thread - (lambda () - (let loop () - (thread-sleep! 15) - (display ".") - (flush-output) - (loop))) - "action is happening thread"))) - (thread-start! th1) - (thread-start! th2) - (thread-join! th1)) - (cons #t "Successfully saved data"))) +;(define (spublish:mkdir configdat submitter target-dir targ-mk comment) +; (let ((targ-path (conc target-dir "/" targ-mk))) +; +; (if (file-exists? targ-path) +; (begin +; (print "ERROR: target Directory " targ-path " already exist!!") +; (exit 1))) +; (spublish:db-do +; configdat +; (lambda (db) +; (spublish:register-action db "mkdir" submitter targ-mk comment))) +; (let* ((th1 (make-thread +; (lambda () +; (create-directory targ-path #t) +; (print " ... dir " targ-path " created")) +; "mkdir thread")) +; (th2 (make-thread +; (lambda () +; (let loop () +; (thread-sleep! 15) +; (display ".") +; (flush-output) +; (loop))) +; "action is happening thread"))) +; (thread-start! th1) +; (thread-start! th2) +; (thread-join! th1)) +; (cons #t "Successfully saved data"))) ;; create a symlink in dest ;; -(define (spublish:ln configdat submitter target-dir targ-link link-name comment) - (let ((targ-path (conc target-dir "/" link-name))) - (if (file-exists? targ-path) - (begin - (print "ERROR: target file " targ-path " already exist!!") - (exit 1))) - (if (not (file-exists? targ-link )) - (begin - (print "ERROR: target file " targ-link " does not exist!!") - (exit 1))) - - (spublish:db-do - configdat - (lambda (db) - (spublish:register-action db "ln" submitter link-name comment))) - (let* ((th1 (make-thread - (lambda () - (create-symbolic-link targ-link targ-path ) - (print " ... link " targ-path " created")) - "symlink thread")) - (th2 (make-thread - (lambda () - (let loop () - (thread-sleep! 15) - (display ".") - (flush-output) - (loop))) - "action is happening thread"))) - (thread-start! th1) - (thread-start! th2) - (thread-join! th1)) - (cons #t "Successfully saved data"))) +;(define (spublish:ln configdat submitter target-dir targ-link link-name comment) +; (let ((targ-path (conc target-dir "/" link-name))) +; (if (file-exists? targ-path) +; (begin +; (print "ERROR: target file " targ-path " already exist!!") +; (exit 1))) +; (if (not (file-exists? targ-link )) +; (begin +; (print "ERROR: target file " targ-link " does not exist!!") +; (exit 1))) +; +; (spublish:db-do +; configdat +; (lambda (db) +; (spublish:register-action db "ln" submitter link-name comment))) +; (let* ((th1 (make-thread +; (lambda () +; (create-symbolic-link targ-link targ-path ) +; (print " ... link " targ-path " created")) +; "symlink thread")) +; (th2 (make-thread +; (lambda () +; (let loop () +; (thread-sleep! 15) +; (display ".") +; (flush-output) +; (loop))) +; "action is happening thread"))) +; (thread-start! th1) +; (thread-start! th2) +; (thread-join! th1)) +; (cons #t "Successfully saved data"))) ;; remove copy of file in dest ;; -(define (spublish:rm configdat submitter target-dir targ-file comment) - (let ((targ-path (conc target-dir "/" targ-file))) - (if (not (file-exists? targ-path)) - (begin - (print "ERROR: target file " targ-path " not found, nothing to remove.") - (exit 1))) - (spublish:db-do - configdat - (lambda (db) - (spublish:register-action db "rm" submitter targ-file comment))) - (let* ((th1 (make-thread - (lambda () - (delete-file targ-path) - (print " ... file " targ-path " removed")) - "rm thread")) - (th2 (make-thread - (lambda () - (let loop () - (thread-sleep! 15) - (display ".") - (flush-output) - (loop))) - "action is happening thread"))) - (thread-start! th1) - (thread-start! th2) - (thread-join! th1)) - (cons #t "Successfully saved data"))) +;(define (spublish:rm configdat submitter target-dir targ-file comment) +; (let ((targ-path (conc target-dir "/" targ-file))) +; (if (not (file-exists? targ-path)) +; (begin +; (print "ERROR: target file " targ-path " not found, nothing to remove.") +; (exit 1))) +; (spublish:db-do +; configdat +; (lambda (db) +; (spublish:register-action db "rm" submitter targ-file comment))) +; (let* ((th1 (make-thread +; (lambda () +; (delete-file targ-path) +; (print " ... file " targ-path " removed")) +; "rm thread")) +; (th2 (make-thread +; (lambda () +; (let loop () +; (thread-sleep! 15) +; (display ".") +; (flush-output) +; (loop))) +; "action is happening thread"))) +; (thread-start! th1) +; (thread-start! th2) +; (thread-join! th1)) +; (cons #t "Successfully saved data"))) (define (spublish:backup-move path) (let* ((trashdir (conc (pathname-directory path) "/.trash")) (trashfile (conc trashdir "/" (current-seconds) "-" (pathname-file path)))) (create-directory trashdir #t) @@ -323,182 +313,476 @@ ;;====================================================================== ;; MISC ;;====================================================================== -(define (spublish:do-as-calling-user proc) - (let ((eid (current-effective-user-id)) - (cid (current-user-id))) - (if (not (eq? eid cid)) ;; running suid - (set! (current-effective-user-id) cid)) - ;; (print "running as " (current-effective-user-id)) - (proc) - (if (not (eq? eid cid)) - (set! (current-effective-user-id) eid)))) - -(define (spublish:find name paths) - (if (null? paths) - #f - (let loop ((hed (car paths)) - (tal (cdr paths))) - (if (file-exists? (conc hed "/" name)) - hed - (if (null? tal) - #f - (loop (car tal)(cdr tal))))))) +;(define (spublish:do-as-calling-user proc) +; (let ((eid (current-effective-user-id)) +; (cid (current-user-id))) +; (if (not (eq? eid cid)) ;; running suid +; (set! (current-effective-user-id) cid)) +; ;; (print "running as " (current-effective-user-id)) +; (proc) +; (if (not (eq? eid cid)) +; (set! (current-effective-user-id) eid)))) + +;(define (spublish:find name paths) +; (if (null? paths) +; #f +; (let loop ((hed (car paths)) +; (tal (cdr paths))) +; (if (file-exists? (conc hed "/" name)) +; hed +; (if (null? tal) +; #f +; (loop (car tal)(cdr tal))))))) + +;;======================================================================== +;;Shell +;;======================================================================== +(define (spublish:get-accessable-projects area) + (let* ((projects `())) + (if (spublish:has-permission area) + (set! projects (cons area projects)) + (begin + (print "User cannot access area " area "!!") + (exit 1))) + projects)) + +;; function to find sheets to which use has access +(define (spublish:has-permission area) + ;(print "in spublish:has-permission") + (let* ((username (current-user-name)) + (ret-val #f)) + (cond + ((equal? (is-admin username) #t) + (set! ret-val #t)) + ((equal? (is-user "publish" username area) #t) + (set! ret-val #t)) + ((equal? (is-user "writer-admin" username area) #t) + (set! ret-val #t)) + + ((equal? (is-user "area-admin" username area) #t) + (set! ret-val #t)) + (else + (set! ret-val #f))) + ret-val)) + +(define (is_directory target-path) + (let* ((retval #f)) + (sauthorize:do-as-calling-user + (lambda () + ;(print (current-effective-user-id) ) + (if (directory? target-path) + (set! retval #t)))) + ;(print (current-effective-user-id)) + retval)) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; shell functions +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +(define (spublish:shell-cp src-path target-path) + (cond + ((not (file-exists? target-path)) + (sauth:print-error (conc " target Directory " target-path " does not exist!!"))) + ((not (file-exists? src-path)) + (sauth:print-error (conc "Source path " src-path " does not exist!!" ))) + (else + (if (is_directory src-path) + (begin + (let* ((parent-dir src-path) + (start-dir target-path)) + (run (pipe + (begin (system (conc "cd " parent-dir " ;tar chf - ." ))) + (begin (change-directory start-dir) + ;(print "123") + (run-cmd "tar" (list "xf" "-"))))) + (print "Copied data to " start-dir))) + (begin + (let*((parent-dir (pathname-directory src-path)) + (start-dir target-path) + (filename (if (pathname-extension src-path) + (conc(pathname-file src-path) "." (pathname-extension src-path)) + (pathname-file src-path)))) + ;(print "parent-dir " parent-dir " start-dir " start-dir) + (run (pipe + (begin (system (conc "cd " parent-dir ";tar chf - " filename ))) + (begin (change-directory start-dir) + (run-cmd "tar" (list "xf" "-"))))) + (print "Copied data to " start-dir))))))) + + +(define (spublish:shell-mkdir targ-path) + (if (file-exists? targ-path) + (begin + (print "Info: Target Directory " targ-path " already exist!!")) + (let* ((th1 (make-thread + (lambda () + (create-directory targ-path #t) + (print " ... dir " targ-path " created")) + "mkdir thread")) + (th2 (make-thread + (lambda () + (let loop () + (thread-sleep! 15) + (display ".") + (flush-output) + (loop))) + "action is happening thread"))) + (thread-start! th1) + (thread-start! th2) + (thread-join! th1) + (cons #t "Successfully saved data")))) + + +(define (spublish:shell-rm targ-path iport) + (if (not (file-exists? targ-path)) + (begin + (sauth:print-error (conc "target path " targ-path " does not exist!!"))) + (begin + (print "Are you sure you want to delete " targ-path "?[y/n]") + (let* ((inl (read-line iport))) + (if (equal? inl "y") + (let* ((th1 (make-thread + (lambda () + (if (symbolic-link? targ-path) + (delete-file targ-path ) + (if (directory? targ-path) + (delete-directory targ-path #t) + (delete-file targ-path ))) + (print " ... path " targ-path " deleted")) + "rm thread")) + (th2 (make-thread + (lambda () + (let loop () + (thread-sleep! 15) + (display ".") + (flush-output) + (loop))) + "action is happening thread"))) + (thread-start! th1) + (thread-start! th2) + (thread-join! th1) + (cons #t "Successfully saved data"))))))) + +(define (spublish:shell-ln src-path target-path sub-path) + (if (not (file-exists? sub-path)) + (sauth:print-error (conc "Path " sub-path " does not exist!! cannot proceed with link creation!!")) + (begin + (if (not (file-exists? src-path)) + (sauth:print-error (conc "Path " src-path " does not exist!! cannot proceed with link creation!!")) + (begin + (if (file-exists? target-path) + (sauth:print-error (conc "Path " target-path "already exist!! cannot proceed with link creation!!")) + (begin + (create-symbolic-link src-path target-path ) + (print " ... link " target-path " created")))))))) + +(define (spublish:shell-help) +(conc "Usage: [action [params ...]] + + ls [target path] : list contents of target area. + cd : To change the current directory within the sretrive shell. + pwd : Prints the full pathname of the current directory within the sretrive shell. + mkdir : creates directory. Note it does not create's a path recursive manner. + rm : removes files and emoty directories + cp : copy a file/dir to target path. if src is a dir it automatically makes a recursive copy. + ln TARGET LINK_NAME : creates a symlink +Part of the Megatest tool suite. +Learn more at http://www.kiatoa.com/fossils/megatest + +Version: " megatest-fossil-hash) +) + +(define (toplevel-command . args) #f) + +(define (spublish:shell area) + ; (print area) + (use readline) + + (let* ((path '()) + (prompt "spublish> ") + (args (argv)) + (usr (current-user-name) ) + (top-areas (spublish:get-accessable-projects area)) + (close-port #f) + (area-obj (get-obj-by-code area)) + (user-obj (get-user usr)) + (base-path (if (null? area-obj) + "" + (caddr (cdr area-obj)))) + (iport (make-readline-port prompt))) + ;(print base-path) + (if (null? area-obj) + (begin + (print "Area " area " does not exist") + (exit 1))) + ; (print "here") + (let loop ((inl (read-line iport))) + (if (not (or (or (eof-object? inl) + (equal? inl "exit")) (port-closed? iport))) + (let* ((parts (string-split inl)) + (cmd (if (null? parts) #f (car parts)))) + (if (and (not cmd) (not (port-closed? iport))) + (loop (read-line)) + (case (string->symbol cmd) + ((cd) + (if (> (length parts) 1) ;; have a parameter + (begin + (let*((arg (cadr parts)) + (resolved-path (sauth-common:resolve-path arg path top-areas)) + (target-path (sauth-common:get-target-path path arg top-areas base-path))) + (if (not (equal? target-path #f)) + (if (or (equal? resolved-path #f) (not (file-exists? target-path))) + (print "Invalid argument " arg ".. ") + (begin + (set! path resolved-path) + (sauthorize:do-as-calling-user + (lambda () + (run-cmd (conc *sauth-path* "/sauthorize") (list "register-log" (conc "\"" inl "\"") (number->string (car user-obj)) (number->string (caddr area-obj)) "cd")))) + ))))) + (set! path '()))) + ((pwd) + (if (null? path) + (print "/") + (print "/" (string-join path "/")))) + ((ls) + (let* ((thepath (if (> (length parts) 1) ;; have a parameter + (cdr parts) + `())) + (plen (length thepath))) + (cond + ((null? thepath) + (sauth-common:shell-ls-cmd path "" top-areas base-path '()) + (sauthorize:do-as-calling-user + (lambda () + (run-cmd (conc *sauth-path* "/sauthorize") (list "register-log" (conc "\"" inl "\"") (number->string (car user-obj)) (number->string (caddr area-obj)) "ls")))) ) + ((< plen 2) + (sauth-common:shell-ls-cmd path (car thepath) top-areas base-path '()) + (sauthorize:do-as-calling-user + (lambda () + (run-cmd (conc *sauth-path* "/sauthorize") (list "register-log" (conc "\"" inl "\"") (number->string (car user-obj)) (number->string (caddr area-obj)) "ls"))))) + (else + (if (equal? (car thepath) "|") + (sauth-common:shell-ls-cmd path "" top-areas base-path thepath) + (sauth-common:shell-ls-cmd path (car thepath) top-areas base-path (cdr thepath))) + (sauthorize:do-as-calling-user + (lambda () + (run-cmd (conc *sauth-path* "/sauthorize") (list "register-log" (conc "\"" inl "\"") (number->string (car user-obj)) (number->string (caddr area-obj)) "ls")))))))) + ((mkdir) + (let* ((thepath (if (> (length parts) 1) ;; have a parameter + (cdr parts) + `())) + (plen (length thepath))) + (cond + ((null? thepath) + (print "mkdir takes one argument")) + ((< plen 2) + (let*((mk-path (cadr parts)) + (resolved-path (sauth-common:resolve-path mk-path path top-areas)) + (target-path (sauth-common:get-target-path path mk-path top-areas base-path))) + (if (not (equal? target-path #f)) + (if (equal? resolved-path #f) + (print "Invalid argument " mk-path ".. ") + (begin + (print "here") + (spublish:shell-mkdir target-path) + (sauthorize:do-as-calling-user + (lambda () + (run-cmd (conc *sauth-path* "/sauthorize") (list "register-log" (conc "\"" inl "\"") (number->string (car user-obj)) (number->string (caddr area-obj)) "mkdir"))))))) + ))))) + ((rm) + (let* ((thepath (if (> (length parts) 1) ;; have a parameter + (cdr parts) + `())) + (plen (length thepath))) + (cond + ((null? thepath) + (print "rm takes one argument")) + ((< plen 2) + (let*((rm-path (cadr parts)) + (resolved-path (sauth-common:resolve-path rm-path path top-areas)) + (target-path (sauth-common:get-target-path path rm-path top-areas base-path))) + (if (not (equal? target-path #f)) + (if (equal? resolved-path #f) + (print "Invalid argument " rm-path ".. ") + (begin + (spublish:shell-rm target-path iport) + (sauthorize:do-as-calling-user + (lambda () + (run-cmd (conc *sauth-path* "/sauthorize") (list "register-log" (conc "\"" inl "\"") (number->string (car user-obj)) (number->string (caddr area-obj)) "rm"))))))) + ))))) + + ((cp publish) + (let* ((thepath (if (> (length parts) 1) ;; have a parameter + (cdr parts) + `())) + (plen (length thepath))) + (cond + ((or (null? thepath) (< plen 2)) + (print "cp takes two argument")) + ((< plen 3) + (let*((src-path (car thepath)) + (dest-path (cadr thepath)) + (resolved-path (sauth-common:resolve-path dest-path path top-areas)) + (target-path (sauth-common:get-target-path path dest-path top-areas base-path))) + (if (not (equal? target-path #f)) + (if (equal? resolved-path #f) + (print "Invalid argument " dest-path ".. ") + (begin + (spublish:shell-cp src-path target-path) + (sauthorize:do-as-calling-user + (lambda () + (run-cmd (conc *sauth-path* "/sauthorize") (list "register-log" (conc "\"" inl "\"") (number->string (car user-obj)) (number->string (caddr area-obj)) "cp"))))))) + ))))) + ((ln) + (let* ((thepath (if (> (length parts) 1) ;; have a parameter + (cdr parts) + `())) + (plen (length thepath))) + (cond + ((or (null? thepath) (< plen 2)) + (print "ln takes two argument")) + ((< plen 3) + (let*((src-path (car thepath)) + (dest-path (cadr thepath)) + (resolved-path (sauth-common:resolve-path dest-path path top-areas)) + (target-path (sauth-common:get-target-path path dest-path top-areas base-path)) + (sub-path (conc "/" (string-reverse (string-join (cdr (string-split (string-reverse target-path) "/")) "/"))))) + (if (not (equal? target-path #f)) + (if (equal? resolved-path #f) + (print "Invalid argument " dest-path ".. ") + (begin + (spublish:shell-ln src-path target-path sub-path) + (sauthorize:do-as-calling-user + (lambda () + (run-cmd (conc *sauth-path* "/sauthorize") (list "register-log" (conc "\"" inl "\"") (number->string (car user-obj)) (number->string (caddr area-obj)) "ln"))))))) + ))))) + ((exit) + (print "got exit")) + ((help) + (print (spublish:shell-help))) + (else + (print "Got command: " inl)))) + (loop (read-line iport))))))) + ;;====================================================================== ;; MAIN ;;====================================================================== -(define (spublish:load-config exe-dir exe-name) - (let* ((fname (conc exe-dir "/." exe-name ".config"))) +;(define (spublish:load-config exe-dir exe-name) +; (let* ((fname (conc exe-dir "/." exe-name ".config"))) ;; (ini:property-separator-patt " * *") ;; (ini:property-separator #\space) - (if (file-exists? fname) - ;; (ini:read-ini fname) - (read-config fname #f #t) - (make-hash-table)))) - -(define (spublish:process-action configdat action . args) - (let* ((target-dir (configf:lookup configdat "settings" "target-dir")) - (user (current-user-name)) - (allowed-users (string-split - (or (configf:lookup configdat "settings" "allowed-users") - "")))) - (if (not target-dir) - (begin - (print "[settings]\ntarget-dir /some/path\n\n Is MISSING from the config file!") - (exit))) - (if (null? allowed-users) - (begin - (print "[setings]\nallowed-users user1 user2 ...\n\n Is MISSING from the config file!") - (exit))) - (if (not (member user allowed-users)) - (begin - (print "User \"" (current-user-name) "\" does not have access. Exiting") - (exit 1))) +; (if (file-exists? fname) +; ;; (ini:read-ini fname) +; (read-config fname #f #t) +; (make-hash-table)))) + +(define (spublish:process-action action . args) + ;(print args) + (let* ((usr (current-user-name)) + (user-obj (get-user usr)) + (area (car args)) + (area-obj (get-obj-by-code area)) + (top-areas (spublish:get-accessable-projects area)) + (base-path (if (null? area-obj) + "" + (caddr (cdr area-obj)))) + (remargs (cdr args))) + (if (null? area-obj) + (begin + (print "Area " area " does not exist") + (exit 1))) (case (string->symbol action) ((cp publish) - (if (< (length args) 2) + (if (< (length remargs) 2) (begin - (print "ERROR: Missing arguments; " (string-intersperse args ", ")) + (print "ERROR: Missing arguments; spublish " ) (exit 1))) - (let* ((remargs (args:get-args args '("-m") '() args:arg-hash 0)) - (dest-dir (cadr args)) - (src-path-in (car args)) + (let* ((filter-args (args:get-args args '("-m") '() args:arg-hash 0)) + (src-path-in (car filter-args)) + (dest-path (cadr filter-args)) (src-path (with-input-from-pipe (conc "readlink -f " src-path-in) (lambda () (read-line)))) (msg (or (args:get-arg "-m") "")) - (targ-file (pathname-strip-directory src-path))) - (if (not (file-read-access? src-path)) - (begin - (print "ERROR: source file not readable: " src-path) - (exit 1))) - (if (directory? src-path) - (begin - (print "ERROR: source file is a directory, this is not supported yet.") - (exit 1))) - (print "publishing " src-path-in " to " target-dir) - (spublish:validate target-dir dest-dir) - (spublish:cp configdat user src-path target-dir targ-file dest-dir msg))) - ((tar) - (if (< (length args) 1) - (begin - (print "ERROR: Missing arguments; " (string-intersperse args ", ")) - (exit 1))) - (let* ((dst-dir (car args)) - (msg (or (args:get-arg "-m") ""))) - (spublish:validate target-dir dst-dir) - (spublish:tar configdat user target-dir dst-dir msg))) - - ((mkdir) - (if (< (length args) 1) - (begin - (print "ERROR: Missing arguments; " (string-intersperse args ", ")) - (exit 1))) - (let* ((targ-mk (car args)) - (msg (or (args:get-arg "-m") ""))) - (print "attempting to create directory " targ-mk " in " target-dir) - (spublish:validate target-dir targ-mk) - (spublish:mkdir configdat user target-dir targ-mk msg))) - - ((ln) - (if (< (length args) 2) - (begin - (print "ERROR: Missing arguments; " (string-intersperse args ", ")) - (exit 1))) - (let* ((targ-link (car args)) - (link-name (cadr args)) - (sub-path (string-reverse (string-join (cdr (string-split (string-reverse link-name) "/")) "/"))) - (msg (or (args:get-arg "-m") ""))) - (if (> (string-length(string-trim sub-path)) 0) - (begin - (print "attempting to create directory " sub-path " in " target-dir) - (spublish:validate target-dir sub-path) - (print (conc target-dir "/" sub-path ) ) - (print (directory-exists?(conc target-dir "/" sub-path ))) - (if (directory-exists?(conc target-dir "/" sub-path )) - (print "Target Directory " (conc target-dir sub-path ) " exist!!") - (spublish:mkdir configdat user target-dir sub-path msg)))) - - (print "attempting to create link " link-name " in " target-dir) - (spublish:ln configdat user target-dir targ-link link-name msg))) - + (resolved-path (sauth-common:resolve-path (conc area "/" dest-path) `() top-areas)) + (target-path (sauth-common:get-target-path `() (conc area "/" dest-path) top-areas base-path))) + (if (not (equal? target-path #f)) + (if (equal? resolved-path #f) + (print "Invalid argument " dest-path ".. ") + (begin + (spublish:shell-cp src-path target-path) + (sauthorize:do-as-calling-user + (lambda () + (run-cmd (conc *sauth-path* "/sauthorize") (list "register-log" (conc "\" cp " src-path-in " " dest-path "\"") (number->string (car user-obj)) (number->string (caddr area-obj)) "cp"))))))))) + ((mkdir) + (if (< (length remargs) 1) + (begin + (print "ERROR: Missing arguments; ") + (exit 1))) + (let* ((filter-args (args:get-args args '("-m") '() args:arg-hash 0)) + (mk-path (car filter-args)) + (msg (or (args:get-arg "-m") "")) + (resolved-path (sauth-common:resolve-path mk-path (list area) top-areas)) + (target-path (sauth-common:get-target-path (list area) mk-path top-areas base-path))) + (print "attempting to create directory " mk-path ) + (if (not (equal? target-path #f)) + (if (equal? resolved-path #f) + (print "Invalid argument " mk-path ".. ") + (begin + (spublish:shell-mkdir target-path) + (sauthorize:do-as-calling-user + (lambda () + (run-cmd (conc *sauth-path* "/sauthorize") (list "register-log" (conc "\" mkdir " mk-path "\"") (number->string (car user-obj)) (number->string (caddr area-obj)) "mkdir"))))))))) + ((ln) + (if (< (length remargs) 2) + (begin + (print "ERROR: Missing arguments; " ) + (exit 1))) + (let* ((filter-args (args:get-args args '("-m") '() args:arg-hash 0)) + (src-path (car filter-args)) + (dest-path (cadr filter-args)) + (resolved-path (sauth-common:resolve-path dest-path (list area) top-areas)) + (target-path (sauth-common:get-target-path (list area) dest-path top-areas base-path)) + (sub-path (conc "/" (string-reverse (string-join (cdr (string-split (string-reverse target-path) "/")) "/"))))) + (if (not (equal? target-path #f)) + (if (equal? resolved-path #f) + (print "Invalid argument " dest-path ".. ") + (begin + (spublish:shell-ln src-path target-path sub-path) + (sauthorize:do-as-calling-user + (lambda () + (run-cmd (conc *sauth-path* "/sauthorize") (list "register-log" (conc "\" ln " src-path " " dest-path "\"") (number->string (car user-obj)) (number->string (caddr area-obj)) "ln"))))))))) ((rm) - (if (< (length args) 1) + (if (< (length remargs) 1) (begin - (print "ERROR: Missing arguments; " (string-intersperse args ", ")) + (print "ERROR: Missing arguments; ") (exit 1))) - (let* ((targ-file (car args)) - (msg (or (args:get-arg "-m") ""))) - (print "attempting to remove " targ-file " from " target-dir) - (spublish:validate target-dir targ-file) - - (spublish:rm configdat user target-dir targ-file msg))) - ((publish) - (if (< (length args) 3) - (begin - (print "ERROR: Missing arguments; " (string-intersperse args ", ")) + (let* ((filter-args (args:get-args args '("-m") '() args:arg-hash 0)) + (rm-path (car filter-args)) + (resolved-path (sauth-common:resolve-path rm-path (list area) top-areas)) + (prompt ">") + (iport (make-readline-port prompt)) + (target-path (sauth-common:get-target-path (list area) rm-path top-areas base-path))) + (if (not (equal? target-path #f)) + (if (equal? resolved-path #f) + (print "Invalid argument " rm-path ".. ") + (begin + (spublish:shell-rm target-path iport) + (sauthorize:do-as-calling-user + (lambda () + (run-cmd (conc *sauth-path* "/sauthorize") (list "register-log" (conc "\" rm " rm-path "\"") (number->string (car user-obj)) (number->string (caddr area-obj)) "rm"))))))))) + ((shell) + (if (< (length args) 1) + (begin + (print "ERROR: Missing arguments area!!" ) (exit 1)) - (let* ((srcpath (list-ref args 0)) - (areaname (list-ref args 1)) - (version (list-ref args 2)) - (remargs (args:get-args (drop args 2) - '("-type" ;; link or copy (default is copy) - "-m") - '() - args:arg-hash - 0)) - (publish-type (if (equal? (args:get-arg "-type") "link") 'link 'copy)) - (comment (or (args:get-arg "-m") "")) - (submitter (current-user-name)) - (quality (args:get-arg "-quality")) - (publish-res (spublish:publish configdat publish-type areaname version comment srcpath submitter quality))) - (if (not (car publish-res)) - (begin - (print "ERROR: " (cdr publish-res)) - (exit 1)))))) - ((list-versions) - (let ((area-name (car args)) ;; version patt full print - (remargs (args:get-args args '("-vpatt") '("-full") args:arg-hash 0)) - (db (spublish:open-db configdat)) - (versions (spublish:get-versions-for-area db (car args) version-patt: (args:get-arg "-vpatt")))) - ;; (print "area-name=" area-name " args=" args " *args-hash*=" (hash-table->alist *args-hash*)) - (map (lambda (x) - (if (args:get-arg "-full") - (format #t - "~10a~10a~4a~27a~30a\n" - (vector-ref x 0) - (vector-ref x 1) - (vector-ref x 2) - (conc "\"" (time->string (seconds->local-time (vector-ref x 3))) "\"") - (conc "\"" (vector-ref x 4) "\"")) - (print (vector-ref x 0)))) - versions))) + (spublish:shell area))) (else (print "Unrecognised command " action))))) ;; ease debugging by loading ~/.dashboardrc - REMOVE FROM PRODUCTION! ;; (let ((debugcontrolf (conc (get-environment-variable "HOME") "/.spublishrc"))) ;; (if (file-exists? debugcontrolf) @@ -506,37 +790,21 @@ (define (main) (let* ((args (argv)) (prog (car args)) (rema (cdr args)) - (exe-name (pathname-file (car (argv)))) - (exe-dir (or (pathname-directory prog) - (spublish:find exe-name (string-split (get-environment-variable "PATH") ":")))) - (configdat (spublish:load-config exe-dir exe-name))) + (exe-name (pathname-file (car (argv))))) (cond ;; one-word commands ((eq? (length rema) 1) (case (string->symbol (car rema)) ((help -h -help --h --help) (print spublish:help)) - ((list-vars) ;; print out the ini file - (map print (spublish:get-areas configdat))) - ((ls) - (let ((target-dir (configf:lookup configdat "settings" "target-dir"))) - (print "Files in " target-dir) - (system (conc "ls " target-dir)))) - ((log) - (spublish:db-do configdat (lambda (db) - (print "Listing actions") - (query (for-each-row - (lambda (row) - (apply print (intersperse row " | ")))) - (sql db "SELECT * FROM actions"))))) (else (print "ERROR: Unrecognised command. Try \"spublish help\"")))) ;; multi-word commands ((null? rema)(print spublish:help)) ((>= (length rema) 2) - (apply spublish:process-action configdat (car rema)(cdr rema))) + (apply spublish:process-action (car rema)(cdr rema))) (else (print "ERROR: Unrecognised command2. Try \"spublish help\""))))) (main) Index: sretrieve.scm ================================================================== --- sretrieve.scm +++ sretrieve.scm @@ -7,43 +7,29 @@ ;; This program is distributed WITHOUT ANY WARRANTY; without even the ;; implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ;; PURPOSE. (use defstruct) - -;; (use ssax) -;; (use sxml-serializer) -;; (use sxml-modifications) -;; (use regex) -;; (use srfi-69) -;; (use regex-case) -;; (use posix) -;; (use json) -;; (use csv) -;; (use directory-utils) +(use scsh-process) (use srfi-18) -(use format) - -;; (require-library ini-file) -;; (import (prefix ini-file ini:)) - +(use srfi-19) +(use refdb) (use sql-de-lite srfi-1 posix regex regex-case srfi-69) -;; (import (prefix sqlite3 sqlite3:)) -;; +(declare (uses common)) (declare (uses configf)) -;; (declare (uses tree)) (declare (uses margs)) -;; (declare (uses dcommon)) -;; (declare (uses launch)) -;; (declare (uses gutils)) -;; (declare (uses db)) -;; (declare (uses synchash)) -;; (declare (uses server)) (declare (uses megatest-version)) -;; (declare (uses tbd)) + (include "megatest-fossil-hash.scm") +;;; please create this file before using sautherise. For sample file is avaliable sample-sauth-paths.scm. +(include "sauth-paths.scm") +(include "sauth-common.scm") + +(define (toplevel-command . args) #f) +(use readline) + ;; ;; GLOBALS ;; (define *verbosity* 1) @@ -51,16 +37,14 @@ (define *exe-name* (pathname-file (car (argv)))) (define *sretrieve:current-tab-number* 0) (define *args-hash* (make-hash-table)) (define sretrieve:help (conc "Usage: " *exe-name* " [action [params ...]] - ls : list contents of target area - get : retrieve data for release - -m \"message\" : why retrieved? - cp : copy file to current directory - log : get listing of recent downloads - shell : start a shell-like interface + ls : list contents of target area + get : retrieve path to the data within + -m \"message\" : why retrieved? + shell : start a shell-like interface Part of the Megatest tool suite. Learn more at http://www.kiatoa.com/fossils/megatest Version: " megatest-fossil-hash)) ;; " @@ -72,320 +56,214 @@ ;;====================================================================== ;; DB ;;====================================================================== ;; replace (strftime('%s','now')), with datetime('now')) -(define (sretrieve:initialize-db db) - (for-each - (lambda (qry) - (exec (sql db qry))) - (list - "CREATE TABLE IF NOT EXISTS actions - (id INTEGER PRIMARY KEY, - action TEXT NOT NULL, - retriever TEXT NOT NULL, - datetime TIMESTAMP DEFAULT (datetime('now','localtime')), - srcpath TEXT NOT NULL, - comment TEXT DEFAULT '' NOT NULL, - state TEXT DEFAULT 'new');" - "CREATE TABLE IF NOT EXISTS bundles - (id INTEGER PRIMARY KEY, - bundle TEXT NOT NULL, - release TEXT NOT NULL, - status TEXT NOT NULL, - event_date TEXT NOT NULL);" - ))) - -(define (sretrieve:register-action db action submitter source-path comment) - (print "(sretrieve:register-action db " db " action " action " submitter " submitter " source-path " source-path " comment " comment) - (exec (sql db "INSERT INTO actions (action,retriever,srcpath,comment) - VALUES(?,?,?,?)") - action - submitter - source-path - (or comment ""))) +;(define (sretrieve:initialize-db db) +; (for-each +; (lambda (qry) +; (exec (sql db qry))) +; (list +; "CREATE TABLE IF NOT EXISTS actions +; (id INTEGER PRIMARY KEY, +; action TEXT NOT NULL, +; retriever TEXT NOT NULL, +; datetime TIMESTAMP DEFAULT (datetime('now','localtime')), +; srcpath TEXT NOT NULL, +; comment TEXT DEFAULT '' NOT NULL, +; state TEXT DEFAULT 'new');" +; "CREATE TABLE IF NOT EXISTS bundles +; (id INTEGER PRIMARY KEY, +; bundle TEXT NOT NULL, +; release TEXT NOT NULL, +; status TEXT NOT NULL, +; event_date TEXT NOT NULL);" +; ))) +; +;(define (sretrieve:register-action db action submitter source-path comment) +; ; (print "(sretrieve:register-action db " db " action " action " submitter " submitter " source-path " source-path " comment " comment) +; (exec (sql db "INSERT INTO actions (action,retriever,srcpath,comment) +; VALUES(?,?,?,?)") +; action +; submitter +; source-path +; (or comment ""))) ;; (call-with-database ;; (lambda (db) ;; (set-busy-handler! db (busy-timeout 10000)) ; 10 second timeout ;; ...)) ;; Create the sqlite db -(define (sretrieve:db-do configdat proc) - - (let ((path (configf:lookup configdat "database" "location"))) - (if (not path) - (begin - (debug:print 0 *default-log-port* "[database]\nlocation /some/path\n\n Is missing from the config file!") - (exit 1))) - (if (and path - (directory? path) - (file-read-access? path)) - (let* ((dbpath (conc path "/" *exe-name* ".db")) - (writeable (file-write-access? dbpath)) - (dbexists (file-exists? dbpath))) - (handle-exceptions - exn - (begin - (debug:print 2 *default-log-port* "ERROR: problem accessing db " dbpath - ((condition-property-accessor 'exn 'message) exn)) - (exit 1)) - ;;(debug:print 0 *default-log-port* "calling proc " proc "db path " dbpath ) - (call-with-database - dbpath - (lambda (db) - ;;(debug:print 0 *default-log-port* "calling proc " proc " on db " db) - (set-busy-handler! db (busy-timeout 10000)) ;; 10 sec timeout - (if (not dbexists)(sretrieve:initialize-db db)) - (proc db))))) - (debug:print-error 0 *default-log-port* "invalid path for storing database: " path)))) +;(define (sretrieve:db-do configdat proc) +; (let ((path (configf:lookup configdat "database" "location"))) +; (if (not path) +; (begin +; (debug:print 0 "[database]\nlocation /some/path\n\n Is missing from the config file!") +; (exit 1))) +; (if (and path +; (directory? path) +; (file-read-access? path)) +; (let* ((dbpath (conc path "/" *exe-name* ".db")) +; (writeable (file-write-access? dbpath)) +; (dbexists (file-exists? dbpath))) +; (handle-exceptions +; exn +; (begin +; (debug:print 2 "ERROR: problem accessing db " dbpath +; ((condition-property-accessor 'exn 'message) exn)) +; (exit 1)) +; ;;(debug:print 0 "calling proc " proc "db path " dbpath ) +; (call-with-database +; dbpath +; (lambda (db) +; ;;(debug:print 0 "calling proc " proc " on db " db) +; (set-busy-handler! db (busy-timeout 10000)) ;; 10 sec timeout +; (if (not dbexists)(sretrieve:initialize-db db)) +; (proc db))))) +; (debug:print 0 "ERROR: invalid path for storing database: " path)))) ;; copy in directory to dest, validation is done BEFORE calling this ;; -(define (sretrieve:get configdat retriever version comment) - (let* ((base-dir (configf:lookup configdat "settings" "base-dir")) - (datadir (conc base-dir "/" version))) - (if (or (not base-dir) - (not (file-exists? base-dir))) - (begin - (debug:print-error 0 *default-log-port* "Bad configuration! base-dir " base-dir " not found") - (exit 1))) - (print datadir) - (if (not (file-exists? datadir)) - (begin - (debug:print-error 0 *default-log-port* "Bad version (" version "), no data found at " datadir "." ) - (exit 1))) - - (sretrieve:db-do - configdat - (lambda (db) - (sretrieve:register-action db "get" retriever datadir comment))) - (sretrieve:do-as-calling-user - (lambda () - (if (directory? datadir) - (begin - (change-directory datadir) - (let ((files (filter (lambda (x) - (not (member x '("." "..")))) - (glob "*" ".*")))) - (print "files: " files) - (process-execute "/bin/tar" (append (append (list "chfv" "-") files) (list "--ignore-failed-read"))))) - (begin - (let* ((parent-dir (pathname-directory datadir) ) - (filename (conc(pathname-file datadir) "." (pathname-extension datadir)))) - (change-directory parent-dir) - (process-execute "/bin/tar" (list "chfv" "-" filename)) - ))) -)) -)) - - -;; copy in file to dest, validation is done BEFORE calling this -;; -(define (sretrieve:cp configdat retriever file comment) - (let* ((base-dir (configf:lookup configdat "settings" "base-dir")) - (allowed-sub-paths (configf:lookup configdat "settings" "allowed-sub-paths")) - (datadir (conc base-dir "/" file)) - (filename (conc(pathname-file datadir) "." (pathname-extension datadir)))) - (if (or (not base-dir) - (not (file-exists? base-dir))) - (begin - (debug:print-error 0 *default-log-port* "Bad configuration! base-dir " base-dir " not found") - (exit 1))) - (print datadir) - (if (not (file-exists? datadir)) - (begin - (debug:print-error 0 *default-log-port* "File (" file "), not found at " base-dir "." ) - (exit 1))) - (if (directory? datadir) - (begin - (debug:print-error 0 *default-log-port* "(" file ") is a dirctory!! cp cmd works only on files ." ) - (exit 1))) - (if(not (string-match (regexp allowed-sub-paths) file)) - (begin - (debug:print-error 0 *default-log-port* "Access denied to file (" file ")!! " ) - (exit 1))) - - (sretrieve:db-do - configdat - (lambda (db) - (sretrieve:register-action db "cp" retriever datadir comment))) - (sretrieve:do-as-calling-user - ;; (debug:print 0 *default-log-port* "ph: "(pathname-directory datadir) "!! " ) - (change-directory (pathname-directory datadir)) - ;;(debug:print 0 *default-log-port* "ph: /bin/tar" (list "chfv" "-" filename) ) - (process-execute "/bin/tar" (list "chfv" "-" filename))) - )) - -;; ls in file to dest, validation is done BEFORE calling this -;; -(define (sretrieve:ls configdat retriever file comment) - (let* ((base-dir (configf:lookup configdat "settings" "base-dir")) - (allowed-sub-paths (configf:lookup configdat "settings" "allowed-sub-paths")) - (datadir (conc base-dir "/" file)) - (filename (conc(pathname-file datadir) "." (pathname-extension datadir)))) - (if (or (not base-dir) - (not (file-exists? base-dir))) - (begin - (debug:print-error 0 *default-log-port* "Bad configuration! base-dir " base-dir " not found") - (exit 1))) - (print datadir) - (if (not (file-exists? datadir)) - (begin - (debug:print-error 0 *default-log-port* "File (" file "), not found at " base-dir "." ) - (exit 1))) - (if(not (string-match (regexp allowed-sub-paths) file)) - (begin - (debug:print-error 0 *default-log-port* "Access denied to file (" file ")!! " ) - (exit 1))) - - (sretrieve:do-as-calling-user - (lambda () - ;;(change-directory datadir) - ;; (debug:print 0 *default-log-port* "/usr/bin/find" (list datadir "-ls" "|" "grep" "-E" "'"allowed-file-patt"'")) - ;; (status (with-input-from-pipe "find " datadir " -ls | grep -E '" allowed-file-patt "'" (lambda () (read-line)))) - ;; (debug:print 0 *default-log-port* status) - (process-execute "/bin/ls" (list "-ls" "-lrt" datadir )) - )))) - - - -;;(filter (lambda (x) -;; (not (member x '("." "..")))) -;; (glob "*" ".*")))))))) +;(define (sretrieve:get configdat retriever version comment) +; (let* ((base-dir (configf:lookup configdat "settings" "base-dir")) +; (datadir (conc base-dir "/" version))) +; (if (or (not base-dir) +; (not (file-exists? base-dir))) +; (begin +; (debug:print 0 "ERROR: Bad configuration! base-dir " base-dir " not found") +; (exit 1))) +; (print datadir) +; (if (not (file-exists? datadir)) +; (begin +; (debug:print 0 "ERROR: Bad version (" version "), no data found at " datadir "." ) +; (exit 1))) +; +; (sretrieve:db-do +; configdat +; (lambda (db) +; (sretrieve:register-action db "get" retriever datadir comment))) +; (sretrieve:do-as-calling-user +; (lambda () +; (if (directory? datadir) +; (begin +; (change-directory datadir) +; (let ((files (filter (lambda (x) +; (not (member x '("." "..")))) +; (glob "*" ".*")))) +; (print "files: " files) +; (process-execute "/bin/tar" (append (append (list "chfv" "-") files) (list "--ignore-failed-read"))))) +; (begin +; (let* ((parent-dir (pathname-directory datadir) ) +; (filename (conc(pathname-file datadir) "." (pathname-extension datadir)))) +; (change-directory parent-dir) +; (process-execute "/bin/tar" (list "chfv" "-" filename)) +; ))) +;)))) +; +; +;;; copy in file to dest, validation is done BEFORE calling this +;;; +;(define (sretrieve:cp configdat retriever file comment) +; (let* ((base-dir (configf:lookup configdat "settings" "base-dir")) +; (allowed-sub-paths (configf:lookup configdat "settings" "allowed-sub-paths")) +; (datadir (conc base-dir "/" file)) +; (filename (conc(pathname-file datadir) "." (pathname-extension datadir)))) +; (if (or (not base-dir) +; (not (file-exists? base-dir))) +; (begin +; (debug:print 0 "ERROR: Bad configuration! base-dir " base-dir " not found") +; (exit 1))) +; (print datadir) +; (if (not (file-exists? datadir)) +; (begin +; (debug:print 0 "ERROR: File (" file "), not found at " base-dir "." ) +; (exit 1))) +; (if (directory? datadir) +; (begin +; (debug:print 0 "ERROR: (" file ") is a dirctory!! cp cmd works only on files ." ) +; (exit 1))) +; (if(not (string-match (regexp allowed-sub-paths) file)) +; (begin +; (debug:print 0 "ERROR: Access denied to file (" file ")!! " ) +; (exit 1))) +; +; (sretrieve:db-do +; configdat +; (lambda (db) +; (sretrieve:register-action db "cp" retriever datadir comment))) +; (sretrieve:do-as-calling-user +; ;; (debug:print 0 "ph: "(pathname-directory datadir) "!! " ) +; (change-directory (pathname-directory datadir)) +; ;;(debug:print 0 "ph: /bin/tar" (list "chfv" "-" filename) ) +; (process-execute "/bin/tar" (list "chfv" "-" filename))) +; )) +; +;;; ls in file to dest, validation is done BEFORE calling this +;;; +;(define (sretrieve:ls configdat retriever file comment) +; (let* ((base-dir (configf:lookup configdat "settings" "base-dir")) +; (allowed-sub-paths (configf:lookup configdat "settings" "allowed-sub-paths")) +; (datadir (conc base-dir "/" file)) +; (filename (conc(pathname-file datadir) "." (pathname-extension datadir)))) +; (if (or (not base-dir) +; (not (file-exists? base-dir))) +; (begin +; (debug:print 0 "ERROR: Bad configuration! base-dir " base-dir " not found") +; (exit 1))) +; (print datadir) +; (if (not (file-exists? datadir)) +; (begin +; (debug:print 0 "ERROR: File (" file "), not found at " base-dir "." ) +; (exit 1))) +; (if(not (string-match (regexp allowed-sub-paths) file)) +; (begin +; (debug:print 0 "ERROR: Access denied to file (" file ")!! " ) +; (exit 1))) +; +; (sretrieve:do-as-calling-user +; (lambda () +; (process-execute "/bin/ls" (list "-ls" "-lrt" datadir )) +; )))) + + (define (sretrieve:validate target-dir targ-mk) (let* ((normal-path (normalize-pathname targ-mk)) (targ-path (conc target-dir "/" normal-path))) (if (string-contains normal-path "..") (begin - (debug:print-error 0 *default-log-port* "Path " targ-mk " resolved outside target area " target-dir ) + (debug:print 0 "ERROR: Path " targ-mk " resolved outside target area " target-dir ) (exit 1))) (if (not (string-contains targ-path target-dir)) (begin - (debug:print-error 0 *default-log-port* "You cannot update data outside " target-dir ".") + (debug:print 0 "ERROR: You cannot update data outside " target-dir ".") (exit 1))) - (debug:print 0 *default-log-port* "Path " targ-mk " is valid.") + (debug:print 0 "Path " targ-mk " is valid.") )) -;; make directory in dest -;; - -(define (sretrieve:mkdir configdat submitter target-dir targ-mk comment) - (let ((targ-path (conc target-dir "/" targ-mk))) - - (if (file-exists? targ-path) - (begin - (debug:print-error 0 *default-log-port* "target Directory " targ-path " already exist!!") - (exit 1))) - (sretrieve:db-do - configdat - (lambda (db) - (sretrieve:register-action db "mkdir" submitter targ-mk comment))) - (let* ((th1 (make-thread - (lambda () - (create-directory targ-path #t) - (debug:print 0 *default-log-port* " ... dir " targ-path " created")) - "mkdir thread")) - (th2 (make-thread - (lambda () - (let loop () - (thread-sleep! 15) - (display ".") - (flush-output) - (loop))) - "action is happening thread"))) - (thread-start! th1) - (thread-start! th2) - (thread-join! th1)) - (cons #t "Successfully saved data"))) - -;; create a symlink in dest -;; -(define (sretrieve:ln configdat submitter target-dir targ-link link-name comment) - (let ((targ-path (conc target-dir "/" link-name))) - (if (file-exists? targ-path) - (begin - (debug:print-error 0 *default-log-port* "target file " targ-path " already exist!!") - (exit 1))) - (if (not (file-exists? targ-link )) - (begin - (debug:print-error 0 *default-log-port* "target file " targ-link " does not exist!!") - (exit 1))) - - (sretrieve:db-do - configdat - (lambda (db) - (sretrieve:register-action db "ln" submitter link-name comment))) - (let* ((th1 (make-thread - (lambda () - (create-symbolic-link targ-link targ-path ) - (debug:print 0 *default-log-port* " ... link " targ-path " created")) - "symlink thread")) - (th2 (make-thread - (lambda () - (let loop () - (thread-sleep! 15) - (display ".") - (flush-output) - (loop))) - "action is happening thread"))) - (thread-start! th1) - (thread-start! th2) - (thread-join! th1)) - (cons #t "Successfully saved data"))) - - -;; remove copy of file in dest -;; -(define (sretrieve:rm configdat submitter target-dir targ-file comment) - (let ((targ-path (conc target-dir "/" targ-file))) - (if (not (file-exists? targ-path)) - (begin - (debug:print-error 0 *default-log-port* "target file " targ-path " not found, nothing to remove.") - (exit 1))) - (sretrieve:db-do - configdat - (lambda (db) - (sretrieve:register-action db "rm" submitter targ-file comment))) - (let* ((th1 (make-thread - (lambda () - (delete-file targ-path) - (debug:print 0 *default-log-port* " ... file " targ-path " removed")) - "rm thread")) - (th2 (make-thread - (lambda () - (let loop () - (thread-sleep! 15) - (display ".") - (flush-output) - (loop))) - "action is happening thread"))) - (thread-start! th1) - (thread-start! th2) - (thread-join! th1)) - (cons #t "Successfully saved data"))) - -(define (sretrieve:backup-move path) - (let* ((trashdir (conc (pathname-directory path) "/.trash")) - (trashfile (conc trashdir "/" (current-seconds) "-" (pathname-file path)))) - (create-directory trashdir #t) - (if (directory? path) - (system (conc "mv " path " " trashfile)) - (file-move path trash-file)))) - - -(define (sretrieve:lst->path pathlst) - (conc "/" (string-intersperse (map conc pathlst) "/"))) - -(define (sretrieve:path->lst path) - (string-split path "/")) - -(define (sretrieve:pathdat-apply-heuristics configdat path) - (cond - ((file-exists? path) "found") - (else (conc path " not installed")))) + + +;(define (sretrieve:backup-move path) +; (let* ((trashdir (conc (pathname-directory path) "/.trash")) +; (trashfile (conc trashdir "/" (current-seconds) "-" (pathname-file path)))) +; (create-directory trashdir #t) +; (if (directory? path) +; (system (conc "mv " path " " trashfile)) +; (file-move path trash-file)))) +; +; +;(define (sretrieve:lst->path pathlst) +; (conc "/" (string-intersperse (map conc pathlst) "/"))) +; +;(define (sretrieve:path->lst path) +; (string-split path "/")) +; +;(define (sretrieve:pathdat-apply-heuristics configdat path) +; (cond +; ((file-exists? path) "found") +; (else (conc path " not installed")))) ;;====================================================================== ;; MISC ;;====================================================================== @@ -392,11 +270,11 @@ (define (sretrieve:do-as-calling-user proc) (let ((eid (current-effective-user-id)) (cid (current-user-id))) (if (not (eq? eid cid)) ;; running suid (set! (current-effective-user-id) cid)) - ;; (debug:print 0 *default-log-port* "running as " (current-effective-user-id)) + ;; (debug:print 0 "running as " (current-effective-user-id)) (proc) (if (not (eq? eid cid)) (set! (current-effective-user-id) eid)))) (define (sretrieve:find name paths) @@ -417,203 +295,770 @@ ;;====================================================================== ;; SHELL ;;====================================================================== -(define (toplevel-command . args) #f) -(define (sretrieve:shell) +;; Create the sqlite db for shell +;(define (sretrieve:shell-db-do path proc) +; (if (not path) +; (begin +; (debug:print 0 "[database]\nlocation /some/path\n\n Is missing from the config file!") +; (exit 1))) +; (if (and path +; (directory? path) +; (file-read-access? path)) +; (let* ((dbpath (conc path "/" *exe-name* ".db")) +; (writeable (file-write-access? dbpath)) +; (dbexists (file-exists? dbpath))) +; (handle-exceptions +; exn +; (begin +; (debug:print 2 "ERROR: problem accessing db " dbpath +; ((condition-property-accessor 'exn 'message) exn)) +; (exit 1)) +; ;;(debug:print 0 "calling proc " proc "db path " dbpath ) +; (call-with-database +; dbpath +; (lambda (db) +; ;;(debug:print 0 "calling proc " proc " on db " db) +; (set-busy-handler! db (busy-timeout 10000)) ;; 10 sec timeout +; (if (not dbexists)(sretrieve:initialize-db db)) +; (proc db))))) +; (debug:print 0 "ERROR: invalid path for storing database: " path))) + + + +;; function to find sheets to which use has access +(define (sretrieve:has-permission area) + (let ((username (current-user-name))) + (cond + ((is-admin username) + #t) + ((is-user "retrieve" username area) + #t) + ((is-user "publish" username area) + #t) + ((is-user "writer-admin" username area) + #t) + ((is-user "read-admin" username area) + #t) + ((is-user "area-admin" username area) + #t) + (else + #f)))) + + +(define (sretrieve:get-accessable-projects area) + (let* ((projects `())) + + (if (sretrieve:has-permission area) + (set! projects (cons area projects)) + (begin + (print "User cannot access area " area "!!") + (exit 1))) + ; (print projects) + projects)) + +(define (sauth-common:shell-ls-cmd base-path-list ext-path top-areas base-path tail-cmd-list) + (if (and (null? base-path-list) (equal? ext-path "") ) + (print (string-intersperse top-areas " ")) + (let* ((resolved-path (sauth-common:resolve-path ext-path base-path-list top-areas ))) + ;(print resolved-path) + (if (not (equal? resolved-path #f)) + (if (null? resolved-path) + (print (string-intersperse top-areas " ")) + (let* ((target-path (sauth-common:get-target-path base-path-list ext-path top-areas base-path))) + ;(print "Resolved path: " target-path) + (if (not (equal? target-path #f)) + (begin + (if (symbolic-link? target-path) + (set! target-path (conc target-path "/"))) + (if (not (equal? target-path #f)) + (begin + (cond + ((null? tail-cmd-list) + (run (pipe + (ls "-lrt" ,target-path)))) + ((not (equal? (car tail-cmd-list) "|")) + (print "ls cmd cannot accept "(string-join tail-cmd-list) " as an argument!!")) + (else + (run (pipe + (ls "-lrt" ,target-path) + (begin (system (string-join (cdr tail-cmd-list)))))) + )))))))))))) + +(define (sretrieve:shell-cat-cmd base-pathlist ext-path top-areas base-path tail-cmd-list) + (let* ((resolved-path (sauth-common:resolve-path ext-path base-pathlist top-areas )) + (data "") ) + (if (not (equal? resolved-path #f)) + (if (null? resolved-path) + (print "Path could not be resolved!!") + (let* ((target-path (sauth-common:get-target-path base-pathlist ext-path top-areas base-path))) + (if (not (equal? target-path #f)) + (if (or (not (file-exists? target-path)) (directory? target-path)) + (print "Target path does not exist or is a directory!") + (begin + (cond + ((null? tail-cmd-list) + (run (pipe + (cat ,target-path)))) + ((not (equal? (car tail-cmd-list) "|")) + (print "cat cmd cannot accept "(string-join tail-cmd-list) " as an argument!!")) + (else + (run (pipe + (cat ,target-path) + (begin (system (string-join (cdr tail-cmd-list)))))))))) +))) + (print "Path could not be resolved!!")))) + +(define (get-options cmd-list split-str) + (if (null? cmd-list) + (list '() '()) + (let loop ((hed (car cmd-list)) + (tal (cdr cmd-list)) + (res '())) + (cond + ((equal? hed split-str) + (list res tal)) + ((null? tal) + (list (cons hed res) tal)) + (else + (loop (car tal)(cdr tal)(cons hed res))))))) + + +(define (sretrieve:shell-grep-cmd base-pathlist ext-path top-areas base-path tail-cmd-list) + (let* ((resolved-path (sauth-common:resolve-path ext-path base-pathlist top-areas )) + (pattern (car tail-cmd-list)) + (pipe-cmd-list (get-options (cdr tail-cmd-list) "|")) + (options (string-join (car pipe-cmd-list))) + (pipe-cmd (cadr pipe-cmd-list)) + (redirect-split (string-split (string-join tail-cmd-list) ">")) ) + (if(and ( > (length redirect-split) 2 )) + (print "sgrep cmd cannot accept > " (string-join redirect-split) " as an argument!!" ) + (if (not (equal? resolved-path #f)) + (if (null? resolved-path) + (print "Path could not be resolved!!") + (let* ((target-path (sauth-common:get-target-path base-pathlist ext-path top-areas base-path)) + (restrictions (if (equal? target-path #f) + "" + (sretrieve:shell-lookup base-path))) + (rest-str (string-split (conc " --exclude-dir=" (string-join (string-split restrictions ",") " --exclude-dir=") )))) + (if (not (file-exists? target-path)) + (print "Target path does not exist!") + (begin + (cond + ((and (null? pipe-cmd) (string-null? options)) + (run (pipe + (grep ,pattern ,target-path )))) + ((and (null? pipe-cmd) (not (string-null? options))) + (run (pipe + (begin (process-execute "/usr/bin/grep" (append (list options pattern target-path) rest-str)))))) + ((and (not (null? pipe-cmd)) (string-null? options)) + (run (pipe + (grep ,exclude-dir ,pattern ,target-path) + (begin (system (string-join pipe-cmd)))))) + (else + (run (pipe + ;(grep ,options ,exclude-dir ,pattern ,target-path) + (begin (process-execute "/usr/bin/grep" (append (list options pattern target-path) rest-str))) + + (begin (system (string-join pipe-cmd))))))) +)))) + (print "Path could not be resolved!!"))))) + + +(define (sretrieve:shell-less-cmd base-pathlist ext-path top-areas base-path) + (let* ((resolved-path (sauth-common:resolve-path ext-path base-pathlist top-areas ))) + (if (not (equal? resolved-path #f)) + (if (null? resolved-path) + (print "Path could not be resolved!!") + (let* ((target-path (sauth-common:get-target-path base-pathlist ext-path top-areas base-path))) + (if (not (equal? target-path #f)) + (if (or (not (file-exists? target-path)) (directory? target-path)) + (print "Target path does not exist or is a directory!") + (begin + ;(sretrieve:shell-db-do + ; db-location + ; (lambda (db) + ; (sretrieve:register-action db "less" (current-user-name) target-path (conc "Executing cmd: less " target-path)))) + + (setenv "LESSSECURE" "1") + (run (pipe + (less ,target-path)))))))) + (print "Path could not be resolved!!")))) + + + +(define (sretrieve:shell-lookup base-path) + (let* ((usr (current-user-name)) + (value (get-restrictions base-path usr))) + value)) + + +(define (sretrieve:load-shell-config fname) + (if (file-exists? fname) + (read-config fname #f #f) + )) + + +(define (is_directory target-path) + (let* ((retval #f)) + (sretrieve:do-as-calling-user + (lambda () + ;(print (current-effective-user-id) ) + (if (directory? target-path) + (set! retval #t)))) + ;(print (current-effective-user-id)) + retval)) + +(define (make-exclude-pattern restriction-list ) + (if (null? restriction-list) + "" + (let loop ((hed (car restriction-list)) + (tal (cdr restriction-list)) + (ret-str "")) + (cond + ((null? tal) + (conc ret-str ".+" hed ".*")) + (else + (loop (car tal)(cdr tal)(conc ret-str ".+" hed ".*|")))))) ) + +(define (sretrieve:get-shell-cmd target-path base-path restrictions iport) + (if (not (file-exists? target-path)) + (sauth:print-error "Target path does not exist!") + (begin + (if (not (equal? target-path #f)) + (begin + (if (is_directory target-path) + (begin + (let* ((tmpfile (conc "/tmp/" (current-user-name) "/my-pipe")) + (parent-dir target-path) + (last-dir-name (if (pathname-extension target-path) + (conc(pathname-file target-path) "." (pathname-extension target-path)) + (pathname-file target-path))) + (curr-dir (current-directory)) + (start-dir (conc (current-directory) "/" last-dir-name)) + (execlude (make-exclude-pattern (string-split restrictions ",")))) + ; (print tmpfile) + (if (file-exists? start-dir) + (begin + (print last-dir-name " already exist in your work dir. Do you want to over write it? [y|n]") + (let* ((inl (read-line iport))) + (if (equal? inl "y") + (begin + (change-directory parent-dir) + (create-fifo tmpfile) + (process-fork + (lambda() + (sleep 1) + (with-output-to-file tmpfile + (lambda () + (sretrieve:make_file parent-dir execlude parent-dir))))) + + (run (pipe + (tar "chfv" "-" "-T" ,tmpfile ) + (begin (system (conc "cd " start-dir ";tar xUf - " ))))) + (change-directory curr-dir) + (system (conc "rm " tmpfile)) ) + (begin + (print "Nothing has been retrieved!! "))))) + (begin + (sretrieve:do-as-calling-user + (lambda () + (create-directory start-dir #t))) + (change-directory parent-dir) + ; (print execlude) + (create-fifo tmpfile) + (process-fork + (lambda() + (sleep 1) + (with-output-to-file tmpfile + (lambda () + (sretrieve:make_file parent-dir execlude parent-dir))))) + + (run (pipe + (tar "chfv" "-" "-T" ,tmpfile) + (begin (system (conc "cd " start-dir ";tar xUf - " ))))) + (change-directory curr-dir) + (system (conc "rm " tmpfile)))))) + (begin + (let*((parent-dir (pathname-directory target-path)) + (start-dir (current-directory)) + (filename (if (pathname-extension target-path) + (conc(pathname-file target-path) "." (pathname-extension target-path)) + (pathname-file target-path))) + (work-dir-file (conc (current-directory) "/" filename))) + (if (file-exists? work-dir-file) + (begin + (print filename " already exist in your work dir. Do you want to over write it? [y|n]") + (let* ((inl (read-line iport))) + (if (equal? inl "y") + (begin + (change-directory parent-dir) + (run (pipe + (tar "chfv" "-" ,filename) + (begin (system (conc "cd " start-dir ";tar xUf - " ))))) + (change-directory start-dir)) + (begin + (print "Nothing has been retrieved!! "))))) + (begin + (change-directory parent-dir) + (run (pipe + (tar "chfv" "-" ,filename) + (begin (system (conc "cd " start-dir ";tar xUf -"))))) + (change-directory start-dir))))))))))) + +(define (sretrieve:get-shell-cmd-line target-path base-path restrictions iport) + (handle-exceptions + exn + (begin + (sauth:print-error (conc "Problem fetching the data. Sauth provieds sudo access to only one unix group. Please ensure you have washed all the remaining groups. System Error: " + ((condition-property-accessor 'exn 'message) exn))) + (exit 1)) + + (if (not (file-exists? target-path)) + (sauth:print-error "Error:Target path does not exist!") + (begin + (if (not (equal? target-path #f)) + (begin + (if (is_directory target-path) + (begin + (let* ((parent-dir target-path) + (last-dir-name (if (pathname-extension target-path) + (conc(pathname-file target-path) "." (pathname-extension target-path)) + (pathname-file target-path))) + (curr-dir (current-directory)) + (start-dir (conc (current-directory) "/" last-dir-name)) + (execlude (make-exclude-pattern (string-split restrictions ","))) + (tmpfile (conc "/tmp/" (current-user-name) "/my-pipe-" (current-process-id)))) + (if (file-exists? start-dir) + (begin + (sauth:print-error (conclast-dir-name " already exist in your work dir.")) + (sauth:print-error "Nothing has been retrieved!! ")) + (begin + ; (sretrieve:do-as-calling-user + ; (lambda () + + (if (not (file-exists? (conc "/tmp/" (current-user-name)))) + (create-directory (conc "/tmp/" (current-user-name)) #t)) + (change-directory parent-dir) + (create-fifo tmpfile) + (process-fork + (lambda() + (sleep 1) + (with-output-to-file tmpfile + (lambda () + (sretrieve:make_file parent-dir execlude parent-dir))))) + + (process-execute "/bin/tar" (append (list "chfv" "-" "-T" tmpfile) (list "--ignore-failed-read"))) + ;(run (pipe + ;(tar "chfv" "-" "." ) + ;(begin (system (conc "cd " start-dir ";tar xUf - " execlude ))))) + (system (conc "rm " tmpfile)) + (change-directory curr-dir))))) + (begin + (let*((parent-dir (pathname-directory target-path)) + (start-dir (current-directory)) + (filename (if (pathname-extension target-path) + (conc(pathname-file target-path) "." (pathname-extension target-path)) + (pathname-file target-path))) + (work-dir-file (conc (current-directory) "/" filename))) + (if (file-exists? work-dir-file) + (begin + (print filename " already exist in your work dir.") + (print "Nothing has been retrieved!! ")) + (begin + (change-directory parent-dir) + (process-execute "/bin/tar" (append (append (list "chfv" "-") (list filename)) (list "--ignore-failed-read"))) + ;(run (pipe + ; (tar "chfv" "-" ,filename) + ; (begin (system (conc "cd " start-dir ";tar xUf -"))))) + (change-directory start-dir)))))))))))) + +(define (sretrieve:make_file path exclude base_path) + (find-files + path + action: (lambda (p res) + (cond + ((symbolic-link? p) + (if (directory?(read-symbolic-link p)) + (sretrieve:make_file p exclude base_path) + (print (string-substitute (conc base_path "/") "" p "-")))) + ((directory? p) + ;;do nothing for dirs) + ) + (else + + (if (not (string-match (regexp exclude) p )) + (print (string-substitute (conc base_path "/") "" p "-")))))))) + +(define (sretrieve:shell-help) +(conc "Usage: " *exe-name* " [action [params ...]] + + ls [target path] : list contents of target area. The output of the cmd can be piped into other system cmd. eg ls | grep txt + cd : To change the current directory within the sretrive shell. + pwd : Prints the full pathname of the current directory within the sretrive shell. + get : download directory/files into the directory where sretrieve shell cmd was invoked + less : Read input file to allows backward movement in the file as well as forward movement + cat : show the contents of a file. The output of the cmd can be piped into other system cmd. + + sgrep [options] : Similar to unix grep cmd But with diffrent parameter ordering. The output of the cmd can be piped into other system cmd. +Part of the Megatest tool suite. +Learn more at http://www.kiatoa.com/fossils/megatest + +Version: " megatest-fossil-hash) +) +;(define (toplevel-command . args) #f) +(define (sretrieve:shell area) + ; (print area) (use readline) (let* ((path '()) - (prompt "> ") - (top-areas '("mrwellan" "pjhatwal" "bjbarcla" "ritikaag" "jmoon18")) + (prompt "sretrieve> ") + (args (argv)) + (usr (current-user-name) ) + (top-areas (sretrieve:get-accessable-projects area)) + (close-port #f) + (area-obj (get-obj-by-code area)) + (user-obj (get-user usr)) + (base-path (if (null? area-obj) + "" + (caddr (cdr area-obj)))) (iport (make-readline-port prompt))) - (install-history-file) ;; [homedir] [filename] [nlines]) - (with-input-from-port iport - (lambda () - (let loop ((inl (read-line))) - (if (not (or (eof-object? inl) - (equal? inl "exit"))) + (if (null? area-obj) + (begin + (print "Area " area " does not exist") + (exit 1))) + (let loop ((inl (read-line iport))) + ;(print 1) + (if (not (or (or (eof-object? inl) + (equal? inl "exit")) (port-closed? iport))) (let* ((parts (string-split inl)) (cmd (if (null? parts) #f (car parts)))) - (if (not cmd) + ; (print "2") + (if (and (not cmd) (not (port-closed? iport))) (loop (read-line)) (case (string->symbol cmd) ((cd) (if (> (length parts) 1) ;; have a parameter - (set! path (append path (string-split (cadr parts)))) ;; not correct for relative paths - (set! path '()))) + (begin + (let*((arg (cadr parts)) + (resolved-path (sauth-common:resolve-path arg path top-areas)) + (target-path (sauth-common:get-target-path path arg top-areas base-path))) + (if (not (equal? target-path #f)) + (if (or (equal? resolved-path #f) (not (file-exists? target-path))) + (print "Invalid argument " arg ".. ") + (begin + (set! path resolved-path) + (sauthorize:do-as-calling-user + (lambda () + (run-cmd (conc *sauth-path* "/sauthorize") (list "register-log" (conc "\"" inl "\"") (number->string (car user-obj)) (number->string (caddr area-obj)) "cd")))) + ))))) + (set! path '()))) + ((pwd) + (if (null? path) + (print "/") + (print "/" (string-join path "/")))) ((ls) (let* ((thepath (if (> (length parts) 1) ;; have a parameter (cdr parts) - path)) + `())) + (plen (length thepath))) + (cond + ((null? thepath) + (sauth-common:shell-ls-cmd path "" top-areas base-path '()) + (sauthorize:do-as-calling-user + (lambda () + (run-cmd (conc *sauth-path* "/sauthorize") (list "register-log" (conc "\"" inl "\"") (number->string (car user-obj)) (number->string (caddr area-obj)) "ls")))) ) + ((< plen 2) + + (sauth-common:shell-ls-cmd path (car thepath) top-areas base-path '()) + (sauthorize:do-as-calling-user + (lambda () + (run-cmd (conc *sauth-path* "/sauthorize") (list "register-log" (conc "\"" inl "\"") (number->string (car user-obj)) (number->string (caddr area-obj)) "ls"))))) + (else + (if (equal? (car thepath) "|") + (sauth-common:shell-ls-cmd path "" top-areas base-path thepath) + (sauth-common:shell-ls-cmd path (car thepath) top-areas base-path (cdr thepath))) + (sauthorize:do-as-calling-user + (lambda () + (run-cmd (conc *sauth-path* "/sauthorize") (list "register-log" (conc "\"" inl "\"") (number->string (car user-obj)) (number->string (caddr area-obj)) "ls")))))))) + ((cat) + (let* ((thepath (if (> (length parts) 1) ;; have a parameter + (cdr parts) + `())) + (plen (length thepath))) + (cond + ((null? thepath) + (print "Error: Missing argument to cat")) + ((< plen 2) + (sretrieve:shell-cat-cmd path (car thepath) top-areas base-path '()) + (sauthorize:do-as-calling-user + (lambda () + (run-cmd (conc *sauth-path* "/sauthorize") (list "register-log" (conc "\"" inl "\"") (number->string (car user-obj)) (number->string (caddr area-obj)) "cat"))))) + + (else + (sretrieve:shell-cat-cmd path (car thepath) top-areas base-path (cdr thepath)) + (sauthorize:do-as-calling-user + (lambda () + (run-cmd (conc *sauth-path* "/sauthorize") (list "register-log" (conc "\"" inl "\"") (number->string (car user-obj)) (number->string (caddr area-obj)) "cat")))) +)))) + ((sgrep) + (let* ((thepath (if (> (length parts) 1) ;; have a parameter + (cdr parts) + `())) + (plen (length thepath))) + (cond + ((null? thepath) + (print "Error: Missing arguments to grep!! Useage: grep [options] ")) + ((< plen 2) + (print "Error: Missing arguments to grep!! Useage: grep [options] ")) + (else + (sretrieve:shell-grep-cmd path (car thepath) top-areas base-path (cdr thepath)) + (sauthorize:do-as-calling-user + (lambda () + (run-cmd (conc *sauth-path* "/sauthorize") (list "register-log" (conc "\"" inl "\"") (number->string (car user-obj)) (number->string (caddr area-obj)) "grep")))))))) + + ((less) + (let* ((thepath (if (> (length parts) 1) ;; have a parameter + (cdr parts) + `())) + (plen (length thepath))) + (cond + ((null? thepath) + (print "Error: Missing argument to less")) + ((< plen 2) + (sretrieve:shell-less-cmd path (car thepath) top-areas base-path) + (sauthorize:do-as-calling-user + (lambda () + (run-cmd (conc *sauth-path* "/sauthorize") (list "register-log" (conc "\"" inl "\"") (number->string (car user-obj)) (number->string (caddr area-obj)) "less"))))) + (else + (print "less cmd takes only one () argument!!"))))) + ((get) + (let* ((thepath (if (> (length parts) 1) ;; have a parameter + (cdr parts) + `())) (plen (length thepath))) (cond ((null? thepath) - (print (string-intersperse top-areas " "))) - ((and (< plen 2) - (member (car thepath) top-areas)) - (system (conc "ls /p/fdk/gwa/" (car thepath)))) - (else ;; have a long path - ;; check for access rights here - (system (conc "ls /p/fdk/gwa/" (string-intersperse thepath "/"))))))) + (print "Error: Missing argument to get")) + ((< plen 2) + (let* ((target-path (sauth-common:get-target-path path (car thepath) top-areas base-path)) + (restrictions (if (equal? target-path #f) + "" + (sretrieve:shell-lookup base-path)))) + (if (not (equal? target-path #f)) + (begin + (sretrieve:get-shell-cmd target-path base-path restrictions iport) + (sauthorize:do-as-calling-user + (lambda () + (run-cmd (conc *sauth-path* "/sauthorize") (list "register-log" (conc "\"" inl "\"") (number->string (car user-obj)) (number->string (caddr area-obj)) "get")))))))) + (else + (print "Error: get cmd takes only one argument "))))) + ((exit) + (print "got exit")) + ((help) + (print (sretrieve:shell-help))) (else (print "Got command: " inl)))) - (loop (read-line))))))))) + (loop (read-line iport))))))) +;;)) ;;====================================================================== ;; MAIN ;;====================================================================== - -(define (sretrieve:load-config exe-dir exe-name) - (let* ((fname (conc exe-dir "/." exe-name ".config"))) - ;; (ini:property-separator-patt " * *") - ;; (ini:property-separator #\space) - (if (file-exists? fname) - ;; (ini:read-ini fname) - (read-config fname #f #t) - (make-hash-table)))) +;;(define *default-log-port* (current-error-port)) + +;(define (sretrieve:load-config exe-dir exe-name) +; (let* ((fname (conc exe-dir "/." exe-name ".config"))) +; ;; (ini:property-separator-patt " * *") +; ;; (ini:property-separator #\space) +; (if (file-exists? fname) +; ;; (ini:read-ini fname) +; (read-config fname #f #f) +; (make-hash-table)))) ;; package-type is "megatest", "builds", "kits" etc. ;; -(define (sretrieve:load-packages configdat exe-dir package-type) - (push-directory exe-dir) - (let* ((packages-metadir (configf:lookup configdat "settings" "packages-metadir")) - (conversion-script (configf:lookup configdat "settings" "conversion-script")) - (upstream-file (configf:lookup configdat "settings" "upstream-file")) - (package-config (conc packages-metadir "/" package-type ".config"))) - ;; this section here does a timestamp based rebuild of the - ;; /.config file using - ;; as an input - (if (file-exists? upstream-file) - (if (or (not (file-exists? package-config)) ;; if not created call the updater, otherwise call only if upstream newer - (> (file-modification-time upstream-file)(file-modification-time package-config))) - (handle-exceptions - exn - (debug:print-error 0 *default-log-port* "failed to run script " conversion-script " with params " upstream-file " " package-config) - (let ((pid (process-run conversion-script (list upstream-file package-config)))) - (process-wait pid))) - (debug:print 0 *default-log-port* "Skipping update of " package-config " from " upstream-file)) - (debug:print 0 *default-log-port* "Skipping update of " package-config " as " upstream-file " not found")) - ;; (ini:property-separator-patt " * *") - ;; (ini:property-separator #\space) - (let ((res (if (file-exists? package-config) - (begin - (debug:print 0 *default-log-port* "Reading package config " package-config) - (read-config package-config #f #t)) - (make-hash-table)))) - (pop-directory) - res))) - -(define (sretrieve:process-action configdat action . args) - (let* ((base-dir (configf:lookup configdat "settings" "base-dir")) - (user (current-user-name)) - (allowed-sub-paths (configf:lookup configdat "settings" "allowed-sub-paths")) - (allowed-users (string-split - (or (configf:lookup configdat "settings" "allowed-users") - ""))) - (default-area (configf:lookup configdat "settings" "default-area"))) ;; otherwise known as the package - - (if (not base-dir) - (begin - (debug:print 0 *default-log-port* "[settings]\nbase-dir /some/path\n\n Is MISSING from the config file!") - (exit))) - (if (null? allowed-users) - (begin - (debug:print 0 *default-log-port* "[setings]\nallowed-users user1 user2 ...\n\n Is MISSING from the config file!") - (exit))) - (if (not (member user allowed-users)) - (begin - (debug:print 0 *default-log-port* "User \"" (current-user-name) "\" does not have access. Exiting") - (exit 1))) + +;(define (sretrieve:load-packages configdat exe-dir package-type) +; (push-directory exe-dir) +; (let* ((packages-metadir (configf:lookup configdat "settings" "packages-metadir")) +; (conversion-script (configf:lookup configdat "settings" "conversion-script")) +; (upstream-file (configf:lookup configdat "settings" "upstream-file")) +; (package-config (conc packages-metadir "/" package-type ".config"))) +; (if (file-exists? upstream-file) +; (if (or (not (file-exists? package-config)) ;; if not created call the updater, otherwise call only if upstream newer +; (> (file-modification-time upstream-file)(file-modification-time package-config))) +; (handle-exceptions +; exn +; (debug:print 0 "ERROR: failed to run script " conversion-script " with params " upstream-file " " package-config) +; (let ((pid (process-run conversion-script (list upstream-file package-config)))) +; (process-wait pid))) +; (debug:print 0 "Skipping update of " package-config " from " upstream-file)) +; (debug:print 0 "Skipping update of " package-config " as " upstream-file " not found")) +; (let ((res (if (file-exists? package-config) +; (begin +; (debug:print 0 "Reading package config " package-config) +; (read-config package-config #f #t)) +; (make-hash-table)))) +; (pop-directory) +; res))) + +(define (toplevel-command . args) #f) +(define (sretrieve:process-action action . args) + ; (print action) + ; (use readline) (case (string->symbol action) ((get) - (if (< (length args) 1) - (begin - (debug:print-error 0 *default-log-port* "Missing arguments; " (string-intersperse args ", ")) - (exit 1))) - (let* ((remargs (args:get-args args '("-m" "-i" "-package") '() args:arg-hash 0)) - (version (car args)) - (msg (or (args:get-arg "-m") "")) - (package-type (or (args:get-arg "-package") - default-area)) - (exe-dir (configf:lookup configdat "exe-info" "exe-dir"))) -;; (relconfig (sretrieve:load-packages configdat exe-dir package-type))) - - (debug:print 0 *default-log-port* "retrieving " version " of " package-type " as tar data on stdout") - (sretrieve:get configdat user version msg))) - ((cp) - (if (< (length args) 1) - (begin - (debug:print-error 0 *default-log-port* "Missing arguments; " (string-intersperse args ", ")) - (exit 1))) - (let* ((remargs (args:get-args args '("-m" "-i" "-package") '() args:arg-hash 0)) - (file (car args)) - (msg (or (args:get-arg "-m") "")) ) - - (debug:print 0 *default-log-port* "copinging " file " to current directory " ) - (sretrieve:cp configdat user file msg))) - ((ls) - (if (< (length args) 1) - (begin - (debug:print-error 0 *default-log-port* "Missing arguments; " (string-intersperse args ", ")) - (exit 1))) - (let* ((remargs (args:get-args args '("-m" "-i" "-package") '() args:arg-hash 0)) - (dir (car args)) - (msg (or (args:get-arg "-m") "")) ) - - (debug:print 0 *default-log-port* "Listing files in " ) - (sretrieve:ls configdat user dir msg))) - - (else (debug:print 0 *default-log-port* "Unrecognised command " action))))) - -;; ease debugging by loading ~/.dashboardrc - REMOVE FROM PRODUCTION! -;; (let ((debugcontrolf (conc (get-environment-variable "HOME") "/.sretrieverc"))) -;; (if (file-exists? debugcontrolf) -;; (load debugcontrolf))) + (if (< (length args) 2) + (begin + (sauth:print-error "Missing arguments; " ) + (exit 1))) + (let* ((remargs (args:get-args args '("-m" ) '() args:arg-hash 0)) + (iport (make-readline-port ">")) + (area (car args)) + (usr (current-user-name)) + (area-obj (get-obj-by-code area)) + (user-obj (get-user usr)) + (top-areas (sretrieve:get-accessable-projects area)) + (base-path (if (null? area-obj) + "" + (caddr (cdr area-obj)))) + (sub-path (if (null? remargs) + "" + (car remargs)))) + + (if (null? area-obj) + (begin + (sauth:print-error (conc "Area " area " does not exist")) + (exit 1))) + (let* ((target-path (sauth-common:get-target-path '() (conc area "/" sub-path) top-areas base-path)) + (restrictions (if (equal? target-path #f) + "" + (sretrieve:shell-lookup base-path)))) + (if (not (equal? target-path #f)) + (begin + (sauthorize:do-as-calling-user + (lambda () + (run-cmd (conc *sauth-path* "/sauthorize") (list "register-log" (conc "get " area " " sub-path) (number->string (car user-obj)) (number->string (caddr area-obj)) "get")))) + (sretrieve:get-shell-cmd-line target-path base-path restrictions iport)))))) + ((cp) + (if (< (length args) 2) + (begin + (sauth:print-error "Missing arguments; " ) + (exit 1))) + (let* ((remargs (args:get-args args '("-m" ) '() args:arg-hash 0)) + (iport (make-readline-port ">")) + (area (car args)) + (usr (current-user-name)) + (area-obj (get-obj-by-code area)) + (user-obj (get-user usr)) + (top-areas (sretrieve:get-accessable-projects area)) + (base-path (if (null? area-obj) + "" + (caddr (cdr area-obj)))) + (sub-path (if (null? remargs) + "" + (car remargs)))) + ; (print args) + (if (null? area-obj) + (begin + (sauth:print-error (conc "Area " area " does not exist")) + (exit 1))) + (let* ((target-path (sauth-common:get-target-path '() (conc area "/" sub-path) top-areas base-path)) + (restrictions (if (equal? target-path #f) + "" + (sretrieve:shell-lookup base-path)))) + ;(print target-path) + (if (not (equal? target-path #f)) + (begin + (sauthorize:do-as-calling-user + (lambda () + (run-cmd (conc *sauth-path* "/sauthorize") (list "register-log" (conc "get " area " " sub-path) (number->string (car user-obj)) (number->string (caddr area-obj)) "get")))) + (sretrieve:get-shell-cmd-line target-path base-path restrictions iport)))))) + ((ls) + (cond + ((< (length args) 1) + (begin + (print "ERROR: Missing arguments; ") + (exit 1))) + ((equal? (length args) 1) + (let* ((area (car args)) + (usr (current-user-name)) + (area-obj (get-obj-by-code area)) + (user-obj (get-user usr)) + (top-areas (sretrieve:get-accessable-projects area)) + (base-path (if (null? area-obj) + "" + (caddr (cdr area-obj))))) + (if (null? area-obj) + (begin + (print "Area " area " does not exist") + (exit 1))) + (sauth-common:shell-ls-cmd '() area top-areas base-path '()) + (sauthorize:do-as-calling-user + (lambda () + (run-cmd (conc *sauth-path* "/sauthorize") (list "register-log" "ls" (number->string (car user-obj)) (number->string (caddr area-obj)) "ls")))))) + ((> (length args) 1) + (let* ((remargs (args:get-args args '("-m" ) '() args:arg-hash 0)) + (usr (current-user-name)) + (user-obj (get-user usr)) + (area (car args))) + (let* ((area-obj (get-obj-by-code area)) + (top-areas (sretrieve:get-accessable-projects area)) + (base-path (if (null? area-obj) + "" + (caddr (cdr area-obj)))) + + (sub-path (if (null? remargs) + area + (conc area "/" (car remargs))))) + ;(print "sub path " sub-path) + (if (null? area-obj) + (begin + (print "Area " area " does not exist") + (exit 1))) + (sauth-common:shell-ls-cmd `() sub-path top-areas base-path '()) + (sauthorize:do-as-calling-user + (lambda () + (run-cmd (conc *sauth-path* "/sauthorize") (list "register-log" (conc "ls " sub-path) (number->string (car user-obj)) (number->string (caddr area-obj)) "ls"))))))))) + + ((shell) + (if (< (length args) 1) + (begin + (print "ERROR: Missing arguments !!" ) + (exit 1)) + (sretrieve:shell (car args)))) + (else (print 0 "Unrecognised command " action)))) (define (main) (let* ((args (argv)) (prog (car args)) (rema (cdr args)) (exe-name (pathname-file (car (argv)))) (exe-dir (or (pathname-directory prog) (sretrieve:find exe-name (string-split (get-environment-variable "PATH") ":")))) - (configdat (sretrieve:load-config exe-dir exe-name))) + ;(configdat (sretrieve:load-config exe-dir exe-name)) +) ;; preserve the exe data in the config file - (hash-table-set! configdat "exe-info" (list (list "exe-name" exe-name) - (list "exe-dir" exe-dir))) + ;(hash-table-set! configdat "exe-info" (list (list "exe-name" exe-name) + ; (list "exe-dir" exe-dir))) (cond ;; one-word commands ((eq? (length rema) 1) (case (string->symbol (car rema)) ((help -h -help --h --help) (print sretrieve:help)) - ((list-vars) ;; print out the ini file - (map print (sretrieve:get-areas configdat))) - ((ls) - (let* ((base-dir (configf:lookup configdat "settings" "base-dir"))) - (if base-dir - (begin - (print "Files in " base-dir) - (sretrieve:do-as-calling-user - (lambda () - (process-execute "/bin/ls" (list "-lrt" base-dir))))) - (print "ERROR: No base dir specified!")))) - ((log) - (sretrieve:db-do configdat (lambda (db) - (print "Logs : ") - (query (for-each-row - (lambda (row) - (apply print (intersperse row " | ")))) - (sql db "SELECT * FROM actions"))))) - ((shell) - (sretrieve:shell)) (else (print "ERROR: Unrecognised command. Try \"sretrieve help\"")))) ;; multi-word commands ((null? rema)(print sretrieve:help)) ((>= (length rema) 2) - (apply sretrieve:process-action configdat (car rema)(cdr rema))) - (else (debug:print-error 0 *default-log-port* "Unrecognised command. Try \"sretrieve help\""))))) + + (apply sretrieve:process-action (car rema) (cdr rema))) + (else (debug:print 0 "ERROR: Unrecognised command. Try \"sretrieve help\""))))) (main) + + + Index: tests.scm ================================================================== --- tests.scm +++ tests.scm @@ -31,10 +31,12 @@ (include "common_records.scm") (include "key_records.scm") (include "db_records.scm") (include "run_records.scm") (include "test_records.scm") +(include "js-path.scm") + ;; Call this one to do all the work and get a standardized list of tests ;; gets paths from configs and finds valid tests ;; returns hash of testname --> fullpath ;; @@ -583,13 +585,11 @@ .HandCursorStyle { cursor: pointer; cursor: hand; } /* For IE */ th {background-color: #8c8c8c;} td.test {background-color: #d9dbdd;} td.PASS {background-color: #347533;} td.FAIL {background-color: #cc2812;} - - - + EOF ) +(define tests:css-jscript-block-dynamic +#< +EOF +) + +(define (test:js-block javascript-lib) + (conc "" )) + + +(define tests:css-jscript-block-static (test:js-block *java-script-lib*)) + +(define (tests:css-jscript-block-cond dynamic) + (if (equal? dynamic #t) + tests:css-jscript-block-dynamic + tests:css-jscript-block-static)) + + (define (tests:run-record->test-path run numkeys) (append (take (vector->list run) numkeys) (list (vector-ref run (+ 1 numkeys))))) @@ -711,55 +729,31 @@ (hash-table-set! (hash-table-ref/default (hash-table-ref/default resh test-name #f) test-item #f) run-id (list test-status test-html-path)))) test-data))) runs) resh)) -;; (tests:create-html-tree "test-index.html") +;; tests:genrate dashboard body ;; -(define (tests:create-html-tree outf) - (let* ((lockfile (conc outf ".lock")) - (runs-to-process '()) - (linktree (common:get-linktree)) - (area-name (common:get-testsuite-name)) - (keys (rmt:get-keys)) - (numkeys (length keys)) - (total-runs (rmt:get-num-runs "%")) - (pg-size 10) ) - (if (common:simple-file-lock lockfile) - (begin - (print total-runs) - (let loop ((page 0)) - (let* ((oup (open-output-file (or outf (conc linktree "/page" page ".html")))) - (start (* page pg-size)) + +(define (tests:dashboard-body page pg-size keys numkeys total-runs linktree area-name get-prev-links get-next-links flag) + (let* ((start (* page pg-size)) (runsdat (rmt:get-runs "%" pg-size start (map (lambda (x)(list x "%")) keys))) (header (vector-ref runsdat 0)) (runs (vector-ref runsdat 1)) (ctr 0) (test-runs-hash (tests:get-rest-data runs header numkeys)) (test-list (hash-table-keys test-runs-hash)) - (get-prev-links (lambda (page linktree ) - (let* ((link (if (not (eq? page 0)) - (s:a "<<prev" 'href (conc linktree "/page" (- page 1) ".html")) - (s:a "" 'href (conc linktree "/page" page ".html"))))) - link))) - (get-next-links (lambda (page linktree total-runs) - (let* ((link (if (> total-runs (+ 1 (* page pg-size))) - (s:a "next>>" 'href (conc linktree "/page" (+ page 1) ".html")) - (s:a "" 'href (conc linktree "/page" page ".html"))))) - link)))) - (s:output-new - oup - (s:html tests:css-jscript-block + ) + (s:html tests:css-jscript-block (tests:css-jscript-block-cond flag) (s:title "Summary for " area-name) (s:body 'onload "addEvents();" (get-prev-links page linktree) (get-next-links page linktree total-runs) (s:h1 "Summary for " area-name) (s:h3 "Filter" ) (s:input 'type "text" 'name "testname" 'id "testname" 'length "30" 'onkeyup "filtersome()") - ;; top list (s:table 'id "LinkedList1" 'border "1" (map (lambda (key) (let* ((res (s:tr 'class "something" (s:th key ) @@ -784,31 +778,134 @@ (map (lambda (run) (let* ((run-test (hash-table-ref/default item-hash item-name #f)) (run-id (db:get-value-by-header run header "id")) (result (hash-table-ref/default run-test run-id "n/a")) (status (if (string? result) - (begin - ; (print "string" result) - result) - (begin - ; (print "not string" result ) - (car result))))) - (s:td status 'class status))) + result + (car result))) + (link (if (string? result) + result + (if (equal? flag #t) + (s:a (car result) 'href (conc "./test_log?runid=" run-id "&testname=" item-name )) + (s:a (car result) 'href (cadr result)))))) + (s:td link 'class status))) runs)))) res)) item-keys))) - test-list))))) + test-list)))))) + +;; (tests:create-html-tree "test-index.html") +;; +(define (tests:create-html-tree outf) + (let* ((lockfile (conc outf ".lock")) + (runs-to-process '()) + (linktree (common:get-linktree)) + (area-name (common:get-testsuite-name)) + (keys (rmt:get-keys)) + (numkeys (length keys)) + (total-runs (rmt:get-num-runs "%")) + (pg-size 10)) + (if (common:simple-file-lock lockfile) + (begin + ;(print total-runs) + (let loop ((page 0)) + (let* ((oup (open-output-file (or outf (conc linktree "/page" page ".html")))) + (get-prev-links (lambda (page linktree ) + (let* ((link (if (not (eq? page 0)) + (s:a "<<prev" 'href (conc linktree "/page" (- page 1) ".html")) + (s:a "" 'href (conc linktree "/page" page ".html"))))) + link))) + (get-next-links (lambda (page linktree total-runs) + (let* ((link (if (> total-runs (+ 10 (* page pg-size))) + (s:a "next>>" 'href (conc linktree "/page" (+ page 1) ".html")) + (s:a "" 'href (conc linktree "/page" page ".html"))))) + link))) ) + ;(print (tests:dashboard-body page pg-size keys numkeys total-runs linktree area-name)) + (s:output-new + oup + (tests:dashboard-body page pg-size keys numkeys total-runs linktree area-name get-prev-links get-next-links #f)) (close-output-port oup) ; (set! page (+ 1 page)) (if (> total-runs (* (+ 1 page) pg-size)) (loop (+ 1 page))))) (common:simple-file-release-lock lockfile)) #f))) +(define (tests:readlines filename) + (call-with-input-file filename + (lambda (p) + (let loop ((line (read-line p)) + (result '())) + (if (eof-object? line) + (reverse result) + (loop (read-line p) (cons line result))))))) + +(define (tests:get-test-log run-id test-name item-name) + (let* ((test-data (rmt:get-tests-for-run + (string->number run-id) + test-name ;; testnamepatt + '() ;; states + '() ;; statuses + #f ;; offset + #f ;; num-to-get + #f ;; hide/not-hide + #f ;; sort-by + #f ;; sort-order + #f ;; 'shortlist ;; qrytype + 0 ;; last update + #f)) + (path "") + (found 0)) + (debug:print-info 0 *default-log-port* "found: " found ) + + (let loop ((hed (car test-data)) + (tal (cdr test-data))) + (debug:print-info 0 *default-log-port* "item: " (vector-ref hed 11) (vector-ref hed 10) "/" (vector-ref hed 13)) + + (if (equal? (vector-ref hed 11) item-name) + (begin + (set! found 1) + (set! path (conc (vector-ref hed 10) "/" (vector-ref hed 13))))) + (if (and (not (null? tal)) (equal? found 0)) + (loop (car tal)(cdr tal)))) + (if (equal? path "") + "

Data not found

" + (string-join (tests:readlines path) "\n")))) + +(define (tests:dynamic-dboard page) +;(define (tests:create-html-tree o) + (let* ( +;(page "1") + (linktree (common:get-linktree)) + (area-name (common:get-testsuite-name)) + (keys (rmt:get-keys)) + (numkeys (length keys)) + (total-runs (rmt:get-num-runs "%")) + (pg-size 10) + (pg (if (equal? page #f) + 0 + (- (string->number page) 1))) + (get-prev-links (lambda (pg linktree) + (debug:print-info 0 *default-log-port* "val: " (- 1 pg)) + (let* ((link (if (not (eq? pg 0)) + (s:a "<<prev " 'href (conc "dashboard?page=" pg )) + (s:a "" 'href (conc "dashboard?page=" pg))))) + link))) + (get-next-links (lambda (pg linktree total-runs) + (debug:print-info 0 *default-log-port* "val: " pg) + (debug:print-info 0 *default-log-port* "val: " total-runs " size" pg-size) + + (let* ((link (if (> total-runs (+ 10 (* pg pg-size))) + (s:a "next>> " 'href (conc "dashboard?page=" (+ pg 2) )) + (s:a "" 'href (conc "dashboard?page=" pg ))))) + link))) + (html-body (tests:dashboard-body pg pg-size keys numkeys total-runs linktree area-name get-prev-links get-next-links #t))) + ;(print (tests:dashboard-body page pg-size keys numkeys total-runs linktree area-name)) +html-body)) (define (tests:create-html-tree-old outf) (let* ((lockfile (conc outf ".lock"))