XmppMessenger.cs 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Text;
  4. using System.IO;
  5. using System.Net.Sockets;
  6. using System.Net.Security;
  7. using System.Security.Cryptography.X509Certificates;
  8. using System.Xml;
  9. using System.Globalization;
  10. using FastReport.Export;
  11. using FastReport.Cloud;
  12. using FastReport.Cloud.StorageClient.FastCloud;
  13. using FastReport.Messaging.Authentication.Sasl;
  14. using FastReport.Utils;
  15. namespace FastReport.Messaging.Xmpp
  16. {
  17. /// <summary>
  18. /// Represents the XMPP messenger.
  19. /// </summary>
  20. public class XmppMessenger : MessengerBase, IDisposable
  21. {
  22. #region Constants
  23. private const int DEFAULT_PORT_NUMBER = 5222;
  24. private const int DEFAULT_CHUNK_SIZE = 4096;
  25. private const string DEFAULT_RESOURCE = "frnet";
  26. private const string DEFAULT_SESSION_ID = "frnet_session_0";
  27. #endregion // Constants
  28. #region Fields
  29. private string username;
  30. private string password;
  31. private string hostname;
  32. private int port;
  33. private string sendToUsername;
  34. private TcpClient client;
  35. private Stream stream;
  36. private StreamParser parser;
  37. private bool connected;
  38. private bool authenticated;
  39. private bool disposed;
  40. private string sessionId;
  41. private string jidFrom;
  42. private string jidTo;
  43. private int chunkSize;
  44. #endregion // Fields
  45. #region Properties
  46. /// <summary>
  47. /// Gets or sets the username.
  48. /// </summary>
  49. public string Username
  50. {
  51. get { return username; }
  52. set { username = value; }
  53. }
  54. /// <summary>
  55. /// Gets or sets the user's password.
  56. /// </summary>
  57. public string Password
  58. {
  59. get { return password; }
  60. set { password = value; }
  61. }
  62. /// <summary>
  63. /// Gets or sets the hostname of XMPP server.
  64. /// </summary>
  65. public string Hostname
  66. {
  67. get { return hostname; }
  68. set { hostname = value; }
  69. }
  70. /// <summary>
  71. /// Gets or sets the port number of the XMPP service of the server.
  72. /// </summary>
  73. public int Port
  74. {
  75. get { return port; }
  76. set { port = value; }
  77. }
  78. /// <summary>
  79. /// Gets or sets the username to send file to.
  80. /// </summary>
  81. public string SendToUsername
  82. {
  83. get { return sendToUsername; }
  84. set { sendToUsername = value; }
  85. }
  86. /// <summary>
  87. /// Gets or sets the JID to send from.
  88. /// </summary>
  89. public string JidFrom
  90. {
  91. get { return jidFrom; }
  92. set
  93. {
  94. jidFrom = value;
  95. if (!String.IsNullOrEmpty(jidFrom))
  96. {
  97. int jidFromAtPosition = jidFrom.IndexOf("@");
  98. this.username = jidFrom.Substring(0, jidFromAtPosition);
  99. this.hostname = jidFrom.Substring(jidFromAtPosition + 1, jidFrom.Length - jidFromAtPosition - 1);
  100. }
  101. }
  102. }
  103. /// <summary>
  104. /// Gets or set the JID to send to.
  105. /// </summary>
  106. public string JidTo
  107. {
  108. get { return jidTo; }
  109. set
  110. {
  111. jidTo = value;
  112. if (!String.IsNullOrEmpty(jidTo))
  113. {
  114. int jidToAtPosition = jidTo.IndexOf("@");
  115. this.sendToUsername = jidTo.Substring(0, jidToAtPosition);
  116. }
  117. }
  118. }
  119. #endregion // Properties
  120. #region Constructors
  121. /// <summary>
  122. /// Initializes a new instance of the <see cref="XmppMessenger"/> class.
  123. /// </summary>
  124. public XmppMessenger()
  125. {
  126. username = "";
  127. password = "";
  128. hostname = "";
  129. port = DEFAULT_PORT_NUMBER;
  130. sendToUsername = "";
  131. client = null;
  132. stream = null;
  133. parser = null;
  134. connected = false;
  135. authenticated = false;
  136. disposed = false;
  137. sessionId = DEFAULT_SESSION_ID;
  138. jidFrom = "";
  139. jidTo = "";
  140. chunkSize = DEFAULT_CHUNK_SIZE;
  141. }
  142. /// <summary>
  143. /// Initializes a new instance of the <see cref="XmppMessenger"/> class with specified parameters.
  144. /// </summary>
  145. /// <param name="username">Username.</param>
  146. /// <param name="password">Password.</param>
  147. /// <param name="hostname">Hostname.</param>
  148. /// <param name="port">Port.</param>
  149. /// <param name="sendToUsername">Username to send file to.</param>
  150. /// <param name="sendToResource">Send to user's resource.</param>
  151. public XmppMessenger(string username, string password, string hostname, int port, string sendToUsername, string sendToResource)
  152. {
  153. this.username = username;
  154. this.password = password;
  155. this.hostname = hostname;
  156. this.port = port;
  157. this.sendToUsername = sendToUsername;
  158. client = null;
  159. stream = null;
  160. parser = null;
  161. connected = false;
  162. authenticated = false;
  163. disposed = false;
  164. sessionId = DEFAULT_SESSION_ID;
  165. jidFrom = username + "@" + hostname + "/" + DEFAULT_RESOURCE;
  166. jidTo = sendToUsername + "@" + hostname + "/" + sendToResource;
  167. chunkSize = DEFAULT_CHUNK_SIZE;
  168. }
  169. /// <summary>
  170. /// Initializes a new instance of the <see cref="XmppMessenger"/> class with specified parameters.
  171. /// </summary>
  172. /// <param name="jidFrom">User's JID without resource.</param>
  173. /// <param name="password">User's password.</param>
  174. /// <param name="jidTo">JID to send to with resource.</param>
  175. public XmppMessenger(string jidFrom, string password, string jidTo)
  176. {
  177. this.port = DEFAULT_PORT_NUMBER;
  178. client = null;
  179. stream = null;
  180. parser = null;
  181. connected = false;
  182. authenticated = false;
  183. disposed = false;
  184. sessionId = DEFAULT_SESSION_ID;
  185. if (!String.IsNullOrEmpty(jidFrom))
  186. {
  187. jidFrom += "/" + DEFAULT_RESOURCE;
  188. }
  189. JidFrom = jidFrom;
  190. this.password = password;
  191. JidTo = jidTo;
  192. chunkSize = DEFAULT_CHUNK_SIZE;
  193. }
  194. #endregion // Constructors
  195. #region Private Methods
  196. /// <summary>
  197. /// Sends the specified string to the server.
  198. /// </summary>
  199. /// <param name="str">The string to send.</param>
  200. private void SendString(string str)
  201. {
  202. byte[] buffer = Encoding.UTF8.GetBytes(str);
  203. try
  204. {
  205. stream.Write(buffer, 0, buffer.Length);
  206. }
  207. catch
  208. {
  209. connected = false;
  210. }
  211. }
  212. /// <summary>
  213. /// Initiates the stream to the server.
  214. /// </summary>
  215. /// <param name="hostname">The hostname.</param>
  216. /// <returns>The features response of the server.</returns>
  217. private XmlElement InitiateStream(string hostname)
  218. {
  219. XmlElement xml = Xml.CreateElement("stream:stream", "jabber:client");
  220. Xml.AddAttribute(xml, "from", jidFrom);
  221. Xml.AddAttribute(xml, "to", hostname);
  222. Xml.AddAttribute(xml, "version", "1.0");
  223. Xml.AddAttribute(xml, "xml:lang", "en");
  224. Xml.AddAttribute(xml, "xmlns", "jabber:client");
  225. Xml.AddAttribute(xml, "xmlns:stream", "http://etherx.jabber.org/streams");
  226. string str = Xml.ToXmlString(xml, true, true);
  227. SendString(str);
  228. if (parser != null)
  229. {
  230. parser.Close();
  231. }
  232. parser = new StreamParser(stream, true);
  233. return parser.ReadNextElement(new List<string>(new string[] { "stream:features" }));
  234. }
  235. /// <summary>
  236. /// Validates the server certificate.
  237. /// </summary>
  238. /// <param name="sender">The sender object.</param>
  239. /// <param name="certificate">X509 certificate.</param>
  240. /// <param name="chain">The X509 chain.</param>
  241. /// <param name="sslPolicyErrors">The SSL policy errors.</param>
  242. /// <returns>True if successfull.</returns>
  243. public static bool ValidateServerCertificate(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
  244. {
  245. if (sslPolicyErrors != SslPolicyErrors.None)
  246. {
  247. return false;
  248. }
  249. return true;
  250. }
  251. /// <summary>
  252. /// Secures the stream by TLS.
  253. /// </summary>
  254. /// <param name="hostname">The hostname.</param>
  255. /// <returns>The features response of the server.</returns>
  256. private XmlElement StartTls(string hostname)
  257. {
  258. XmlElement xml = Xml.CreateElement("starttls", "urn:ietf:params:xml:ns:xmpp-tls");
  259. SendString("<starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>");
  260. XmlElement proceed = parser.ReadNextElement(new List<string>(new string[] { "proceed" }));
  261. SslStream sslStream = new SslStream(stream, false, new RemoteCertificateValidationCallback(ValidateServerCertificate), null);
  262. sslStream.AuthenticateAsClient(hostname);
  263. stream = sslStream;
  264. return InitiateStream(hostname);
  265. }
  266. /// <summary>
  267. /// Selects the SASL authentication mechanism.
  268. /// </summary>
  269. /// <param name="mechanisms">List of mechanisms.</param>
  270. /// <returns>The string containing mechanism name.</returns>
  271. private string SelectMechanism(List<string> mechanisms)
  272. {
  273. bool hasPlain = false;
  274. bool hasDigestMd5 = false;
  275. foreach (string mechanism in mechanisms)
  276. {
  277. if (!hasPlain)
  278. {
  279. hasPlain = mechanism.ToUpper().Contains(PlainMechanism.MECHANISM_NAME);
  280. }
  281. if (!hasDigestMd5)
  282. {
  283. hasDigestMd5 = mechanism.ToUpper().Contains(DigestMd5Mechanism.MECHANISM_NAME);
  284. }
  285. }
  286. if (hasDigestMd5)
  287. {
  288. return DigestMd5Mechanism.MECHANISM_NAME;
  289. }
  290. else if (hasPlain)
  291. {
  292. return PlainMechanism.MECHANISM_NAME;
  293. }
  294. return null;
  295. }
  296. /// <summary>
  297. /// Authenticates the user on the server using Plain mechanism.
  298. /// </summary>
  299. private void AuthenticateUsingPlainMechanism()
  300. {
  301. XmlElement xml = Xml.CreateElement("auth", "urn:ietf:params:xml:ns:xmpp-sasl");
  302. Xml.AddAttribute(xml, "mechanism", PlainMechanism.MECHANISM_NAME);
  303. Xml.AddText(xml, new PlainMechanism(username, password).GetResponse(""));
  304. SendString(Xml.ToXmlString(xml, false, true));
  305. XmlElement element = parser.ReadNextElement(new List<string>(new string[] { "success", "failure" }));
  306. if (element.Name == "success")
  307. {
  308. authenticated = true;
  309. }
  310. }
  311. /// <summary>
  312. /// Authenticates the user on the server using Digest-MD5 mechanism.
  313. /// </summary>
  314. private void AuthenticateUsingDigestMd5Mechanism()
  315. {
  316. XmlElement xml = Xml.CreateElement("auth", "urn:ietf:params:xml:ns:xmpp-sasl");
  317. Xml.AddAttribute(xml, "mechanism", DigestMd5Mechanism.MECHANISM_NAME);
  318. SendString(Xml.ToXmlString(xml, false, true));
  319. XmlElement element = parser.ReadNextElement(new List<string>(new string[] { "challenge", "success", "failure" }));
  320. if (element.Name == "challenge")
  321. {
  322. //!!
  323. authenticated = true;
  324. }
  325. }
  326. /// <summary>
  327. /// Authenticates the user on the server.
  328. /// </summary>
  329. /// <param name="mechanisms">The SASL mechanisms list.</param>
  330. private void Authenticate(List<string> mechanisms)
  331. {
  332. if (mechanisms.Count > 0)
  333. {
  334. //string mechanismName = SelectMechanism(mechanisms);
  335. string mechanismName = PlainMechanism.MECHANISM_NAME;
  336. switch (mechanismName)
  337. {
  338. case DigestMd5Mechanism.MECHANISM_NAME:
  339. AuthenticateUsingDigestMd5Mechanism();
  340. break;
  341. default:
  342. AuthenticateUsingPlainMechanism();
  343. break;
  344. }
  345. }
  346. }
  347. /// <summary>
  348. /// Setups the connection with the server.
  349. /// </summary>
  350. private void SetupConnection()
  351. {
  352. XmlElement features = InitiateStream(hostname);
  353. //if (features.GetElementsByTagName("starttls").Count > 0)
  354. //{
  355. // features = StartTls(hostname);
  356. //}
  357. XmlNodeList mechanismsNodes = features.GetElementsByTagName("mechanism");
  358. List<string> mechanisms = new List<string>();
  359. foreach (XmlNode node in mechanismsNodes)
  360. {
  361. mechanisms.Add(node.InnerText);
  362. }
  363. Authenticate(mechanisms);
  364. if (!authenticated && !Config.WebMode)
  365. {
  366. FRMessageBox.Error(Res.Get("Messaging,Xmpp,Errors,InvalidJidOrPassword"));
  367. }
  368. }
  369. /// <summary>
  370. /// Binds resource and gets the full JID that will be associated with current session.
  371. /// </summary>
  372. /// <returns>The full session JID.</returns>
  373. private string BindResource()
  374. {
  375. string jid = null;
  376. XmlElement xml = Xml.CreateElement("iq", "");
  377. Xml.AddAttribute(xml, "type", "set");
  378. Xml.AddAttribute(xml, "id", "bind-0");
  379. XmlElement bind = Xml.CreateElement("bind", "urn:ietf:params:xml:ns:xmpp-bind");
  380. XmlElement resource = Xml.CreateElement("resource", "");
  381. Xml.AddText(resource, DEFAULT_RESOURCE);
  382. Xml.AddChild(bind, resource);
  383. Xml.AddChild(xml, bind);
  384. SendString(Xml.ToXmlString(xml, false, true));
  385. XmlElement res = parser.ReadNextElement(new List<string>(new string[] { "iq" }));
  386. XmlNodeList jidNode = res.GetElementsByTagName("jid");
  387. if (jidNode.Count > 0)
  388. {
  389. jid = jidNode[0].InnerText;
  390. }
  391. return jid;
  392. }
  393. /// <summary>
  394. /// Opens session between client and server.
  395. /// </summary>
  396. /// <returns>The id of the opened session.</returns>
  397. private string OpenSession()
  398. {
  399. SendString("<iq type='set' id='" + DEFAULT_SESSION_ID + "'><session xmlns='urn:ietf:params:xml:ns:xmpp-session'/></iq>");
  400. XmlElement result = parser.ReadNextElement(new List<string>(new string[] { "iq" }));
  401. return result.GetAttribute("id"); ;
  402. }
  403. /// <summary>
  404. /// Connects to the server.
  405. /// </summary>
  406. private void Connect()
  407. {
  408. client = new TcpClient(hostname, port);
  409. stream = client.GetStream();
  410. SetupConnection();
  411. if (authenticated)
  412. {
  413. XmlElement features = InitiateStream(hostname);
  414. XmlNodeList bind = features.GetElementsByTagName("bind");
  415. if (bind.Count > 0)
  416. {
  417. jidFrom = BindResource();
  418. sessionId = OpenSession();
  419. if (!String.IsNullOrEmpty(jidFrom) && !String.IsNullOrEmpty(sessionId))
  420. {
  421. connected = true;
  422. }
  423. }
  424. }
  425. }
  426. /// <summary>
  427. /// Sends the message.
  428. /// </summary>
  429. /// <param name="text">The text of the message.</param>
  430. /// <returns>True if message has been successfully sent.</returns>
  431. private bool SendMessage(string text)
  432. {
  433. XmlElement data = Xml.CreateElement("body", null);
  434. Xml.AddText(data, text);
  435. List<XmlElement> list = new List<XmlElement>();
  436. list.Add(data);
  437. Message message = new Message(null, "chat", jidFrom, jidTo, sessionId, new CultureInfo("en"), list);
  438. SendString(message.ToString());
  439. return true;
  440. }
  441. /// <summary>
  442. /// Sends the presence.
  443. /// </summary>
  444. /// <param name="text">The text of the presence.</param>
  445. /// <returns>True if presence has been successfully sent.</returns>
  446. private bool SendPresence(string text)
  447. {
  448. SendString("<presence><show></show></presence>");
  449. while (true)
  450. {
  451. XmlElement resp = parser.ReadNextElement(new List<string>(new string[] { "iq", "presence" }));
  452. if (resp == null) break;
  453. }
  454. return true;
  455. }
  456. /// <summary>
  457. /// Initiates the In Band Bytestream for sending the file (XEP-0047).
  458. /// </summary>
  459. /// <returns>True if bytestream has been successfully initiated.</returns>
  460. private bool InitiateInBandBytestream()
  461. {
  462. XmlElement open = Xml.CreateElement("open", "http://jabber.org/protocol/ibb");
  463. Xml.AddAttribute(open, "block-size", chunkSize.ToString());
  464. Xml.AddAttribute(open, "sid", sessionId);
  465. Xml.AddAttribute(open, "stanza", "message");
  466. List<XmlElement> list = new List<XmlElement>();
  467. list.Add(open);
  468. Iq iq = new Iq(null, "set", jidFrom, jidTo, "ibb1", null, list);
  469. //Message iq = new Message(null, "set", fullJid, jidTo + "/Miranda", sessionId, null, list);
  470. string str = iq.ToString();
  471. //string str2 = "<iq type='set' from='frbot@im.fast-report.com/frnet' to='olegk@im.fast-report.com/psee' id='frnet_session_0' stanza='message'><open sid='mySID' block-size='4096' xmlns='http://jabber.org/protocol/ibb'/></iq>";
  472. SendString(iq.ToString());
  473. XmlElement resp = parser.ReadNextElement(new List<string>(new string[] { "iq" }));
  474. //resp = parser.ReadNextElement(new List<string>(new string[] { "iq" }));
  475. //resp = parser.ReadNextElement(new List<string>(new string[] { "iq" }));
  476. resp = parser.ReadNextElement(new List<string>(new string[] { "iq" }));
  477. resp = parser.ReadNextElement(new List<string>(new string[] { "iq" }));
  478. while (resp == null)
  479. {
  480. resp = parser.ReadNextElement(new List<string>(new string[] { "iq" }));
  481. resp = parser.ReadNextElement(new List<string>(new string[] { "iq" }));
  482. }
  483. if (resp.GetElementsByTagName("service-unavailable").Count > 0 || resp.GetElementsByTagName("feature-not-implemented").Count > 0)
  484. {
  485. return false;
  486. }
  487. return true;
  488. }
  489. /// <summary>
  490. /// Sends the chunk to the XMPP server.
  491. /// </summary>
  492. /// <param name="chunk">The data of the chunk.</param>
  493. /// <param name="number">The number of the chunk.</param>
  494. private void SendChunk(byte[] chunk, int number)
  495. {
  496. XmlElement data = Xml.CreateElement("data", "http://jabber.org/protocol/ibb");
  497. Xml.AddAttribute(data, "seq", number.ToString());
  498. Xml.AddAttribute(data, "sid", sessionId);
  499. Xml.AddText(data, Convert.ToBase64String(chunk));
  500. List<XmlElement> list = new List<XmlElement>();
  501. list.Add(data);
  502. //Iq iq = new Iq(null, "set", fullJid, jidTo, sessionId, new CultureInfo("en"), list);
  503. Message iq = new Message(null, null, jidFrom, jidTo, sessionId, null, list);
  504. SendString(iq.ToString());
  505. //XmlElement resp = parser.ReadNextElement(new List<string>(new string[] { "iq" }));
  506. }
  507. /// <summary>
  508. /// Sends the file using In Band Bytestream.
  509. /// </summary>
  510. /// <param name="ms">The memory stream containing data of the file.</param>
  511. /// <returns>True if file has been successfully sent.</returns>
  512. private bool SendFileUsingIbb(MemoryStream ms)
  513. {
  514. InitiateInBandBytestream();
  515. try
  516. {
  517. byte[] chunk = new byte[chunkSize];
  518. int chunksCount = (int)Math.Ceiling((double)ms.Length / chunkSize);
  519. ms.Position = 0;
  520. for (int i = 0; i < chunksCount - 1; i++)
  521. {
  522. ms.Read(chunk, 0, chunk.Length);
  523. SendChunk(chunk, i);
  524. }
  525. byte[] lastChunk = new byte[ms.Length - ((chunksCount - 1) * chunkSize)];
  526. ms.Read(lastChunk, 0, lastChunk.Length);
  527. SendChunk(lastChunk, chunksCount - 1);
  528. }
  529. catch
  530. {
  531. return false;
  532. }
  533. return true;
  534. }
  535. /// <summary>
  536. /// Sends the file using FastReport Cloud as a proxy server.
  537. /// </summary>
  538. /// <param name="report">The report template.</param>
  539. /// <param name="export">The export filter to export report before sending.</param>
  540. /// <returns>True if file has been successfully sent.</returns>
  541. private bool SendFileUsingFastReportCloud(Report report, ExportBase export)
  542. {
  543. FastCloudStorageClient client = new FastCloudStorageClient();
  544. if (ProxySettings != null)
  545. {
  546. client.ProxySettings = new CloudProxySettings(FastReport.Cloud.ProxyType.Http, ProxySettings.Server, ProxySettings.Port, ProxySettings.Username, ProxySettings.Password);
  547. switch (ProxySettings.ProxyType)
  548. {
  549. case ProxyType.Socks4:
  550. client.ProxySettings.ProxyType = FastReport.Cloud.ProxyType.Socks4;
  551. break;
  552. case ProxyType.Socks5:
  553. client.ProxySettings.ProxyType = FastReport.Cloud.ProxyType.Socks5;
  554. break;
  555. default:
  556. client.ProxySettings.ProxyType = FastReport.Cloud.ProxyType.Http;
  557. break;
  558. }
  559. }
  560. client.AccessToken = "sozTWBzEm9toiTB5J2MA";
  561. bool saved = false;
  562. try
  563. {
  564. // çàìåíèòü null íà export êîãäà ïîÿâèòñÿ ïîääåðæêà äðóãèõ ôîðìàòîâ â îáëàêå
  565. client.SaveReport(report, null);
  566. saved = true;
  567. }
  568. catch { }
  569. if (saved)
  570. {
  571. SendMessage(client.ReportUrl);
  572. }
  573. else
  574. {
  575. if (!Config.WebMode)
  576. {
  577. FRMessageBox.Error(Res.Get("Messaging,Xmpp,Errors,UnableToUploadFile"));
  578. }
  579. return false;
  580. }
  581. return true;
  582. }
  583. /// <summary>
  584. /// Disconnects from the server.
  585. /// </summary>
  586. private void Disconnect()
  587. {
  588. if (connected)
  589. {
  590. SendString("</stream:stream>");
  591. connected = false;
  592. authenticated = false;
  593. }
  594. }
  595. #endregion // Private Methods
  596. #region Protected Methods
  597. /// <inheritdoc/>
  598. protected override bool Authorize()
  599. {
  600. Connect();
  601. return connected;
  602. }
  603. #endregion // Protected Methods
  604. #region Public Methods
  605. /// <inheritdoc/>
  606. public override bool SendReport(Report report, ExportBase export)
  607. {
  608. bool result = false;
  609. Authorize();
  610. if (connected)
  611. {
  612. //using (MemoryStream ms = PrepareToSave(report, export))
  613. //{
  614. // result = SendFileUsingIbb(ms);
  615. //}
  616. result = SendFileUsingFastReportCloud(report, export);
  617. Disconnect();
  618. }
  619. return result;
  620. }
  621. /// <summary>
  622. /// Closes the connection.
  623. /// </summary>
  624. public void Close()
  625. {
  626. if (connected)
  627. {
  628. Disconnect();
  629. }
  630. if (!disposed)
  631. {
  632. Dispose();
  633. }
  634. }
  635. /// <summary>
  636. /// Releases all the resources used by the XMPP messenger.
  637. /// </summary>
  638. public void Dispose()
  639. {
  640. if (!disposed)
  641. {
  642. if (parser != null)
  643. {
  644. parser.Close();
  645. parser = null;
  646. }
  647. if (client != null)
  648. {
  649. client.Close();
  650. client = null;
  651. }
  652. disposed = true;
  653. }
  654. }
  655. #endregion // Public Methods
  656. }
  657. }