From 5e474dd3a9e5a945acf7d2e76b930767225b5f20 Mon Sep 17 00:00:00 2001
From: Jesus Federico <jesus@123it.ca>
Date: Thu, 18 Jul 2013 15:16:21 -0400
Subject: [PATCH] bbb-lti: Added lti cartridge as response for GET request to
 tool.xml

---
 .../controllers/ToolController.groovy         | 139 +++++++++++-------
 bbb-lti/grails-app/services/LtiService.groovy |  21 ++-
 2 files changed, 109 insertions(+), 51 deletions(-)

diff --git a/bbb-lti/grails-app/controllers/ToolController.groovy b/bbb-lti/grails-app/controllers/ToolController.groovy
index b54dac6788..f8d93c3bd0 100644
--- a/bbb-lti/grails-app/controllers/ToolController.groovy
+++ b/bbb-lti/grails-app/controllers/ToolController.groovy
@@ -50,67 +50,73 @@ class ToolController {
         params.put(REQUEST_METHOD, request.getMethod().toUpperCase())
         log.debug "params: " + params
         
-        Map<String, String> result = new HashMap<String, String>()
-        ArrayList<String> missingParams = new ArrayList<String>()
-        log.debug "Checking for required parameters"
-        if (hasAllRequiredParams(params, missingParams)) {
-            def sanitizedParams = sanitizePrametersForBaseString(params)
-            def consumer = ltiService.getConsumer(params.get(Parameter.CONSUMER_ID))
-            if (consumer != null) {
-                log.debug "Found consumer with key " + consumer.get("key") //+ " and sharedSecret " + consumer.get("secret")
-                if (checkValidSignature(params.get(REQUEST_METHOD), ltiService.endPoint, consumer.get("secret"), sanitizedParams, params.get(Parameter.OAUTH_SIGNATURE))) {
-                    log.debug  "The message has a valid signature."
-                    
-                    if( !"extended".equals(ltiService.mode) ) {
-                        log.debug  "LTI service running in simple mode."
-                        result = doJoinMeeting(params)
-                    } else {
-                        log.debug  "LTI service running in extended mode."
-                        if ( !Boolean.parseBoolean(params.get(Parameter.CUSTOM_RECORD)) ) {
-                            log.debug  "No bbb_record parameter was sent; immediately redirecting to BBB session!"
+        if( request.post ){
+            Map<String, String> result = new HashMap<String, String>()
+            ArrayList<String> missingParams = new ArrayList<String>()
+            log.debug "Checking for required parameters"
+            if (hasAllRequiredParams(params, missingParams)) {
+                def sanitizedParams = sanitizePrametersForBaseString(params)
+                def consumer = ltiService.getConsumer(params.get(Parameter.CONSUMER_ID))
+                if (consumer != null) {
+                    log.debug "Found consumer with key " + consumer.get("key") //+ " and sharedSecret " + consumer.get("secret")
+                    if (checkValidSignature(params.get(REQUEST_METHOD), ltiService.retrieveBasicLtiEndpoint(request.isSecure()?"https":"http"), consumer.get("secret"), sanitizedParams, params.get(Parameter.OAUTH_SIGNATURE))) {
+                        log.debug  "The message has a valid signature."
+                        
+                        if( !"extended".equals(ltiService.mode) ) {
+                            log.debug  "LTI service running in simple mode."
                             result = doJoinMeeting(params)
+                        } else {
+                            log.debug  "LTI service running in extended mode."
+                            if ( !Boolean.parseBoolean(params.get(Parameter.CUSTOM_RECORD)) ) {
+                                log.debug  "No bbb_record parameter was sent; immediately redirecting to BBB session!"
+                                result = doJoinMeeting(params)
+                            }
                         }
+                        
+                    } else {
+                        result.put("resultMessageKey", "InvalidSignature")
+                        result.put("resultMessage", "Invalid signature (" + params.get(Parameter.OAUTH_SIGNATURE) + ").")
                     }
                     
                 } else {
-                    result.put("resultMessageKey", "InvalidSignature")
-                    result.put("resultMessage", "Invalid signature (" + params.get(Parameter.OAUTH_SIGNATURE) + ").")
+                    result.put("resultMessageKey", "ConsumerNotFound")
+                    result.put("resultMessage", "Consumer with id = " + params.get(Parameter.CONSUMER_ID) + " was not found.")
                 }
+    
+            } else {
+                String missingStr = ""
+                for(String str:missingParams) {
+                    missingStr += str + ", ";
+                }
+                result.put("resultMessageKey", "MissingRequiredParameter")
+                result.put("resultMessage", "Missing parameters [$missingStr]")
+            }
+            
+            
+            if( result != null && result.containsKey("resultMessageKey") ) {
+                log.debug "Error [resultMessageKey:'" + result.get("resultMessageKey") + "', resultMessage:'" + result.get("resultMessage") + "']"
+                render(view: "error", model: ['resultMessageKey': result.get("resultMessageKey"), 'resultMessage': result.get("resultMessage")])
                 
             } else {
-                result.put("resultMessageKey", "ConsumerNotFound")
-                result.put("resultMessage", "Consumer with id = " + params.get(Parameter.CONSUMER_ID) + " was not found.")
+                session["params"] = params
+                List<Object> recordings = bigbluebuttonService.getRecordings(params)
+                for(Map<String, Object> recording: recordings){
+                    /// Calculate duration
+                    long endTime = Long.parseLong((String)recording.get("endTime"))
+                    endTime -= (endTime % 1000)
+                    long startTime = Long.parseLong((String)recording.get("startTime"))
+                    startTime -= (startTime % 1000)
+                    int duration = (endTime - startTime) / 60000
+                    /// Add duration
+                    recording.put("duration", duration )
+                }
+                
+                render(view: "index", model: ['params': params, 'recordingList': recordings, 'ismoderator': bigbluebuttonService.isModerator(params)])
             }
-
+    
         } else {
-            String missingStr = ""
-            for(String str:missingParams) {
-                missingStr += str + ", ";
-            }
-            result.put("resultMessageKey", "MissingRequiredParameter")
-            result.put("resultMessage", "Missing parameters [$missingStr]")
-        }
+            render(text: getCartridgeXML(), contentType: "text/xml", encoding: "UTF-8")
         
-        
-        if( result != null && result.containsKey("resultMessageKey") ) {
-            log.debug "Error [resultMessageKey:'" + result.get("resultMessageKey") + "', resultMessage:'" + result.get("resultMessage") + "']"
-            render(view: "error", model: ['resultMessageKey': result.get("resultMessageKey"), 'resultMessage': result.get("resultMessage")])
-            
-        } else {
-            session["params"] = params
-            List<Object> recordings = bigbluebuttonService.getRecordings(params)
-            for(Map<String, Object> recording: recordings){
-                /// Calculate duration
-                long endTime = Long.parseLong((String)recording.get("endTime"))
-                endTime -= (endTime % 1000) 
-                long startTime = Long.parseLong((String)recording.get("startTime"))
-                startTime -= (startTime % 1000)
-                int duration = (endTime - startTime) / 60000
-                /// Add duration
-                recording.put("duration", duration )
-            }
-            
-            render(view: "index", model: ['params': params, 'recordingList': recordings, 'ismoderator': bigbluebuttonService.isModerator(params)])
         }
     }
     
@@ -338,5 +344,38 @@ class ToolController {
         log.debug("Calculated: " + calculatedSignature + " Received: " + signature);
         return calculatedSignature.equals(signature)
     }
+    
+    private String getCartridgeXML(){
+        def cartridge = '' +
+        '<?xml version="1.0" encoding="UTF-8"?>' +
+        '<cartridge_basiclti_link xmlns="http://www.imsglobal.org/xsd/imslticc_v1p0"' +
+        '       xmlns:blti = "http://www.imsglobal.org/xsd/imsbasiclti_v1p0"' +
+        '       xmlns:lticm ="http://www.imsglobal.org/xsd/imslticm_v1p0"' +
+        '       xmlns:lticp ="http://www.imsglobal.org/xsd/imslticp_v1p0"' +
+        '       xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"' +
+        '       xsi:schemaLocation = "http://www.imsglobal.org/xsd/imslticc_v1p0 http://www.imsglobal.org/xsd/lti/ltiv1p0/imslticc_v1p0.xsd' +
+        '                             http://www.imsglobal.org/xsd/imsbasiclti_v1p0 http://www.imsglobal.org/xsd/lti/ltiv1p0/imsbasiclti_v1p0.xsd' +
+        '                             http://www.imsglobal.org/xsd/imslticm_v1p0 http://www.imsglobal.org/xsd/lti/ltiv1p0/imslticm_v1p0.xsd' +
+        '                             http://www.imsglobal.org/xsd/imslticp_v1p0 http://www.imsglobal.org/xsd/lti/ltiv1p0/imslticp_v1p0.xsd">' +
+        '    <blti:title>ePortfolio</blti:title>' +
+        '    <blti:description>Single Sign On into BigBlueButton</blti:description>' +
+        '    <blti:launch_url>' + ltiService.retrieveBasicLtiEndpoint("http") + '</blti:launch_url>' +
+        '    <blti:secure_launch_url>' + ltiService.retrieveBasicLtiEndpoint("https") + '</blti:secure_launch_url>' +
+        '    <blti:icon>' + ltiService.retrieveEndpoint("http") + 'images/icon.ico</blti:icon>' +
+        '    <blti:secure_icon>' + ltiService.retrieveEndpoint("http") + 'images/icon.ico</blti:secure_icon>' +
+        '    <blti:vendor>' +
+        '        <lticp:code>BBB</lticp:code>' +
+        '        <lticp:name>BigBlueButton</lticp:name>' +
+        '        <lticp:description>Open source web conferencing system for distance learning.</lticp:description>' +
+        '        <lticp:url>http://www.bigbluebutton.org/</lticp:url>' +
+        '    </blti:vendor>' +
+        '    <cartridge_bundle identifierref="BLTI001_Bundle"/>' +
+        '    <cartridge_icon identifierref="BLTI001_Icon"/>' +
+        '</cartridge_basiclti_link>'
+        
+        return cartridge
+        
+    }
+
 
 }
diff --git a/bbb-lti/grails-app/services/LtiService.groovy b/bbb-lti/grails-app/services/LtiService.groovy
index d63ecebf3e..9947043126 100644
--- a/bbb-lti/grails-app/services/LtiService.groovy
+++ b/bbb-lti/grails-app/services/LtiService.groovy
@@ -26,11 +26,30 @@ class LtiService {
 
     boolean transactional = false
     
-    def endPoint = "http://localhost/lti/tool.xml"
+    //def endPoint = "http://localhost/lti/tool.xml"
+    def endPoint = "localhost"
+    def basicLtiEndpoint = "tool.xml"
+    
     def consumers = "demo:welcome"
     def mode = "simple"
     Map<String, String> consumerMap
     
+    def retrieveEndpoint() {
+        return retrieveEndpoint("http")
+    }
+
+    def retrieveEndpoint(protocol) {
+        return protocol + "://" + endPoint + "/lti/"
+    }
+        
+    def retrieveBasicLtiEndpoint() {
+        return retrieveBasicLtiEndpoint("http")
+    }
+    
+    def retrieveBasicLtiEndpoint(protocol) {
+        return protocol + "://" + endPoint + "/lti/" + basicLtiEndpoint
+    }
+
     private Map<String, String> getConsumer(consumerId) {
         Map<String, String> consumer = null
         
-- 
GitLab