ProtocolManager.cpp 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283
  1. /*
  2. * Copyright 2009-2011, Andrea Anzani. All rights reserved.
  3. * Copyright 2021, Jaidyn Levesque. All rights reserved.
  4. * Distributed under the terms of the MIT License.
  5. *
  6. * Authors:
  7. * Andrea Anzani, andrea.anzani@gmail.com
  8. * Jaidyn Levesque, jadedctrl@teknik.io
  9. */
  10. #include <stdio.h>
  11. #include <image.h>
  12. #include <Bitmap.h>
  13. #include <Directory.h>
  14. #include <Entry.h>
  15. #include <Handler.h>
  16. #include "Account.h"
  17. #include "AppMessages.h"
  18. #include "ChatProtocolMessages.h"
  19. #include "ProtocolManager.h"
  20. #include "ProtocolSettings.h"
  21. #include "ChatProtocol.h"
  22. #include "MainWindow.h"
  23. #include "Server.h"
  24. #include "TheApp.h"
  25. #include "Utils.h"
  26. static ProtocolManager* fInstance = NULL;
  27. bool
  28. ProtocolManager::Init(BDirectory dir, BHandler* target)
  29. {
  30. BEntry entry;
  31. BPath path;
  32. bool ret = false;
  33. dir.Rewind();
  34. while (dir.GetNextEntry(&entry) == B_OK) {
  35. path = BPath(&entry);
  36. // Load protocol addon
  37. image_id id = load_add_on(path.Path());
  38. if (id < 0)
  39. continue;
  40. // If add-on's API version fits then load accounts…
  41. ChatProtocolAddOn* addOn = new ChatProtocolAddOn(id, path.Path());
  42. if (addOn->Version() != APP_VERSION)
  43. continue;
  44. ret = true;
  45. // If add-on has multiple protocols, also load them
  46. for (int32 i = 0; i < addOn->CountProtocols(); i++) {
  47. ChatProtocolAddOn* subAddOn = addOn;
  48. if (i > 0)
  49. subAddOn = new ChatProtocolAddOn(id, path.Path(), i);
  50. ChatProtocol* proto = subAddOn->Protocol();
  51. fAddOnMap.AddItem(proto->Signature(), subAddOn);
  52. _LoadAccounts(path.Path(), subAddOn, i, target);
  53. delete proto;
  54. }
  55. }
  56. return ret;
  57. }
  58. ProtocolManager::ProtocolManager()
  59. {
  60. }
  61. ProtocolManager*
  62. ProtocolManager::Get()
  63. {
  64. if (fInstance == NULL)
  65. fInstance = new ProtocolManager();
  66. return fInstance;
  67. }
  68. uint32
  69. ProtocolManager::CountProtocolAddOns() const
  70. {
  71. return fAddOnMap.CountItems();
  72. }
  73. ChatProtocolAddOn*
  74. ProtocolManager::ProtocolAddOnAt(uint32 i) const
  75. {
  76. return fAddOnMap.ValueAt(i);
  77. }
  78. ChatProtocolAddOn*
  79. ProtocolManager::ProtocolAddOn(const char* signature)
  80. {
  81. return fAddOnMap.ValueFor(signature);
  82. }
  83. uint32
  84. ProtocolManager::CountProtocolInstances() const
  85. {
  86. return fProtocolMap.CountItems();
  87. }
  88. ChatProtocol*
  89. ProtocolManager::ProtocolInstanceAt(uint32 i) const
  90. {
  91. return fProtocolMap.ValueAt(i);
  92. }
  93. ChatProtocol*
  94. ProtocolManager::ProtocolInstance(bigtime_t identifier)
  95. {
  96. return fProtocolMap.ValueFor(identifier);
  97. }
  98. void
  99. ProtocolManager::AddAccount(ChatProtocolAddOn* addOn, const char* account,
  100. BHandler* target)
  101. {
  102. // If already active, don't double-dip!
  103. bool active = false;
  104. _Server()->GetActiveAccounts().ValueFor(BString(account), &active);
  105. if (active == true)
  106. return;
  107. bigtime_t instanceId = system_time();
  108. ChatProtocol* cayap = addOn->Protocol();
  109. Account* acc =
  110. new Account(instanceId, cayap, account, addOn->Signature(), target);
  111. // If account is disabled, just let it go
  112. if (acc->InitCheck() == B_DONT_DO_THAT) {
  113. delete acc;
  114. return;
  115. }
  116. // Send a "whoops" notification if hits a failure
  117. else if (acc->InitCheck() != B_OK) {
  118. BMessage error(APP_ACCOUNT_FAILED);
  119. cayap->Icon()->Archive(&error);
  120. error.AddString("name", account);
  121. _MainWin()->MessageReceived(&error);
  122. return;
  123. }
  124. fProtocolMap.AddItem(instanceId, cayap);
  125. _Server()->AddProtocolLooper(instanceId, cayap);
  126. }
  127. void
  128. ProtocolManager::EnableAccount(ProtocolSettings* settings, const char* account)
  129. {
  130. BMessage* msg = NULL;
  131. if (settings->Load(account, &msg) == B_OK) {
  132. if (msg->HasBool("disabled"))
  133. msg->ReplaceBool("disabled", false);
  134. else
  135. msg->AddBool("disabled", false);
  136. settings->Save(account, *msg);
  137. }
  138. AddAccount(settings->AddOn(), account, _MainWin());
  139. }
  140. void
  141. ProtocolManager::DisableAccount(ProtocolSettings* settings, const char* account)
  142. {
  143. bool active = false;
  144. int64 instance
  145. = _Server()->GetActiveAccounts().ValueFor(BString(account), &active);
  146. if (active == false)
  147. return;
  148. BMessage* msg = NULL;
  149. if (settings->Load(account, &msg) == B_OK) {
  150. if (msg->HasBool("disabled"))
  151. msg->ReplaceBool("disabled", true);
  152. else
  153. msg->AddBool("disabled", true);
  154. settings->Save(account, *msg);
  155. }
  156. BMessage remove(IM_MESSAGE);
  157. remove.AddInt32("im_what", IM_PROTOCOL_DISABLE);
  158. remove.AddInt64("instance", instance);
  159. _MainWin()->PostMessage(&remove);
  160. }
  161. void
  162. ProtocolManager::ToggleAccount(ProtocolSettings* settings, const char* account)
  163. {
  164. bool active = false;
  165. int64 instance
  166. = _Server()->GetActiveAccounts().ValueFor(BString(account), &active);
  167. if (active == true)
  168. DisableAccount(settings, account);
  169. else
  170. EnableAccount(settings, account);
  171. }
  172. void
  173. ProtocolManager::_LoadAccounts(const char* image_path, ChatProtocolAddOn* addOn,
  174. int protoIndex, BHandler* target)
  175. {
  176. // Find accounts path for this protocol
  177. BPath path(AccountPath(addOn->Signature(), addOn->Protocol()->Signature()));
  178. if (path.InitCheck() != B_OK)
  179. return;
  180. BDirectory dir(path.Path());
  181. BEntry entry;
  182. bool firstDone = false;
  183. while (dir.GetNextEntry(&entry) == B_OK)
  184. _LoadAccount(addOn, entry, target);
  185. }
  186. void
  187. ProtocolManager::_LoadAccount(const char* imagePath, BEntry accountEntry,
  188. int protoIndex, BHandler* target)
  189. {
  190. image_id id = load_add_on(imagePath);
  191. if (id < 0)
  192. return;
  193. // If add-on's API version fits then load accounts…
  194. ChatProtocolAddOn* addOn = new ChatProtocolAddOn(id, imagePath, protoIndex);
  195. if (addOn->Version() != APP_VERSION)
  196. return;
  197. _LoadAccount(addOn, accountEntry, target);
  198. }
  199. void
  200. ProtocolManager::_LoadAccount(ChatProtocolAddOn* addOn, BEntry accountEntry,
  201. BHandler* target)
  202. {
  203. BFile file(&accountEntry, B_READ_ONLY);
  204. BMessage msg;
  205. if (msg.Unflatten(&file) == B_OK) {
  206. char buffer[B_PATH_NAME_LENGTH];
  207. if (accountEntry.GetName(buffer) == B_OK) {
  208. printf("Found %s for protocol %s!\n", buffer, addOn->Protocol()->Signature());
  209. AddAccount(addOn, buffer, target);
  210. }
  211. }
  212. }
  213. MainWindow*
  214. ProtocolManager::_MainWin()
  215. {
  216. return ((TheApp*)be_app)->GetMainWindow();
  217. }
  218. Server*
  219. ProtocolManager::_Server()
  220. {
  221. MainWindow* win = _MainWin();
  222. return win ? win->GetServer() : NULL;
  223. }