dataman.lzx

<library>
    <script src="md5.js"/>

    <!--
        GLOBALS
    -->
    <node id="gGlobals">
        <attribute name="SHAREDSECRET" type="string" value="b199acb45fd055e7"/>
        <attribute name="API_KEY" type="string" value="563a40afe6128e60145dd1e347911e54"/>
        <attribute name="RESTSRC" type="string" value="http://api.flickr.com/services/rest/"/>
    </node>
    
    <!--
        DATA MANAGER
    -->
    <node name="gDataMan">
        <handler name="oninit">
            this.errdel = new LzDelegate( this, "dsError" );
            this['errdel'].register( photods , "onerror" );
            this['errdel'].register( infods , "onerror" );
            this['errdel'].register( sizeds , "onerror" );
            this['errdel'].register( userds , "onerror" );
            this['errdel'].register( frobds , "onerror" );
            this['errdel'].register( tokends , "onerror" );

            this['errdel'].register( photods , "ontimeout" );
            this['errdel'].register( infods , "ontimeout" );
            this['errdel'].register( sizeds , "ontimeout" );
            this['errdel'].register( userds , "ontimeout" );
            this['errdel'].register( frobds , "ontimeout" );
            this['errdel'].register( tokends, "ontimeout" );
        </handler>

        <method name="dsError" args="v">
            this['gError'].show();
        </method>
        
        <!-- 
            builds, signs and sends authenticated FlickrRequest 
            results go in provided dataset
            
            app *must* have called doAuth() and doToken() before trying to call doAuthFilterRequest()
            
            REQUIRED ARG - ds - dataset to make call with
            REQUIRED ARG - argobjarr - array of objects {argname:[name], argvalue:[value]}
            
            SUPPORTS ALL  METHODS DESCRIBED IN FLICKR SERVICES API THAT REQUIRE AUTHENTICATION
            http://www.flickr.com/services/api/
        -->
        <method name="doAuthFlickrRequest" args="ds, argobjarr">
            
            var token=tokends.getPointer().xpathQuery("rsp/auth/token/text()");
            argobjarr.push(
                {argname:"auth_token", 
                argvalue:token} );
                
            doFlickrRequest(ds, argobjarr);
            
        </method>

        <!-- 
            builds, signs and sends FlickrRequest 
            results go in provided dataset
            
            REQUIRED ARG - ds - dataset to make call with
            REQUIRED ARG - argobjarr - array of objects {argname:[name], argvalue:[value]}
            
            SUPPORTS ALL METHODS DESCRIBED IN FLICKR SERVICES API
            http://www.flickr.com/services/api/
        -->
        <method name="doFlickrRequest" args="ds, argobjarr">
            
            // clear query params
            ds.setQueryParams(null);

            // string to start building sig
            var api_sig_string=gGlobals.SHAREDSECRET;

            // set source
            ds.setAttribute('src', gGlobals.RESTSRC);

            // add api_key
            argobjarr.push({argname:"api_key", argvalue:gGlobals.API_KEY});
            
            // alphabetize argobjs comparator
            var argcomparator = function (a, b) {
                if (a.argname < b.argname) return -1;
                if (a.argname > b.argname) return 1;
                return 0
            }
            argobjarr.sort(argcomparator)

            // build argobject
            for (var i=0;i<argobjarr.length;i++) 
            {
                var argobj=argobjarr[i];

                // set query param
                ds.setQueryParam(argobj.argname, argobj.argvalue);

                // buid api_sig_string
                api_sig_string+=argobj.argname+argobj.argvalue                

            }


            // sign call
            var api_sig = hex_md5(api_sig_string);                
            ds.setQueryParam("api_sig", api_sig);

            // make actual request
            ds.doRequest();
            
        </method>

        <!-- 
             authenticate if necessary but not if already authenticated 
             
             PUBLIC AUTH FUNCTIONS 
        -->
        <method name="doAuth">
            _getFrob();
        </method>

        <!-- renew token after successful out-of-app authentication -->
        <method name="doToken">
            var frob = frobds.getPointer().xpathQuery("rsp/frob/text()");
            var argobj = [{argname:"method",argvalue:"flickr.auth.getToken"},
                          {argname:"frob",argvalue:frob}];
            this.doFlickrRequest(tokends, argobj);            
        </method>

        <!-- 
             PRIVATE AUTH HANDLERS
        -->
        <method name="_getFrob">
            var argobj = [{argname:"method",argvalue:"flickr.auth.getFrob"}];
            this.doFlickrRequest(frobds, argobj);            
        </method>
        <method name="_handleFrob">
            
            if (global['debugdata']) Debug.write("handle frob", frobds.serialize());
            var frob = frobds.getPointer().xpathQuery("rsp/frob/text()");

            // string to start building sig
            var api_sig_string=gGlobals.SHAREDSECRET;
            api_sig_string+="api_key"+gGlobals.API_KEY;
            api_sig_string+="frob"+frob;
            api_sig_string+="permswrite";            

            var sig=hex_md5(api_sig_string);

            // authenticate user
            var url="http://flickr.com/services/auth/?api_key="+gGlobals.API_KEY
            +"&perms=write&frob="+frob+"&api_sig="+sig;

            // TODO: possibly put up some UI here to note that out-of-app authentication will occur
            // then call doAuth() function again
            lz.Browser.loadURL(url, "_blank");
            
        </method>
        <method name="_handleToken">
            
            if (global['debugdata']) Debug.write("_handleToken", tokends);
            var stat=tokends.getPointer().xpathQuery("rsp/@stat");
            
        </method>

        <!-- Only search for photos with a creative commons license:
            http://creativecommons.org/licenses/by/2.0/
        -->
        <method name="loadPhotosByTag" args="tags">
            var argobj;
            if (tags == "interesting") {
                // Special search for interesting photos            
                argobj = [
                    {argname:"method", 
                        argvalue:"flickr.interestingness.getList"}
                ]            
            } else if (tags=="recent") {
                argobj = [
                    {argname:"method", 
                        argvalue:"flickr.photos.getRecent"}
                ]                        
            } else {
                // search by tags
                argobj = [
                    {argname:"method", argvalue:"flickr.photos.search"},
                    // Any Creative-Commons license (all include attribution)
                    {argname:"license", argvalue:"1,2,3,4,5,6"},
                    {argname:"tags", argvalue:tags},
                    {argname:"tag_mode", argvalue:"all"},
                    {argname:"sort", argvalue:"interestingness-desc"}
                ]
            } 

            header_txt.setAttribute('text', 'loading tags: ' + tags);

            this.doFlickrRequest(photods, argobj);                    
        </method>

        <method name="getPhotoURL" args="dp, suffix">
            
            var id=dp.p.getAttr("id");
            var suf = (suffix != '') ? "_"+suffix: "";

            // build URL to image
            var server=dp.p.getAttr("server");
            var secret=dp.p.getAttr("secret");
            var s="http://static.flickr.com/"+server+"/"+id+"_"+secret + suf + ".jpg";
            return s;
            
        </method>

        <!-- Load details for the photo  --> 
        <method name="loadPhotoDetails" args="photo_id">
            var argobj = [
                {argname:"method", 
                argvalue:"flickr.photos.getInfo"},
                {argname:"photo_id",
                argvalue: photo_id}
                ];
            this.doFlickrRequest(canvas.infods, argobj);             
            loadSizeInfo(photo_id);  
        </method>

        <!-- Load owner info --> 
        <method name="loadUserInfo" args="user_id">
            var argobj = [
                {argname:"method", 
                argvalue:"flickr.people.getInfo"},
                {argname:"user_id",
                argvalue: user_id}
                ];
            this.doFlickrRequest(canvas.userds, argobj);
        </method>
                    
        <!-- Load size info. --> 
        <method name="loadSizeInfo" args="photo_id">
            var argobj = [
                {argname:"method", 
                argvalue:"flickr.photos.getSizes"},
                {argname:"photo_id",
                argvalue: photo_id}
                ];
            gDataMan.doFlickrRequest(canvas.sizeds, argobj);
        </method>
    </node>

    <!-- ds to query for photos -->
    <dataset name="photods" ondata="if (global['debugdata']) Debug.write('got data', this)" type="http" cacheable="true"/>
    
    <!-- ds to query for photo info -->
    <dataset name="infods" ondata="if (global['debugdata']) Debug.write('got info', this)" type="http" cacheable="true"/>
    
    <!-- ds to store clipboard contents -->
    <dataset name="clipds"/>
    
    <!-- datapointer for setting up clipboard -->
    <datapointer name="clipDP" xpath="clipds:/" oninit="this.addNode('photos')"/>
    
    <!-- photo sizes -->
    <dataset name="sizeds" type="http" cacheable="true"/>
    
    <!-- ds to query for user info -->
    <dataset name="userds" ondata="if (global['debugdata']) Debug.write('got user', this)" cacheable="true"/>

    <!-- auth... -->
    <dataset name="frobds" type="http" ondata="gDataMan._handleFrob()"/>

    <!-- token for logged-in user -->
    <dataset name="tokends" type="http" ondata="gDataMan._handleToken()"/>

</library>
<!--
* X_LZ_COPYRIGHT_BEGIN ****************************************************
* Copyright 2006-2008 Laszlo Systems, Inc.  All Rights Reserved.          *
* Use is subject to license terms.                                        *
* X_LZ_COPYRIGHT_END ******************************************************-->

Cross References

Named Instances