В данном способе создания нод будут использоваться модули Key Authentication, XMLRPC Server, Node Service и User Service из решения Drupal Services 6.x-2.2 (выбрал 6.x-2.2 как наиболее безглючную)
Подключаем их, далее идем в панели Administer › Site building › Services Administer › Site building › Services, жмем “Создать ключ”, задаем название, указываем что-нибудь в поле “Allowed domain” и выбираем разрешенные методы – в моем случае это system.connect, user.login и node.save. В настройках модуля Services выбираем тип авторизации – “Key Authentication”.
Скачиваем библиотеку XML-RPC, компилим ее и добавляем в ссылки проекта VS2008 файл CookComputing.XmlRpcV2.dll, в using добавляем CookComputing.XmlRpc и System.Security.Cryptography.
Внутри класса добавляем:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
[XmlRpcMissingMapping(MappingAction.Ignore)] public struct DrupalUser { public string name; public string email; } public struct Drupal { public string sessid; public DrupalUser user; } [XmlRpcUrl("http://0x2.dev/services/xmlrpc")] public interface IServiceSystem : IXmlRpcProxy { [XmlRpcMethod("node.save")] string NodeSave(string hash, string domain_name, string domain_time_stamp, string nonce, string sessid, XmlRpcStruct node); [XmlRpcMethod("system.connect")] Drupal Connect(); [XmlRpcMethod("user.login")] Drupal Login(string hash, string timestamp, string domain, string nonce, string sessid, string username, string password); } |
Создание ноды будем производить, скажем, по нажатию кнопки, обработчик будет такой:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
private void button1_Click(object sender, EventArgs e) { IServiceSystem iss = XmlRpcProxyGen.Create<IServiceSystem>(); Drupal cnct = iss.Connect(); // сначала выполняем подключение string timestamp = GetUnixTimestamp(); string nonce = GetNonce(10); string domain = "domain"; string key = "s5741111141bbe123b211e77ccf4ca304"; // api key берем созданный нами на сайте StringBuilder sb = new StringBuilder(); sb.Append(timestamp); sb.Append(";"); sb.Append(domain); sb.Append(";"); sb.Append(nonce); sb.Append(";"); sb.Append("user.login"); string hash = GetHMAC(sb.ToString(), key); Drupal lgn = iss.Login(hash, domain, timestamp, nonce, cnct.sessid, "мой_логин", "мой_пароль"); // выполняем вход, используя полученный ранее cnct.sessid // теперь подготавливаем материал к постингу (тип - "Страница") var saveData = new XmlRpcStruct(); saveData["title"] = "Первая страница!"; saveData["body"] = "Некоторый текст"; saveData["field_tseloe"] = 1; // CCK поле saveData["type"] = "page"; // или свой тип nonce = GetNonce(10); hash = GetHMAC(timestamp + ";" + domain + ";" + nonce + ";node.save", key); iss.NodeSave(hash, domain, timestamp, nonce, lgn.sessid, saveData); } |
Дополнительные функции:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
public string GetUnixTimestamp() { TimeSpan ts = (DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0)); return Convert.ToString(Convert.ToUInt64(ts.TotalSeconds)); } // Similar to the 'user_password' function Drupal uses. public string GetNonce(int length) { string allowedCharacters = "abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ23456789"; StringBuilder password = new StringBuilder(); Random rand = new Random(); for (int i = 0; i < length; i++) { password.Append(allowedCharacters[rand.Next(0, (allowedCharacters.Length - 1))]); } return password.ToString(); } // вычисление SHA256 public string GetHMAC(string message, string key) { System.Text.ASCIIEncoding encoding = new System.Text.ASCIIEncoding(); byte[] keyByte = encoding.GetBytes(key); byte[] messageByte = encoding.GetBytes(message); HMACSHA256 hmac = new HMACSHA256(keyByte); byte[] hashMessageByte = hmac.ComputeHash(messageByte); string sbinary = String.Empty; for (int i = 0; i < hashMessageByte.Length; i++) { // Converting to hex, but using lowercase 'x' to get lowercase characters sbinary += hashMessageByte[i].ToString("x2"); } return sbinary; } |
Из-за string CCK-полей VS у меня ругалась “Response from server does not contain valid xml” и “Существует несколько корневых элементов” (“There are multiple root elements”). Fiddler показал ошибку “Cannot unset string offsets”.
Исправил применением патча
1 2 3 4 5 6 |
- unset($items[$field['field_name'] .'_add_more']); + if (is_array($items)) { + if(!empty($items[$field['field_name'] .'_add_more'])) { + unset($items[$field['field_name'] .'_add_more']); + } + } |
к файлу /sites/all/modules/cck/includes/content.node_form.inc
Скачать проект Visual Studio 2008: drU-XRPC.cab
05.03.2010
MolineSoftware.DrupalXmlRpc_V2.0.cab, можете скачать. Объявляйте-добавляйте в CustomNode.cs свои CCK-поля:
08.06.2010
23.07.2010
01.09.2012
30.04.2013
09.05.2013
28.02.2014
21.03.2016