Exemplo n.º 1
0
        /// <summary>
        /// Asynchroniously invoke VK API method and get response as XML.
        /// </summary>
        /// <param name="xmlMethodName">API method name, '.xml' added automatically</param>
        /// <param name="methodCallArguments">Arguments to call method. May be empty.</param>
        /// <param name="sendToken">Send access_token, or not.</param>
        /// <returns>Response, if no error.</returns>
        /// <exception cref="VK9.VK.APIException">Server returned an error.</exception>
        public async Task<XmlElement> AsyncXmlMethodCall(string xmlMethodName, NameValueCollection methodCallArguments, bool sendToken = true)
        {
            // Request rate limit
            BeginAnotherRequest();

        _pendingCaptcha:
            if (pendingCaptchaKey != null)
            {
                if (pendingCaptchaKey.IsSolved)
                {
                    // Append args with solved captcha key
                    methodCallArguments.Add("captcha_sid", pendingCaptchaKey.ID);
                    methodCallArguments.Add("captcha_key", pendingCaptchaKey.SolveKey);
                }

                // HACK! It seems that server does not like token sent with captcha key at one time
                // But what about method call result without token?
                sendToken = false;
                pendingCaptchaKey = null;
            }

            // Https?
            string url = string.Format("{0}://{1}",
                HostSession.IsHttpsEnabled ? "https" : "http",
                ServerHost);

            // Do we need to add access_token to arguments?
            if (sendToken)
                methodCallArguments.Add("access_token", HostSession.Token.Value);

            // Append url with query string
            var query_s = ToQueryString(methodCallArguments, true);
            url += string.Format("/method/{0}.xml{1}",
                xmlMethodName, !string.IsNullOrEmpty(query_s) ? "?" + query_s : string.Empty);

            // Do we need to sign the request?
            if (!HostSession.IsHttpsEnabled)
            {
                // Build sign_hash argument
                query_s = ToQueryString(methodCallArguments, false);
                string sig_url_s = string.Format("/method/{0}.xml{1}{2}",
                    xmlMethodName,
                    !string.IsNullOrEmpty(query_s) ? "?" + query_s : string.Empty,
                    HostSession.Secret);

                // Generate sign
                byte[] sig = null;
                using (var md5 = MD5.Create())
                    sig = md5.ComputeHash(Encoding.UTF8.GetBytes(sig_url_s));

                // Append url with digest
                url += "&sig=";
                for (int i = 0; i < sig.Length; i++)
                    url += sig[i].ToString("x2");
            }

            // Do HTTP request
            string response_xml = await AsyncHttpGetString(url);

            // Parse XML data
            var xml = new XmlDocument();
            xml.LoadXml(response_xml);

            // Parse error info, if there is an error
            if (xml["error"] != null)
            {
                // Get error message
                XmlElement e = xml["error"]["error_msg"];
                string msg = e != null
                    ? e.InnerText
                    : "Error description is unspecified.";

                // Parse error code
                e = xml["error"]["error_code"];
                var code = e != null
                    ? (VK.APIError)uint.Parse(e.InnerText)
                    : VK.APIError.UnspecifiedUnsupported;

                // Captcha validation needed?
                if (code == VK.APIError.CaptchaNeeded)
                {
                    // Remove captcha key from previous validation attempt
                    methodCallArguments.Remove("captcha_sid");
                    methodCallArguments.Remove("captcha_key");

                    // Trigger captcha validation
                    var eventData = VKSession.TriggerCaptchaNeeded(HostSession, new Uri(xml["error"]["captcha_img"].InnerText), xml["error"]["captcha_sid"].InnerText);

                    // Send the request again with/out captcha validation
                    if (eventData.Retry || eventData.IsSolved)
                    {
                        pendingCaptchaKey = eventData;
                        goto _pendingCaptcha;
                    }
                }

                // Throw error
                throw new VK.APIException(HostSession, xmlMethodName, msg, code, xml["error"]["request_params"], null);
            }
            else
            {
                // Done
                return xml["response"];
            }
        }
Exemplo n.º 2
0
        /// <summary>
        /// Allows you to set captcha solution for next API request (used for delayed captcha validation).
        /// </summary>
        /// <param name="captchaKey">Captcha key</param>
        public void SetCaptchaKey(VK.CaptchaEventArgs captchaKey)
        {
            if (captchaKey != null && (!captchaKey.IsSolved || !captchaKey.IsValidCaptcha))
                throw new ArgumentException("Specified captchaKey is not valid or not solved'.");

            pendingCaptchaKey = captchaKey;
        }
Exemplo n.º 3
0
 /// <summary>
 /// Triggers CaptchaNeeded event.
 /// </summary>
 public static VK.CaptchaEventArgs TriggerCaptchaNeeded(VKSession self, Uri img, string sid)
 {
     var eventData = new VK.CaptchaEventArgs(img, sid);
     if (self.CaptchaNeeded != null)
         self.CaptchaNeeded(self, eventData);
     return eventData;
 }