/// <summary> /// Starts a session and returns user API method capabilities -- which features the given user can and cannot use. /// http://www.sendspace.com/dev_method.html?method=auth.login /// </summary> /// <param name="token">Received on create token</param> /// <param name="username">Registered user name</param> /// <param name="password">Registered password</param> /// <returns>Account informations including session key</returns> public LoginInfo AuthLogin(string token, string username, string password) { Dictionary<string, string> args = new Dictionary<string, string>(); args.Add("method", "auth.login"); args.Add("token", token); args.Add("user_name", username); // lowercase(md5(token+lowercase(md5(password)))) - md5 values should always be lowercase. string passwordHash = TranslatorHelper.TextToHash(password, HashType.MD5); args.Add("tokened_password", TranslatorHelper.TextToHash(token + passwordHash, HashType.MD5)); string response = SendPostRequest(APIURL, args); if (!string.IsNullOrEmpty(response)) { ResponsePacket packet = ParseResponse(response); if (!packet.Error) { LoginInfo loginInfo = new LoginInfo(packet.Result); return loginInfo; } } return null; }
// upload a file using the web form instead of the API (for old versions of WikiMedia which don't have the upload API) private void UploadFileThroughForm(LoginInfo loginInfo, string localFilePath, string remoteFilename) { UploadFile[] files = new UploadFile[] { new UploadFile(localFilePath, "wpUploadFile", "application/octet-stream") }; HttpWebRequest request = (HttpWebRequest)WebRequest.Create(GetUrl("Special:Upload")); request.CookieContainer = loginInfo.Cookies; var parameters = new System.Collections.Specialized.NameValueCollection(); parameters["wpSourceType"] = "file"; parameters["wpDestFile"] = remoteFilename; parameters["wpUpload"] = "Upload file"; var response = HttpUploadHelper.Upload(request, files, parameters); string strResponse = new StreamReader(response.GetResponseStream()).ReadToEnd(); if (strResponse.Contains("A file with this name exists already")) throw new MediaWikiException("Image already exists on the wiki"); }
// upload a file using the MediaWiki upload API private void UploadFile(string editToken, LoginInfo loginInfo, string localFilePath, string remoteFilename) { UploadFile[] files = new UploadFile[] { new UploadFile(localFilePath, "file", "application/octet-stream") }; HttpWebRequest request = (HttpWebRequest)WebRequest.Create(GetApiUrl()); request.CookieContainer = loginInfo.Cookies; var parameters = new System.Collections.Specialized.NameValueCollection(); parameters["format"] = "xml"; parameters["action"] = "upload"; parameters["filename"] = Path.GetFileName(localFilePath); parameters["token"] = editToken; var response = HttpUploadHelper.Upload(request, files, parameters); string strResponse = new StreamReader(response.GetResponseStream()).ReadToEnd(); if (strResponse.StartsWith("unknown_action")) { // fallback : upload using web form UploadFileThroughForm(loginInfo, localFilePath, remoteFilename); return; } try { XmlDocument xmlDoc = new XmlDocument(); xmlDoc.LoadXml(strResponse); var element = xmlDoc.GetElementsByTagName("api")[0].ChildNodes[0]; if (element.Name == "error") { string errorCode = element.Attributes["code"].Value; string errorMessage = element.Attributes["info"].Value; throw new MediaWikiException("Error uploading to MediaWiki: " + errorCode + "\r\n" + errorMessage); } string result = element.Attributes["result"].Value; if (result == "Warning") { foreach (XmlNode child in element.ChildNodes) { if (child.Name == "warnings") { if (child.Attributes["exists"] != null) { string existingImageName = child.Attributes["exists"].Value; throw new MediaWikiException("Image already exists on the wiki: " + existingImageName); } } } } if (result != "Success") throw new MediaWikiException("Error uploading to MediaWiki:\r\n" + result); } catch (XmlException) { throw new MediaWikiException("Unexpected answer while uploading:\r\n" + strResponse); } }
// query an edit token (needed for upload) after logging in private string QueryEditToken(LoginInfo loginInfo) { string strResponse; try { string postData = "format=xml&action=query&prop=info&intoken=edit&titles=Foo"; ASCIIEncoding encoding = new ASCIIEncoding(); byte[] postBytes = encoding.GetBytes(postData); HttpWebRequest request = (HttpWebRequest)WebRequest.Create(GetApiUrl()); request.Method = WebRequestMethods.Http.Post; request.ContentType = "application/x-www-form-urlencoded"; request.ContentLength = postBytes.Length; request.CookieContainer = loginInfo.Cookies; Stream postStream = request.GetRequestStream(); postStream.Write(postBytes, 0, postBytes.Length); postStream.Close(); var response = request.GetResponse(); strResponse = new StreamReader(response.GetResponseStream()).ReadToEnd(); } catch (Exception e) { throw new MediaWikiException("Error getting edit token:\r\n" + e.Message); } try { XmlDocument xmlDoc = new XmlDocument(); xmlDoc.LoadXml(strResponse); var pageElement = xmlDoc.GetElementsByTagName("api")[0].ChildNodes[0].ChildNodes[0].ChildNodes[0]; string edittoken = pageElement.Attributes["edittoken"].Value; return edittoken; } catch (Exception) { throw new MediaWikiException("Unexpected answer while querying edit token from MediaWiki:\r\n" + strResponse); } }
// login with the token from a first login attempt (if it returned "NeedToken") private void LoginWithToken(LoginInfo loginInfo) { string postData = string.Format("format=xml&action=login&lgname={0}&lgpassword={1}&lgtoken={2}", Options.Account.Username, Options.Account.Password, loginInfo.Token); ASCIIEncoding encoding = new ASCIIEncoding(); byte[] postBytes = encoding.GetBytes(postData); HttpWebRequest request = (HttpWebRequest)WebRequest.Create(GetApiUrl()); request.Method = WebRequestMethods.Http.Post; request.ContentType = "application/x-www-form-urlencoded"; request.ContentLength = postBytes.Length; request.CookieContainer = loginInfo.Cookies; Stream postStream = request.GetRequestStream(); postStream.Write(postBytes, 0, postBytes.Length); postStream.Close(); var response = request.GetResponse(); string strResponse = new StreamReader(response.GetResponseStream()).ReadToEnd(); try { XmlDocument xmlDoc = new XmlDocument(); xmlDoc.LoadXml(strResponse); var loginElement = xmlDoc.GetElementsByTagName("api")[0].ChildNodes[0]; string result = loginElement.Attributes["result"].Value; if (result != "Success") HandleError(result); } catch (XmlException) { throw new MediaWikiException("Unexpected answer:\r\n" + strResponse); } }
// login private LoginInfo Login1(LoginInfo loginInfo) { string postData = string.Format("format=xml&action=login&lgname={0}&lgpassword={1}", Options.Account.Username, Options.Account.Password); ASCIIEncoding encoding = new ASCIIEncoding(); byte[] postBytes = encoding.GetBytes(postData); HttpWebRequest request = (HttpWebRequest)WebRequest.Create(GetApiUrl()); request.Method = WebRequestMethods.Http.Post; request.ContentType = "application/x-www-form-urlencoded"; request.ContentLength = postBytes.Length; request.AllowAutoRedirect = true; var cookieContainer = loginInfo.Cookies ?? new CookieContainer(); request.CookieContainer = cookieContainer; Stream postStream = request.GetRequestStream(); postStream.Write(postBytes, 0, postBytes.Length); postStream.Close(); var response = request.GetResponse(); string strResponse = new StreamReader(response.GetResponseStream()).ReadToEnd(); // redirected to another page if (strResponse.StartsWith("<!DOCTYPE html")) { if (loginInfo.Redirected) { throw new MediaWikiException("Still could not log in after redirection"); } var uri = response.ResponseUri; LoginInfo newLoginInfo = LoginRedirected(uri); return Login1(newLoginInfo); } try { XmlDocument xmlDoc = new XmlDocument(); xmlDoc.LoadXml(strResponse); var loginElement = xmlDoc.GetElementsByTagName("api")[0].ChildNodes[0]; string result = loginElement.Attributes["result"].Value; string token = (loginElement.Attributes["token"] ?? loginElement.Attributes["lgtoken"]).Value; bool needToken; if (result == "Success") needToken = false; else if (result == "NeedToken") needToken = true; else { HandleError(result); // should not happen since HandleError always throws an exception throw new Exception("Error not handled"); } return new LoginInfo() { Token = token, Cookies = cookieContainer, NeedToken = needToken }; } catch (XmlException) { throw new MediaWikiException("unexpected answer:\r\n" + strResponse); } }