Index: lams_webct_integration/.classpath =================================================================== diff -u --- lams_webct_integration/.classpath (revision 0) +++ lams_webct_integration/.classpath (revision 689a0744a03d219ecbcde17da1e9a2ee70ca6284) @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + Index: lams_webct_integration/.cvsignore =================================================================== diff -u --- lams_webct_integration/.cvsignore (revision 0) +++ lams_webct_integration/.cvsignore (revision 689a0744a03d219ecbcde17da1e9a2ee70ca6284) @@ -0,0 +1,3 @@ +*.class +bin +build \ No newline at end of file Index: lams_webct_integration/.project =================================================================== diff -u --- lams_webct_integration/.project (revision 0) +++ lams_webct_integration/.project (revision 689a0744a03d219ecbcde17da1e9a2ee70ca6284) @@ -0,0 +1,17 @@ + + + lams_webct_integration + + + + + + org.eclipse.jdt.core.javabuilder + + + + + + org.eclipse.jdt.core.javanature + + Index: lams_webct_integration/DeployableComponentConfig.xml =================================================================== diff -u --- lams_webct_integration/DeployableComponentConfig.xml (revision 0) +++ lams_webct_integration/DeployableComponentConfig.xml (revision 689a0744a03d219ecbcde17da1e9a2ee70ca6284) @@ -0,0 +1,160 @@ + + + + + + + 0.0.7 + 1.0 + lams.integration + + sso + org.lamsfoundation.integration.webct.AuthorModule + Luke Foxton + LAMS-WebCt integration module + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Index: lams_webct_integration/build.xml =================================================================== diff -u --- lams_webct_integration/build.xml (revision 0) +++ lams_webct_integration/build.xml (revision 689a0744a03d219ecbcde17da1e9a2ee70ca6284) @@ -0,0 +1,94 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Index: lams_webct_integration/lib/authmoduledata_ce_1.4.jar =================================================================== diff -u Binary files differ Index: lams_webct_integration/lib/commons-codec-1.3.jar =================================================================== diff -u Binary files differ Index: lams_webct_integration/lib/commons-discovery-0.2.jar =================================================================== diff -u Binary files differ Index: lams_webct_integration/lib/commons-logging-1.0.4.jar =================================================================== diff -u Binary files differ Index: lams_webct_integration/lib/log4j-1.2.8.jar =================================================================== diff -u Binary files differ Index: lams_webct_integration/lib/servlet.jar =================================================================== diff -u Binary files differ Index: lams_webct_integration/lib/velocity-1.5.jar =================================================================== diff -u Binary files differ Index: lams_webct_integration/lib/webct1200_ap1_sdk_client.jar =================================================================== diff -u Binary files differ Index: lams_webct_integration/src/org/lamsfoundation/integration/util/CSVUtil.java =================================================================== diff -u --- lams_webct_integration/src/org/lamsfoundation/integration/util/CSVUtil.java (revision 0) +++ lams_webct_integration/src/org/lamsfoundation/integration/util/CSVUtil.java (revision 689a0744a03d219ecbcde17da1e9a2ee70ca6284) @@ -0,0 +1,171 @@ +/**************************************************************** + * Copyright (C) 2007 LAMS Foundation (http://lamsfoundation.org) + * ============================================================= + * License Information: http://lamsfoundation.org/licensing/lams/2.0/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2.0 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + * USA + * + * http://www.gnu.org/licenses/gpl.txt + * **************************************************************** + */ +package org.lamsfoundation.integration.util; + +import java.text.ParseException; +import java.util.ArrayList; +import java.util.regex.*; + +/** + * CSVUtil Provides "Comma Seperated Value" writing and parsing. + * The two methods write() and parse() will perform writing to and parse from + * the CSV format + * + * @author Luke Foxton + */ +public class CSVUtil { + + private static final char QUOTE = '"'; + private static final char COMMA = ','; + + /* precompile the patterns to speed up the search */ + + // should we put quotes around a value? + private static final Pattern CONTAINS_NEWLINE = Pattern.compile(".*(\\n|\\r)+.*"); + + // should we put quotes around a value? + private static final Pattern CONTAINS_COMMA = Pattern.compile(".*(,)+.*"); + + // should we escape the quotes? + private static final Pattern CONTAINS_QUOTE = Pattern.compile("\""); + + // how should we wrap qoutes around comma or newline? + private static final String WRAP_QOUTE = "\"$0\""; + + // how should we escape the value if it has qoutes? + private static final String ESCAPE_QUOTE = "\"\""; + + // has this value been wrapped with quotes + private static final Pattern WRAPPED_QUOTE = Pattern.compile("^\"(.*((,|\\n|\\r)+).*)\"$"); + + // has this value been escaped by ESCAPE_QUOTE + private static final Pattern ESCAPED_QUOTE = Pattern.compile("\"\""); + + // how should we unescape the the ESCAPED_QUOTE? + private static final String UNWRAP_QOUTE = "$1"; + + // how should we unescape the the ESCAPED_COMMA? + private static final String UNESCAPE_QUOTE = "\""; + + /* + * NOTE: why are we using \\n|\\r in CONTAINS_NEWLINE and WRAPPED_QUOTE? + * javadoc says "." represents "Any character (may or may not match line terminators)" + * and we want to make sure terminiators such as newline (\n) gets matched as well + * if we dont match it then ,\n, will get written as ","\n"," + */ + + /** + * Writes a array of String into CSV format + * @param vals - The array of string to be written into CSV format + * @return + */ + public static String write(String[] vals){ + String str = ""; + int lastIndex = vals.length - 1; + for(int i=0; iLuke Foxton + */ +public class Constants { + + public static final String PARAM_USER_ID = "uid"; + public static final String PARAM_SERVER_ID = "sid"; + public static final String PARAM_TIMESTAMP = "ts"; + public static final String PARAM_HASH = "hash"; + //public static final String PARAM_URL = "url"; + public static final String PARAM_METHOD = "method"; + public static final String PARAM_LEARNING_SESSION_ID = "lsid"; + public static final String PARAM_LEARNING_DESIGN_ID = "ldid"; + public static final String PARAM_COURSE_ID = "course_id"; + + + public static final String SERVLET_LOGIN_REQUEST = "/lams/LoginRequest"; + public static final String SERVLET_ACTION_REQUEST = "/LamsActionRequest"; + + public static final String URLDECODER_CODING = "US-ASCII"; + + public static final String METHOD_AUTHOR = "author"; + public static final String METHOD_MONITOR = "monitor"; + public static final String METHOD_LEARNER = "learner"; + + // XML format constnats + public static final String ELEM_FOLDER = "Folder"; + public static final String ELEM_LEARNING_DESIGN = "LearningDesign"; + public static final String ATTR_NAME = "name"; + public static final String ATTR_RESOURCE_ID = "resourceId"; + +} Index: lams_webct_integration/src/org/lamsfoundation/integration/webct/AuthorModule.java =================================================================== diff -u --- lams_webct_integration/src/org/lamsfoundation/integration/webct/AuthorModule.java (revision 0) +++ lams_webct_integration/src/org/lamsfoundation/integration/webct/AuthorModule.java (revision 689a0744a03d219ecbcde17da1e9a2ee70ca6284) @@ -0,0 +1,351 @@ +package org.lamsfoundation.integration.webct; + +import java.io.StringWriter; +import java.net.URLEncoder; +import java.net.URL; +import java.util.Hashtable; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import java.util.List; +import java.util.ArrayList; +import java.util.Properties; +import javax.security.auth.Subject; +import javax.security.auth.callback.CallbackHandler; + +import javax.security.auth.login.LoginException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import com.webct.platform.sdk.context.gen.*; +import com.webct.platform.sdk.context.client.*; +import com.webct.platform.sdk.security.authentication.module.AuthenticationModule; +import com.webct.platform.sdk.proxytool.common.ProcessCallback; +import com.webct.platform.sdk.security.authentication.module.WebCTSSOContext; +import com.webct.platform.sdk.context.client.ContextSDK; +import com.webct.platform.sdk.context.gen.SessionVO; +import com.webct.platform.sdk.context.gen.LearningCtxtVO; +import com.webct.platform.sdkext.authmoduledata.*; +import com.webct.platform.sdkext.authmoduledata.UserVO; +import com.webct.platform.sdk.context.gen.SessionVO; + +//-------- Velocity imports -------------- +import java.io.StringWriter; +import java.rmi.RemoteException; +import org.apache.velocity.VelocityContext; +import org.apache.velocity.Template; +import org.apache.velocity.app.VelocityEngine; +import org.apache.velocity.exception.*; +//import org.apache.axis.AxisFault; + +import java.net.URL; +import org.apache.log4j.Logger; + +import org.lamsfoundation.integration.webct.LamsSecurityUtil; +import org.lamsfoundation.integration.util.Constants; + + +/** + * @author Luke Foxton + * + */ +public class AuthorModule extends AuthenticationModule +{ + + public static final String VERSION = "1.0.0"; + public static final String JARSTR = "lams2-webct-integration-" + VERSION + ".jar"; + + + private boolean loginSucceeded = false; + private HttpServletRequest request = null; + private Map settings = null; + private WebCTSSOContext ssoContext; + + + + private String lamsServerUrl; + private String lamsServerId; + private String lamsServerSecretKey; + private String webctRequestSource; + + private String guid = null; + private String user = null; + + private static final Logger log = Logger.getLogger(AuthorModule.class); + + + + private static final String GUTENBERG_QUERY_URL = "http://www.gutenberg.org/catalog/world/results"; + + + public AuthorModule() + { + super(); + } + + public AuthorModule(Hashtable hashtable) + { + super(hashtable); + } + + public void initialize(Subject subject, CallbackHandler callbackHandler, Map sharedState, Map options) + { + super.initialize(subject, callbackHandler, sharedState, options); + } + + public boolean validate() + { + return true; + } + + public boolean login() throws LoginException + { + return true; + } + + public boolean abort() throws LoginException + { + return super.abort(); + } + + public boolean commit() throws LoginException + { + + if(super.getCurrentMode().equals(super.OUTGOING_MODE)) + { + UserVO user = null; + List roles; + Long lcID = super.getCurrentLearningContextId(); + boolean isTeacher = false; + boolean isStudent = false; + try { + + user = UserService.getInstance().getUser(super.getUserId(), lcID); + roles = user.getUserRoles(); + + System.out.println("ROLES!!!!!!:" + roles.toString()); + + System.out.println("COURSE_INSTRUCTOR: " + UserRole.COURSE_INSTRUCTOR_ROLE); + System.out.println("SECTION_INSTRUCTOR: " + UserRole.SECTION_INSTRUCTOR_ROLE); + System.out.println("STUDENT_ROLE: " +UserRole.STUDENT_ROLE); + + Iterator it = roles.iterator(); + while (it.hasNext()) + { + String role = it.next().toString().trim(); + + System.out.println("ROLE: " + role); + if (role.equals(UserRole.COURSE_INSTRUCTOR_ROLE.toString()) || role.equals(UserRole.SECTION_INSTRUCTOR_ROLE.toString()) ) + { + isTeacher=true; + } + else if (role.equals(UserRole.STUDENT_ROLE.toString())) + { + isStudent=true; + } + } + + if (!isStudent && !isTeacher) + { + throw new LoginException("User's role does not have access to these pages."); + } + } + catch (VistaDataException e) + { + log.error("Problem getting user info:", e); + e.printStackTrace(); + return false; + } + + + + Map settings = super.getSettings(); + //user = super.getUserId(); + lamsServerUrl = (String)settings.get("lamsServerUrl"); + lamsServerId = (String)settings.get("lamsServerId"); + lamsServerSecretKey = (String)settings.get("lamsServerSecretKey"); + webctRequestSource = (String)settings.get("webctRequestSource"); + + + + + Map params = new HashMap(); + params.put("lamsServerUrl", lamsServerUrl); + params.put("lamsServerId", lamsServerId); + params.put("lamsServerSecretKey", lamsServerSecretKey); + params.put("webctRequestSource", webctRequestSource); + params.put("user", user); + params.put("isTeacher", "" + isTeacher); + + String authorUrl = null; + String learningDesigns = null; + + try + { + authorUrl = LamsSecurityUtil.generateRequestURL( + lamsServerUrl, + lamsServerId, + lamsServerSecretKey, + webctRequestSource, + user.getUserId(), + "" + lcID, + "en", + "AU", + user.getFirstname(), + user.getLastname(), + user.getEmail(), + "author"); + + + log.info("LAMS AUTHOR REQUEST: " + authorUrl); + System.out.println("LAMS AUTHOR REQUEST: " + authorUrl); + params.put("authorUrl", authorUrl); + + + learningDesigns = LamsSecurityUtil.getLearningDesigns( + lamsServerUrl, + lamsServerId, + lamsServerSecretKey, + user.getUserId(), + "" + lcID, + "en", + "AU", + user.getFirstname(), + user.getLastname(), + user.getEmail(), + "1"); + + log.info("LAMS LEARNING DESIGNS: " + learningDesigns); + System.out.println("LAMS LEARNING DESIGN: " + learningDesigns); + params.put("learningDesigns", learningDesigns); + + } + catch (Exception e) + { + log.error("Problem generating request url:", e); + System.out.println("Problem generating request url: " + e.getMessage() ); + e.printStackTrace(); + return false; + } + + + + String html=null; + try + { + if (isTeacher) + { + html = this.generatePage("web/create.vm", params); + } + else + { + html = this.generatePage("web/learnerMonitor.vm", params); + } + } + catch(Exception e) + { + log.error("Problem generating page:", e); + e.printStackTrace(); + throw new LoginException("Error generating page: " + e.toString()); + } + super.setResponseContent(html); + + return true; + } + /*else if(super.getCurrentMode().equals(super.INCOMING_MODE)) + { + //try { + //ContextSDK context = new ContextSDK(); + //SessionVO session = context.getCurrentSession(); + //Long lcid = super.getCurrentLearningContextId(); + // get the learning context object that corresponds to the LCID + //LearningCtxtVO lc = context.getLearningContext(session, lcid.longValue()); + + + + + Map params = new HashMap(); + params.put("title", ""); // not implemented by WebCt + params.put("fname", super.getUserId()); + params.put("lname", super.getUserId()); + params.put("adress", ""); // not implemented by WebCt + params.put("city", ""); // not implemented by WebCt + params.put("state", ""); // not implemented by WebCt + params.put("postcode", ""); // not implemented by WebCt + params.put("country", ""); // not implemented by WebCt + params.put("phnumber", ""); // not implemented by WebCt + params.put("mphnumber", ""); // not implemented by WebCt + params.put("fnumber", ""); // not implemented by WebCt + params.put("email", ""); // not implemented by WebCt + params.put("localelanguage", "en"); + params.put("localecountry", "AU"); + + String html=null; + try + { + html = this.generatePage("web/userdataservlet.vm", params); + } + catch(Exception e) + { + e.printStackTrace(); + throw new LoginException("Error generating page: " + e.toString()); + } + super.setResponseContent(html); + + return true; + + //} + //catch (RemoteException e) + //{ + // e.printStackTrace(); + // throw new LoginException("Error getting user session: " + e.toString()); + //} + }*/ + else + { + // shouldn't be here + return false; + } + + } + + + private String generatePage(String htmlTemplate, Map contextObjects) throws Exception + { + String jar_base = "./deployablecomponents/lams2/"; + + VelocityEngine ve = new VelocityEngine(); + + Properties props = new Properties(); + props.setProperty("resource.loader", "file, jar"); + props.setProperty("file.resource.loader.path", jar_base); + props.setProperty("jar.resource.loader.class", "org.apache.velocity.runtime.resource.loader.JarResourceLoader"); + props.setProperty("jar.resource.loader.path", "jar:file:" + jar_base + JARSTR); + ve.init(props); + + VelocityContext context = new VelocityContext(); + + for(Iterator it = contextObjects.keySet().iterator(); it.hasNext();) + { + String key = (String)it.next(); + context.put(key, contextObjects.get(key)); + } + + context.put("request", request); + context.put("settings", settings); + context.put("authmod", this); + + Template template = null; + template = ve.getTemplate(htmlTemplate); + StringWriter html = new StringWriter(); + template.merge(context, html); + return html.toString(); + } + + public boolean logout() throws LoginException + { + return super.logout(); + } +} + + \ No newline at end of file Index: lams_webct_integration/src/org/lamsfoundation/integration/webct/LamsSecurityUtil.java =================================================================== diff -u --- lams_webct_integration/src/org/lamsfoundation/integration/webct/LamsSecurityUtil.java (revision 0) +++ lams_webct_integration/src/org/lamsfoundation/integration/webct/LamsSecurityUtil.java (revision 689a0744a03d219ecbcde17da1e9a2ee70ca6284) @@ -0,0 +1,452 @@ +/**************************************************************** + * Copyright (C) 2007 LAMS Foundation (http://lamsfoundation.org) + * ============================================================= + * License Information: http://lamsfoundation.org/licensing/lams/2.0/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2.0 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + * USA + * + * http://www.gnu.org/licenses/gpl.txt + * **************************************************************** + */ +package org.lamsfoundation.integration.webct; + +import java.lang.IllegalStateException; +import java.net.ConnectException; +import java.io.IOException; +import java.io.InputStream; +import java.io.UnsupportedEncodingException; +import java.net.HttpURLConnection; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLConnection; +import java.net.URLEncoder; +import java.rmi.RemoteException; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.util.Map; +import java.lang.StringBuffer; + +import org.apache.commons.codec.binary.Hex; +import org.lamsfoundation.integration.util.Constants; +import org.w3c.dom.Document; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; +import org.xml.sax.SAXException; +import org.apache.log4j.Logger; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; + + +/** + * This class creates URLs, servlet calls and webservice calls + * for communication with LAMS + * + * @author Luke Foxton + */ +public class LamsSecurityUtil { + + static Logger logger = Logger.getLogger(LamsSecurityUtil.class); + + + /** + * Generates login requests to LAMS for author, monitor and learner + * + * @param ctx the blackboard contect, contains session data + * @param method the method to request of LAMS "author", "monitor", "learner" + * @return a url pointing to the LAMS lesson, monitor, author session + * @throws Exception + */ + public static String generateRequestURL( + String serverAddr, + String serverId, + String secretKey, + String reqSrc, + String username, + String courseId, + String lang, + String country, + String firstName, + String lastName, + String email, + String method) + throws Exception + { + // If lams.properties could not be read, throw exception + if(serverAddr == null || serverId == null || reqSrc==null){ + throw new Exception("Configuration Exception " + serverAddr + ", " + serverId); + } + + String timestamp = new Long(System.currentTimeMillis()).toString(); + String hash = generateAuthenticationHash(timestamp, username, method, serverId, secretKey); + + + String url; + try { + url = serverAddr + "/LoginRequest?" + + "&uid=" + URLEncoder.encode(username, "UTF8") + + "&method=" + method + + "&ts=" + timestamp + + "&sid=" + serverId + + "&hash=" + hash + + "&courseid=" + URLEncoder.encode(courseId, "UTF8") + + "&country=" + country + + "&lang=" + lang + + "&requestSrc=" + URLEncoder.encode(reqSrc, "UTF8") + + "&firstName=" + firstName + + "&lastName=" + lastName + + "&email=" + email; + } catch (UnsupportedEncodingException e) { + throw new RuntimeException(); + } + + logger.info("LAMS Req: " + url); + //System.out.println(url); + + return url; + } + + + public static String getLearningDesigns( + String serverAddr, + String serverId, + String secretKey, + String username, + String courseId, + String lang, + String country, + String firstName, + String lastName, + String email, + String mode) + throws Exception + { + + + + + String timestamp = new Long(System.currentTimeMillis()).toString(); + String hash = generateAuthenticationHash(timestamp, username, serverId, secretKey); + + + + // TODO: Make locale settings work + String learningDesigns = "[]"; // empty javascript array + try { + String serviceURL = serverAddr + "/services/xml/LearningDesignRepository?" + + "datetime=" + timestamp + + "&username=" + URLEncoder.encode(username, "utf8") + + "&serverId=" + URLEncoder.encode(serverId, "utf8") + + "&hashValue=" + hash + + "&courseId=" + URLEncoder.encode(courseId, "UTF8") + + "&country=" + country + + "&lang=" + lang + + "&mode=" + mode + + "&firstName=" + firstName + + "&lastName=" + lastName + + "&email=" + email; + + URL url = new URL(serviceURL); + URLConnection conn = url.openConnection(); + if (!(conn instanceof HttpURLConnection)) { + logger.error("Unable to open connection to: " + serviceURL); + } + + HttpURLConnection httpConn = (HttpURLConnection)conn; + + + if (httpConn.getResponseCode() != HttpURLConnection.HTTP_OK) { + logger.error("HTTP Response Code: " + httpConn.getResponseCode() + + ", HTTP Response Message: " + httpConn.getResponseMessage()); + return "error"; + } + + + //InputStream is = url.openConnection().getInputStream(); + InputStream is = conn.getInputStream(); + + + // parse xml response + DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); + DocumentBuilder db = dbf.newDocumentBuilder(); + Document document = db.parse(is); + + learningDesigns = "[" + convertToTigraFormat(document.getDocumentElement()) + "]"; + + // replace sequence id with javascript method + String pattern = "'(\\d+)'"; + String replacement = "'javascript:selectSequence($1)'"; + learningDesigns = learningDesigns.replaceAll(pattern, replacement); + + // TODO better error handling + } catch (MalformedURLException e) { + logger.error("Unable to get LAMS learning designs, bad URL: '" + + serverAddr + + "', please check lams.properties", e); + e.printStackTrace(); + return "error"; + }catch (IllegalStateException e){ + logger.error("LAMS Server timeout, did not get a response from the LAMS server. Please contact your systems administrator", e); + e.printStackTrace(); + return "error"; + }catch (ConnectException e){ + logger.error("LAMS Server timeout, did not get a response from the LAMS server. Please contact your systems administrator", e); + e.printStackTrace(); + return "error"; + } catch (UnsupportedEncodingException e) { + logger.error(e); + e.printStackTrace(); + return "error"; + } catch (IOException e) { + logger.error(e); + e.printStackTrace(); + return "error"; + } catch (ParserConfigurationException e) { + logger.error(e); + e.printStackTrace(); + return "error"; + } catch (SAXException e) { + logger.error(e); + e.printStackTrace(); + return "error"; + } + return learningDesigns; + } + + /** + * Starts lessons in lams through a LAMS webservice + * + * @param ldId the learning design id for which you wish to start a lesson + * @param title the title of the lesson + * @param desc the description of the lesson + * @return the learning session id + */ + public static long startLesson( + String serverAddr, + String serverId, + String secretKey, + String reqSrc, + String username, + String courseId, + String lang, + String country, + String firstName, + String lastName, + String email, + long ldId, + String title, + String desc) + { + long error = -1; + if (serverId == null || serverAddr == null || secretKey == null ) { + logger.error("Unable to retrieve learning designs from LAMS, one or more lams configuration properties is null"); + return error; + } + + try { + + String timestamp = new Long(System.currentTimeMillis()).toString(); + String hash = generateAuthenticationHash(timestamp, username, serverId, secretKey); + + // (serverId, datetime, hashValue, username, ldId, courseId, title, desc, country, lang) + + String serviceURL = serverAddr + "/services/xml/LessonManager?" + + "&serverId=" + URLEncoder.encode(serverId, "utf8") + + "&datetime=" + timestamp + + "&username=" + URLEncoder.encode(username, "utf8") + + "&hashValue=" + hash + + "&courseId=" + URLEncoder.encode(courseId, "utf8") + + "&ldId=" + new Long(ldId).toString() + + "&country=" + country + + "&lang=" + lang + + "&method=" + "start" + + "&title=" + URLEncoder.encode(title, "utf8").trim() + + "&desc=" + URLEncoder.encode(desc, "utf8").trim(); + + + logger.info("LAMS START LESSON Req: " + serviceURL); + //System.out.println("START LESSON: " + serviceURL); + + URL url = new URL(serviceURL); + URLConnection conn = url.openConnection(); + if (!(conn instanceof HttpURLConnection)) { + logger.error("Unable to open connection to: " + serviceURL); + } + + HttpURLConnection httpConn = (HttpURLConnection)conn; + + if (httpConn.getResponseCode() != HttpURLConnection.HTTP_OK) { + logger.error("HTTP Response Code: " + httpConn.getResponseCode() + + ", HTTP Response Message: " + httpConn.getResponseMessage()); + return error; + } + + //InputStream is = url.openConnection().getInputStream(); + InputStream is = conn.getInputStream(); + + + // parse xml response + DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); + DocumentBuilder db = dbf.newDocumentBuilder(); + Document document = db.parse(is); + + // get the lesson id from the response + return Long.parseLong(document.getElementsByTagName("Lesson").item(0).getAttributes().getNamedItem("lessonId").getNodeValue()); + + } catch (MalformedURLException e) { + logger.error("Unable to start LAMS lesson, bad URL: '" + + serverAddr + + "', please check lams.properties", e); + e.printStackTrace(); + return error; + }catch (IllegalStateException e){ + logger.error("LAMS Server timeout, did not get a response from the LAMS server. Please contact your systems administrator", e); + e.printStackTrace(); + return error; + } catch (RemoteException e) { + logger.error("Unable to start LAMS lesson, RMI Remote Exception",e); + e.printStackTrace(); + return error; + } catch (UnsupportedEncodingException e) + { + logger.error("Unable to start LAMS lesson, Unsupported Encoding Exception",e); + e.printStackTrace(); + return error; + } + catch (ConnectException e) + { + logger.error("LAMS Server timeout, did not get a response from the LAMS server. Please contact your systems administrator", e); + e.printStackTrace(); + return error; + } + catch (Exception e) { + logger.error("Unable to start LAMS lesson. Please contact your system administrator.",e); + e.printStackTrace(); + return error; + } + } + + + /** + * + * @param node the node from which to do the recursive conversion + * @return the string converted to tigra format + */ + + public static String convertToTigraFormat(Node node) { + + StringBuffer sb = new StringBuffer(); + + if (node.getNodeName().equals(Constants.ELEM_FOLDER)) { + sb.append("['"); + + StringBuffer attribute= new StringBuffer(node.getAttributes().getNamedItem( + Constants.ATTR_NAME).getNodeValue().replaceAll("'", "\\'")); + + sb.append(attribute.append("',").append("null").append(',')); + + NodeList children = node.getChildNodes(); + if (children.getLength() == 0) { + sb.append("['',null]"); + } else { + sb.append(convertToTigraFormat(children.item(0))); + for (int i = 1; i < children.getLength(); i++) { + sb.append(',').append( + convertToTigraFormat(children.item(i))); + } + } + sb.append(']'); + } else if (node.getNodeName().equals( + Constants.ELEM_LEARNING_DESIGN)) { + sb.append('['); + + StringBuffer attrName = new StringBuffer(node.getAttributes().getNamedItem( + Constants.ATTR_NAME).getNodeValue().replaceAll("'", "\\'")); + StringBuffer attrResId = new StringBuffer(node.getAttributes().getNamedItem( + Constants.ATTR_RESOURCE_ID).getNodeValue().replaceAll("'", "\\'")); + + sb.append('\'') + .append(attrName + .append('\'') + .append(',') + .append('\'') + .append(attrResId.append('\''))); + + sb.append(']'); + } + return sb.toString(); + } + + //generate authentication hash code to validate parameters + public static String generateAuthenticationHash(String datetime, String login, String method, String serverId, String secretkey) { + String plaintext = datetime.toLowerCase().trim() + + login.toLowerCase().trim() + + method.toLowerCase().trim() + + serverId.toLowerCase().trim() + + secretkey.toLowerCase().trim(); + + String hash = sha1(plaintext); + return hash; + } + + + //generate authentication hash code to validate parameters + public static String generateAuthenticationHash(String datetime, String login, String serverId, String secretkey) { + String plaintext = datetime.toLowerCase().trim() + + login.toLowerCase().trim() + + serverId.toLowerCase().trim() + + secretkey.toLowerCase().trim(); + + String hash = sha1(plaintext); + + return hash; + } + + //generate authentication hash code to validate parameters + public static String generateAuthenticationHash(String datetime, String serverId, String secretkey) + throws NoSuchAlgorithmException { + String plaintext = datetime.toLowerCase().trim() + + serverId.toLowerCase().trim() + + secretkey.toLowerCase().trim() ; + + return sha1(plaintext); + } + + + /** + * The parameters are: + * uid - the username on the external system + * method - either author, monitor or learner + * ts - timestamp + * sid - serverID + * str is [ts + uid + method + serverID + serverKey] (Note: all lower case) + * + * @param str The string to be hashed + * @return The hased string + */ + public static String sha1(String str){ + try{ + MessageDigest md = MessageDigest.getInstance("SHA1"); + return new String(Hex.encodeHex(md.digest(str.getBytes()))); + } catch(NoSuchAlgorithmException e){ + throw new RuntimeException(e); + } + } + + + + + +} Index: lams_webct_integration/web/create.vm =================================================================== diff -u --- lams_webct_integration/web/create.vm (revision 0) +++ lams_webct_integration/web/create.vm (revision 689a0744a03d219ecbcde17da1e9a2ee70ca6284) @@ -0,0 +1,133 @@ + + + + + +LAMS: Start Lesson + + + + + + +Create LAMS Lesson + + + + + + + + + + + + + Title + + + + Description + + + + Lesson Visibility + Show Lesson + Hide Lesson + + + + + + + + Select Sequence + + + + + + + + + + + + + + + + + + + \ No newline at end of file Index: lams_webct_integration/web/learnerMonitor.vm =================================================================== diff -u --- lams_webct_integration/web/learnerMonitor.vm (revision 0) +++ lams_webct_integration/web/learnerMonitor.vm (revision 689a0744a03d219ecbcde17da1e9a2ee70ca6284) @@ -0,0 +1,11 @@ + + + + + + + + + Hello Student + + \ No newline at end of file Index: lams_webct_integration/web/lib/tigra/tree.js =================================================================== diff -u --- lams_webct_integration/web/lib/tigra/tree.js (revision 0) +++ lams_webct_integration/web/lib/tigra/tree.js (revision 689a0744a03d219ecbcde17da1e9a2ee70ca6284) @@ -0,0 +1,9 @@ +// Title: Tigra Tree +// Description: See the demo at url +// URL: http://www.softcomplex.com/products/tigra_menu_tree/ +// Version: 1.1 (size optimized) +// Date: 11-12-2002 (mm-dd-yyyy) +// Notes: This script is free. Visit official site for further details. + +function tree(tm0,tm1) +{this.tm2=tm1;this.tm3=tm0;this.tm4=this;this.tm5=[];this.tm6=null;this.tm7=-1;var tm8=new Image(),tm9=new Image();tm8.src=tm1['icon_e'];tm9.src=tm1['icon_l'];tm1['im_e']=tm8;tm1['im_l']=tm9;for(var i=0;i<64;i++)if(tm1['icon_'+i]){var tmA=new Image();tm1['im_'+i]=tmA;tmA.src=tm1['icon_'+i]}this.tmB=function(tmC){var tmD=this.tm5[tmC];tmD.tmE(tmD.tmF)};this.tmG=function(tmC){return this.tm5[tmC].tmG()};this.tmH=function(tmC){this.tm5[tmC].tmI(true)};this.tmJ=function(tmC){this.tm5[tmC].tmI()};this.tmK=[];for(var i=0;i1;i--){tme[i]='';tmf=tmf.tmN}return ''+(this.tm7?tme.join('')+(this.tmK.length?'':''):'')+''+this.tm3[0]+''+(this.tmK.length?'':'')}function tmQ(tmg){return this.tm4.tm2['icon_'+((this.tm7?0:32)+(this.tmK.length?16:0)+(this.tmK.length&&this.tmF?8:0)+(!tmg&&this.tm4.tm6==this?4:0)+(tmg?2:0)+(tmg&&this.tmV()?1:0))]}var trees=[];tmY=document.all?function(tmh){return document.all[tmh]}:function(tmh){return document.getElementById(tmh)}; \ No newline at end of file Index: lams_webct_integration/web/lib/tigra/tree_tpl.js =================================================================== diff -u --- lams_webct_integration/web/lib/tigra/tree_tpl.js (revision 0) +++ lams_webct_integration/web/lib/tigra/tree_tpl.js (revision 689a0744a03d219ecbcde17da1e9a2ee70ca6284) @@ -0,0 +1,36 @@ +/* + Feel free to use your custom treeicons for the tree. Make sure they are all of the same size. + User treeicons collections are welcome, we'll publish them giving all regards. +*/ + +var TREE_TPL = { + 'target' : '_self', // name of the frame links will be opened in + // other possible values are: _blank, _parent, _search, _self and _top + + 'icon_e' : '/webct/images/tigra_empty.gif', // empty image + 'icon_l' : '/webct/images/tigra_line.gif', // vertical line + + 'icon_32' : '/webct/images/tigra_base.gif', // root leaf icon normal + 'icon_36' : '/webct/images/tigra_base.gif', // root leaf icon selected + + 'icon_48' : '/webct/images/tigra_base.gif', // root icon normal + 'icon_52' : '/webct/images/tigra_base.gif', // root icon selected + 'icon_56' : '/webct/images/tigra_base.gif', // root icon opened + 'icon_60' : '/webct/images/tigra_base.gif', // root icon selected + + 'icon_16' : '/webct/images/tigra_folder.gif', // node icon normal + 'icon_20' : '/webct/images/tigra_folderopen.gif', // node icon selected + 'icon_24' : '/webct/images/tigra_folderopen.gif', // node icon opened + 'icon_28' : '/webct/images/tigra_folderopen.gif', // node icon selected opened + + 'icon_0' : '/webct/images/tigra_page.gif', // leaf icon normal + 'icon_4' : '/webct/images/tigra_page.gif', // leaf icon selected + + 'icon_2' : '/webct/images/tigra_joinbottom.gif', // junction for leaf + 'icon_3' : '/webct/images/tigra_join.gif', // junction for last leaf + 'icon_18' : '/webct/images/tigra_plusbottom.gif', // junction for closed node + 'icon_19' : '/webct/images/tigra_plus.gif', // junction for last closed node + 'icon_26' : '/webct/images/tigra_minusbottom.gif',// junction for opened node + 'icon_27' : '/webct/images/tigra_icons/minus.gif' // junction for last opened node +}; + Index: lams_webct_integration/web/lib/tigra/treeicons/Thumbs.db =================================================================== diff -u Binary files differ Index: lams_webct_integration/web/lib/tigra/treeicons/base.gif =================================================================== diff -u Binary files differ Index: lams_webct_integration/web/lib/tigra/treeicons/empty.gif =================================================================== diff -u Binary files differ Index: lams_webct_integration/web/lib/tigra/treeicons/folder.gif =================================================================== diff -u Binary files differ Index: lams_webct_integration/web/lib/tigra/treeicons/folderopen.gif =================================================================== diff -u Binary files differ Index: lams_webct_integration/web/lib/tigra/treeicons/join.gif =================================================================== diff -u Binary files differ Index: lams_webct_integration/web/lib/tigra/treeicons/joinbottom.gif =================================================================== diff -u Binary files differ Index: lams_webct_integration/web/lib/tigra/treeicons/line.gif =================================================================== diff -u Binary files differ Index: lams_webct_integration/web/lib/tigra/treeicons/minus.gif =================================================================== diff -u Binary files differ Index: lams_webct_integration/web/lib/tigra/treeicons/minusbottom.gif =================================================================== diff -u Binary files differ Index: lams_webct_integration/web/lib/tigra/treeicons/page.gif =================================================================== diff -u Binary files differ Index: lams_webct_integration/web/lib/tigra/treeicons/plus.gif =================================================================== diff -u Binary files differ Index: lams_webct_integration/web/lib/tigra/treeicons/plusbottom.gif =================================================================== diff -u Binary files differ Index: lams_webct_integration/web/teach.vm =================================================================== diff -u --- lams_webct_integration/web/teach.vm (revision 0) +++ lams_webct_integration/web/teach.vm (revision 689a0744a03d219ecbcde17da1e9a2ee70ca6284) @@ -0,0 +1,22 @@ + + + + + +LAMS: Teach + + +LAMS Teaching + + + + + + + + + + + + + \ No newline at end of file