В данном способе создания нод будут использоваться модули 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.NET, компилим ее и добавляем в ссылки проекта 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 |
[XmlRpcMissingMapping(MappingAction.Ignore)] public struct DrupalUser { public string name; public string email; } public struct Drupal { public string sessid; public DrupalUser user; } [XmlRpcUrl("http://sap.sd/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 |
private void button1_Click(object sender, EventArgs e) { IServiceSystem iss = XmlRpcProxyGen.Create(); 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 |
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']); + } + } |
P.S.
В случае проблем с CCK-полями советую использовать библиотеку DrupalXmlRpc.NET, скопировал ее и пример использования сюда:
- DrupalXmlRpc.NET_Demo
- MolineSoftware.DrupalXmlRpc_V2.0 , можете скачать.
Объявляйте-добавляйте в CustomNode.cs свои CCK-поля:
12345[XmlRpcMember(Member = "ma_CCK_field")]public XmlRpcStruct[] MaCCK_ImportntDatta { get; set; }// но для Path тип - string:[XmlRpcMember(Member = "path")]public string Path_URLalias { get; set; }
Скачать проект Visual Studio 2008: drU-XRPC.cab
16.12.2014
16.12.2014
16.12.2014
16.12.2014
16.12.2014
16.12.2014
16.12.2014