/// <summary> /// Performs log-in procedure /// </summary> /// <param name="userName">valid Adobe Connect acount name</param> /// <param name="userPassword">valid Adobe Connect acount password</param> /// <param name="iStatus">after succesfull login, <see cref="StatusInfo">iStatus</see> contains session ID to be used for single-sign-on.</param> /// <returns><see cref="bool"/></returns> public bool Login(string userName, string userPassword, out StatusInfo iStatus) { //action=login&[email protected]&password=football&session= //cookie: BREEZESESSION iStatus = new StatusInfo(); try { //StatusInfo iStatus; XmlDocument xDoc = _ProcessRequest("login", string.Format("login={0}&password={1}", userName, userPassword), true, out iStatus); if (xDoc == null || !xDoc.HasChildNodes) return false; //return (xDoc.SelectSingleNode("//status/@code").Value.Equals("ok")) ? true : false; return (iStatus.Code == StatusCodes.ok) ? true : false; } catch (Exception ex) { TraceTool.TraceException(ex); } return false; }
/// <summary> /// Returns a list of SCOs within another SCO. The enclosing SCO can be a folder, meeting, or /// curriculum. /// </summary> /// <param name="sco_id">Room/Folder ID</param> /// <param name="iStatus"></param> /// <returns>Raw contents as <see cref="XmlNodeList"/></returns> public XmlNodeList GetMeetingsInRoomRaw(string sco_id, out StatusInfo iStatus) { iStatus = new StatusInfo(); XmlDocument xDoc = _ProcessRequest("sco-contents", string.Format("sco-id={0}", sco_id), out iStatus); if (iStatus.Code != StatusCodes.ok || xDoc == null || !xDoc.HasChildNodes) return null; XmlNodeList transNodes = xDoc.SelectNodes("//sco"); if (transNodes == null || transNodes.Count < 1) return null; return transNodes; }
/// <summary> /// Method is intented to retrive data from AC 'Content' folder. E.g.: Quizzes /// </summary> /// <returns>Raw contents as <see cref="XmlNodeList"/></returns> public XmlNodeList GetQuizzesInRoom(string sco_id, out StatusInfo iStatus) { iStatus = new StatusInfo(); XmlDocument xDoc = _ProcessRequest("sco-contents", string.Format("sco-id={0}", sco_id), out iStatus); if (iStatus.Code != StatusCodes.ok || xDoc == null || !xDoc.HasChildNodes) return null; XmlNodeList MeetingDetailNodes = xDoc.SelectNodes("//sco"); if (MeetingDetailNodes == null || MeetingDetailNodes.Count < 1) { iStatus = ReportStatus(StatusCodes.no_data, StatusSubCodes.not_set, new ArgumentNullException("Node 'sco' is empty")); return null; } else { return MeetingDetailNodes; } }
private XmlDocument _ProcessRequest(string pAction, string qParams, bool extractSessionCookie, out StatusInfo iStatus) { iStatus = new StatusInfo(); iStatus.Code = StatusCodes.not_set; if (qParams == null) qParams = string.Empty; HttpWebRequest HttpWReq = WebRequest.Create(m_serviceURL + string.Format(@"?action={0}&{1}", pAction, qParams)) as HttpWebRequest; if (HttpWReq == null) return null; try { if (!string.IsNullOrEmpty(this.m_proxyUrl)) { if (!string.IsNullOrEmpty(this.m_netUser) && !string.IsNullOrEmpty(this.m_netPassword)) { HttpWReq.Proxy = new System.Net.WebProxy(this.m_proxyUrl, true); HttpWReq.Proxy.Credentials = new NetworkCredential(this.m_netUser, this.m_netPassword, this.m_netDomain); } } } catch (Exception ex) { TraceTool.TraceException(ex); } //20 sec. timeout: A Domain Name System (DNS) query may take up to 15 seconds to return or time out. HttpWReq.Timeout = 20000 * 60; HttpWReq.Accept = "*/*"; HttpWReq.KeepAlive = false; HttpWReq.CookieContainer = new CookieContainer(); if ((!m_sessionParam) && (!extractSessionCookie)) { if (!string.IsNullOrEmpty(m_SessionInfo) && !string.IsNullOrEmpty(m_SessionDomain)) HttpWReq.CookieContainer.Add(new System.Net.Cookie("BREEZESESSION", this.m_SessionInfo, "/", this.m_SessionDomain)); } HttpWebResponse HttpWResp = null; try { //FIX: invalid SSL passing behavior //(Object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) ServicePointManager.ServerCertificateValidationCallback = delegate { return true; }; HttpWResp = HttpWReq.GetResponse() as HttpWebResponse; if (extractSessionCookie) { if (HttpWResp.Cookies["BREEZESESSION"] != null) { this.m_SessionInfo = HttpWResp.Cookies["BREEZESESSION"].Value; this.m_SessionDomain = HttpWResp.Cookies["BREEZESESSION"].Domain; iStatus.SessionInfo = this.m_SessionInfo; } } Stream receiveStream = HttpWResp.GetResponseStream(); if (receiveStream == null) return null; XmlDocument xDoc = null; using (StreamReader readStream = new StreamReader(receiveStream, Encoding.UTF8)) { string buf = readStream.ReadToEnd(); if (!string.IsNullOrEmpty(buf)) { xDoc = new XmlDocument(); xDoc.Load(new StringReader(buf)); iStatus.InnerXml = xDoc.InnerXml; object var = this.ReflectEnum(typeof(StatusCodes), xDoc.SelectSingleNode("//status/@code").Value); if (var != null) iStatus.Code = (StatusCodes)var; switch (iStatus.Code) { case StatusCodes.invalid: //there is not always an invalid child element XmlNode node = xDoc.SelectSingleNode("//invalid"); if (node != null) { iStatus.SubCode = (StatusSubCodes)this.ReflectEnum(typeof(StatusSubCodes), node.Attributes["subcode"].Value); iStatus.InvalidField = node.Attributes["field"].Value; } break; case StatusCodes.no_access: iStatus.SubCode = (StatusSubCodes)this.ReflectEnum(typeof(StatusSubCodes), xDoc.SelectSingleNode("//status/@subcode").Value); break; default: break; } } } return xDoc; } catch (Exception ex) { HttpWReq.Abort(); TraceTool.TraceException(ex); iStatus.UndeliningExceptionInfo = ex; } finally { if (HttpWResp != null) HttpWResp.Close(); } return null; }
/// <summary> /// Returns a list of SCOs within another SCO. The enclosing SCO can be a folder, meeting, or /// curriculum. /// In general, the contained SCOs can be of any type—meetings, courses, curriculums, content, /// events, folders, trees, or links (see the list in type). However, the type of the contained SCO /// needs to be valid for the enclosing SCO. For example, courses are contained within /// curriculums, and meeting content is contained within meetings. /// Because folders are SCOs, the returned list includes SCOs and subfolders at the next /// hierarchical level, but not the contents of the subfolders. To include the subfolder contents, /// call sco-expanded-contents. /// </summary> /// <param name="sco_id">Room/Folder ID</param> /// <param name="iStatus">status response object returned</param> /// <returns><see cref="MeetingItem">MeetingItem</see> array</returns> public MeetingItem[] GetMeetingsInRoom(string sco_id, out StatusInfo iStatus) { //act: "sco-contents" iStatus = new StatusInfo(); XmlDocument xDoc = _ProcessRequest("sco-contents", string.Format("sco-id={0}", sco_id), out iStatus); if (iStatus.Code != StatusCodes.ok || xDoc == null || !xDoc.HasChildNodes) return null; XmlNodeList MeetingDetailNodes = xDoc.SelectNodes("//sco"); if (MeetingDetailNodes == null || MeetingDetailNodes.Count < 1) { //iStatus = ReportStatus(StatusCodes.no_data, StatusSubCodes.not_set, new ArgumentNullException("Node 'sco' is empty")); TraceTool.TraceMessage("Node 'sco' is empty: no data available for sco-id=" + sco_id); return null; } List<MeetingItem> lstDetails = new List<MeetingItem>(); foreach (XmlNode node in MeetingDetailNodes) { try { MeetingItem mDetail = new MeetingItem(); mDetail.sco_id = node.Attributes["sco-id"].Value; mDetail.folder_id = node.Attributes["folder-id"].Value; if (!bool.TryParse(node.Attributes["is-folder"].Value, out mDetail.is_folder)) mDetail.is_folder = false; if (node.Attributes["byte-count"] != null) if (!long.TryParse(node.Attributes["byte-count"].Value, NumberStyles.Number, NumberFormatInfo.InvariantInfo, out mDetail.byte_count)) mDetail.byte_count = -1; if (node.Attributes["lang"] != null) mDetail.language = node.Attributes["lang"].Value; if (node.Attributes["type"] != null) mDetail.type = (SCOtype)ReflectEnum(typeof(SCOtype), node.Attributes["type"].Value); if (node.SelectSingleNode("name/text()") != null) mDetail.meeting_name = node.SelectSingleNode("name/text()").Value; if (node.SelectSingleNode("description/text()") != null) mDetail.meeting_description = node.SelectSingleNode("description/text()").Value; if (node.SelectSingleNode("sco-tag/text()") != null) mDetail.sco_tag = node.SelectSingleNode("sco-tag/text()").Value; mDetail.url_path = node.SelectSingleNode("url-path/text()").Value; // if (!string.IsNullOrEmpty(mDetail.url_path)) { Uri u = new Uri(m_serviceURL); mDetail.FullUrl = "https://" + u.GetComponents(UriComponents.Host, UriFormat.SafeUnescaped) + mDetail.url_path; } //NOTE: if folder => date-begin is null if (node.SelectSingleNode("date-begin/text()") != null) if (!DateTime.TryParseExact(node.SelectSingleNode("date-begin/text()").Value, @"yyyy-MM-dd\THH:mm:ss.fffzzz", DateTimeFormatInfo.InvariantInfo, DateTimeStyles.AdjustToUniversal, out mDetail.date_begin)) mDetail.date_begin = default(DateTime); if (!DateTime.TryParseExact(node.SelectSingleNode("date-modified/text()").Value, @"yyyy-MM-dd\THH:mm:ss.fffzzz", DateTimeFormatInfo.InvariantInfo, DateTimeStyles.AdjustToUniversal, out mDetail.date_modified)) mDetail.date_modified = default(DateTime); if (node.SelectSingleNode("date-end/text()") != null) if (!DateTime.TryParseExact(node.SelectSingleNode("date-end/text()").Value, @"yyyy-MM-dd\THH:mm:ss.fffzzz", DateTimeFormatInfo.InvariantInfo, DateTimeStyles.AdjustToUniversal, out mDetail.date_end)) mDetail.date_end = default(DateTime); mDetail.Duration = mDetail.date_end.Subtract(mDetail.date_begin); //if mDetail.date_begin is not defined and duration is 0 => then this is the folder which should be ignored if (mDetail.date_begin.Equals(default(DateTime)) && mDetail.Duration.TotalMinutes == 0) continue; lstDetails.Add(mDetail); } catch (Exception ex) { TraceTool.TraceException(ex); } } return lstDetails.ToArray(); }
private XmlDocument _ProcessRequest(string pAction, string qParams, out StatusInfo iStatus) { //Single sign on (SSO) implementation can be done via passing session info information as ""?session=" parameter to the Adobe Connect event url. if (m_sessionParam) { if (String.IsNullOrEmpty(qParams)) { qParams = "session=" + m_SessionInfo; } else { qParams = String.Concat("session=", m_SessionInfo, @"&", qParams); } } return this._ProcessRequest(pAction, qParams, false, out iStatus); }
StatusInfo ReportStatus(StatusCodes code, StatusSubCodes subCode, Exception exInfo) { StatusInfo iStatus = new StatusInfo(); iStatus.Code = code; iStatus.SubCode = subCode; iStatus.UndeliningExceptionInfo = exInfo; return iStatus; }
/// <summary> /// Provides information about all users who have taken a quiz in a training. Use a sco-id to /// identify the quiz. /// To reduce the volume of the response, use any allowed filter or pass a type parameter to /// return information about just one type of SCO (courses, presentations, or meetings). /// </summary> /// <returns>Raw contents as <see cref="XmlNodeList"/></returns> public XmlNodeList Report_QuizTakers(string sco_id, string filter_by, out StatusInfo iStatus) { XmlDocument xDoc = _ProcessRequest("report-quiz-takers", string.Format("sco-id={0}&{1}", sco_id, filter_by), out iStatus); if (iStatus.Code != StatusCodes.ok || xDoc == null || !xDoc.HasChildNodes) return null; XmlNodeList transNodes = xDoc.SelectNodes("//row"); if (transNodes == null || transNodes.Count < 1) return null; return transNodes; }
/// <summary> /// Returns information about principal-to-SCO transactions on your server or in your hosted account. /// A transaction is an instance of one principal visiting one SCO. The SCO can be an Acrobat /// Connect Professional meeting, course, document, or any content on the server. /// Note: this call to report-bulk-consolidated-transactions, with filter-type=meeting, returns only /// users who logged in to the meeting as participants, not users who entered the meeting as guests. /// </summary> /// <returns><see cref="TransactionInfo">TransactionInfo</see> array</returns> public TransactionInfo[] Report_ConsolidatedTransactions(string filter_by, out StatusInfo iStatus) { XmlDocument xDoc = _ProcessRequest("report-bulk-consolidated-transactions", filter_by, out iStatus); if (iStatus.Code != StatusCodes.ok || xDoc == null || !xDoc.HasChildNodes) return null; XmlNodeList transNodes = xDoc.SelectNodes("//row"); if (transNodes == null || transNodes.Count < 1) return null; List<TransactionInfo> tInfoList = new List<TransactionInfo>(); foreach (XmlNode node in transNodes) { TransactionInfo ti = new TransactionInfo(); try { ti.transaction_id = node.Attributes["transaction-id"].Value; ti.sco_id = node.Attributes["sco-id"].Value; ti.principal_id = node.Attributes["principal-id"].Value; if (node.Attributes["type"] != null) ti.type = (SCOtype)ReflectEnum(typeof(SCOtype), node.Attributes["type"].Value); ti.score = node.Attributes["score"].Value; ti.name = node.SelectSingleNode("name/text()").Value; ti.url = node.SelectSingleNode("url/text()").Value; ti.login = node.SelectSingleNode("login/text()").Value; ti.user_name = node.SelectSingleNode("user-name/text()").Value; if (node.SelectSingleNode("status/text()") != null) { ti.status = node.SelectSingleNode("status/text()").Value; //ti.status = (StatusCodes)ReflectEnum(typeof(StatusCodes), node.SelectSingleNode("status/text()").Value); } if (!DateTime.TryParseExact(node.SelectSingleNode("date-created/text()").Value, @"yyyy-MM-dd\THH:mm:ss.fffzzz", DateTimeFormatInfo.InvariantInfo, DateTimeStyles.AdjustToUniversal, out ti.date_created)) ti.date_created = default(DateTime); if (!DateTime.TryParseExact(node.SelectSingleNode("date-closed/text()").Value, @"yyyy-MM-dd\THH:mm:ss.fffzzz", DateTimeFormatInfo.InvariantInfo, DateTimeStyles.AdjustToUniversal, out ti.date_closed)) ti.date_closed = default(DateTime); tInfoList.Add(ti); } catch (Exception ex) { TraceTool.TraceException(ex); } } return tInfoList.ToArray(); }
/// <summary> /// Returns bulk questions information /// </summary> /// <param name="filter_by">optional 'filter by' params</param> /// <param name="iStatus">status response object returned</param> /// <returns>Raw contents as <see cref="XmlNodeList"/></returns> public XmlNodeList Report_BulkQuestions(string filter_by, out StatusInfo iStatus) { XmlDocument xDoc = _ProcessRequest("report-bulk-questions", string.Format("{0}", filter_by), out iStatus); if (iStatus.Code != StatusCodes.ok || xDoc == null || !xDoc.HasChildNodes) return null; XmlNodeList transNodes = xDoc.SelectNodes("//row"); if (transNodes == null || transNodes.Count < 1) return null; return transNodes; }