aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region')
-rw-r--r--OpenSim/Region/Framework/Interfaces/IGroupsMessagingModule.cs21
-rw-r--r--OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsMessagingModule.cs156
-rw-r--r--OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs60
-rw-r--r--OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/Tests/GroupsModuleTests.cs26
4 files changed, 171 insertions, 92 deletions
diff --git a/OpenSim/Region/Framework/Interfaces/IGroupsMessagingModule.cs b/OpenSim/Region/Framework/Interfaces/IGroupsMessagingModule.cs
index f158236..61bd153 100644
--- a/OpenSim/Region/Framework/Interfaces/IGroupsMessagingModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/IGroupsMessagingModule.cs
@@ -25,6 +25,7 @@
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */ 26 */
27 27
28using System;
28using OpenMetaverse; 29using OpenMetaverse;
29using OpenSim.Framework; 30using OpenSim.Framework;
30 31
@@ -57,7 +58,7 @@ namespace OpenSim.Region.Framework.Interfaces
57 bool StartGroupChatSession(UUID agentID, UUID groupID); 58 bool StartGroupChatSession(UUID agentID, UUID groupID);
58 59
59 /// <summary> 60 /// <summary>
60 /// Send a message to an entire group. 61 /// Send a message to each member of a group whose chat session is active.
61 /// </summary> 62 /// </summary>
62 /// <param name="im"> 63 /// <param name="im">
63 /// The message itself. The fields that must be populated are 64 /// The message itself. The fields that must be populated are
@@ -69,5 +70,23 @@ namespace OpenSim.Region.Framework.Interfaces
69 /// </param> 70 /// </param>
70 /// <param name="groupID"></param> 71 /// <param name="groupID"></param>
71 void SendMessageToGroup(GridInstantMessage im, UUID groupID); 72 void SendMessageToGroup(GridInstantMessage im, UUID groupID);
73
74 /// <summary>
75 /// Send a message to all the members of a group that fulfill a condition.
76 /// </summary>
77 /// <param name="im">
78 /// The message itself. The fields that must be populated are
79 ///
80 /// imSessionID - Populate this with the group ID (session ID and group ID are currently identical)
81 /// fromAgentName - Populate this with whatever arbitrary name you want to show up in the chat dialog
82 /// message - The message itself
83 /// dialog - This must be (byte)InstantMessageDialog.SessionSend
84 /// </param>
85 /// <param name="groupID"></param>
86 /// <param name="sendCondition">
87 /// The condition that must be met by a member for the message to be sent. If null then the message is sent
88 /// if the chat session is active.
89 /// </param>
90 void SendMessageToGroup(GridInstantMessage im, UUID groupID, Func<GroupMembersData, bool> sendCondition);
72 } 91 }
73} \ No newline at end of file 92} \ No newline at end of file
diff --git a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsMessagingModule.cs b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsMessagingModule.cs
index 2802e2f..741a98f 100644
--- a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsMessagingModule.cs
+++ b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsMessagingModule.cs
@@ -237,9 +237,15 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
237 return false; 237 return false;
238 } 238 }
239 } 239 }
240
240 241
241 public void SendMessageToGroup(GridInstantMessage im, UUID groupID) 242 public void SendMessageToGroup(GridInstantMessage im, UUID groupID)
242 { 243 {
244 SendMessageToGroup(im, groupID, null);
245 }
246
247 public void SendMessageToGroup(GridInstantMessage im, UUID groupID, Func<GroupMembersData, bool> sendCondition)
248 {
243 List<GroupMembersData> groupMembers = m_groupData.GetGroupMembers(new UUID(im.fromAgentID), groupID); 249 List<GroupMembersData> groupMembers = m_groupData.GetGroupMembers(new UUID(im.fromAgentID), groupID);
244 int groupMembersCount = groupMembers.Count; 250 int groupMembersCount = groupMembers.Count;
245 251
@@ -279,10 +285,25 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
279 285
280 foreach (GroupMembersData member in groupMembers) 286 foreach (GroupMembersData member in groupMembers)
281 { 287 {
282 if (m_groupData.hasAgentDroppedGroupChatSession(member.AgentID, groupID)) 288 if (sendCondition != null)
289 {
290 if (!sendCondition(member))
291 {
292 if (m_debugEnabled)
293 m_log.DebugFormat(
294 "[GROUPS-MESSAGING]: Not sending to {0} as they do not fulfill send condition",
295 member.AgentID);
296
297 continue;
298 }
299 }
300 else if (m_groupData.hasAgentDroppedGroupChatSession(member.AgentID, groupID))
283 { 301 {
284 // Don't deliver messages to people who have dropped this session 302 // Don't deliver messages to people who have dropped this session
285 if (m_debugEnabled) m_log.DebugFormat("[GROUPS-MESSAGING]: {0} has dropped session, not delivering to them", member.AgentID); 303 if (m_debugEnabled)
304 m_log.DebugFormat(
305 "[GROUPS-MESSAGING]: {0} has dropped session, not delivering to them", member.AgentID);
306
286 continue; 307 continue;
287 } 308 }
288 309
@@ -315,7 +336,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
315 { 336 {
316 // Deliver locally, directly 337 // Deliver locally, directly
317 if (m_debugEnabled) m_log.DebugFormat("[GROUPS-MESSAGING]: Passing to ProcessMessageFromGroupSession to deliver to {0} locally", client.Name); 338 if (m_debugEnabled) m_log.DebugFormat("[GROUPS-MESSAGING]: Passing to ProcessMessageFromGroupSession to deliver to {0} locally", client.Name);
318 ProcessMessageFromGroupSession(msg); 339 ProcessMessageFromGroupSession(msg, client);
319 } 340 }
320 } 341 }
321 342
@@ -348,7 +369,6 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
348 // Any other message type will not be delivered to a client by the 369 // Any other message type will not be delivered to a client by the
349 // Instant Message Module 370 // Instant Message Module
350 371
351
352 if (m_debugEnabled) 372 if (m_debugEnabled)
353 { 373 {
354 m_log.DebugFormat("[GROUPS-MESSAGING]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); 374 m_log.DebugFormat("[GROUPS-MESSAGING]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
@@ -362,11 +382,30 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
362 || (msg.dialog == (byte)InstantMessageDialog.SessionAdd) 382 || (msg.dialog == (byte)InstantMessageDialog.SessionAdd)
363 || (msg.dialog == (byte)InstantMessageDialog.SessionDrop))) 383 || (msg.dialog == (byte)InstantMessageDialog.SessionDrop)))
364 { 384 {
365 ProcessMessageFromGroupSession(msg); 385 IClientAPI client = null;
386
387 if (msg.dialog == (byte)InstantMessageDialog.SessionSend)
388 {
389 client = GetActiveClient(new UUID(msg.toAgentID));
390
391 if (client != null)
392 {
393 if (m_debugEnabled)
394 m_log.DebugFormat("[GROUPS-MESSAGING]: Delivering to {0} locally", client.Name);
395 }
396 else
397 {
398 m_log.WarnFormat("[GROUPS-MESSAGING]: Received a message over the grid for a client that isn't here: {0}", msg.toAgentID);
399
400 return;
401 }
402 }
403
404 ProcessMessageFromGroupSession(msg, client);
366 } 405 }
367 } 406 }
368 407
369 private void ProcessMessageFromGroupSession(GridInstantMessage msg) 408 private void ProcessMessageFromGroupSession(GridInstantMessage msg, IClientAPI client)
370 { 409 {
371 if (m_debugEnabled) m_log.DebugFormat("[GROUPS-MESSAGING]: Session message from {0} going to agent {1}", msg.fromAgentName, msg.toAgentID); 410 if (m_debugEnabled) m_log.DebugFormat("[GROUPS-MESSAGING]: Session message from {0} going to agent {1}", msg.fromAgentName, msg.toAgentID);
372 411
@@ -393,67 +432,58 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
393 m_groupData.AgentInvitedToGroupChatSession(AgentID, GroupID); 432 m_groupData.AgentInvitedToGroupChatSession(AgentID, GroupID);
394 433
395 UUID toAgentID = new UUID(msg.toAgentID); 434 UUID toAgentID = new UUID(msg.toAgentID);
396 IClientAPI activeClient = GetActiveClient(toAgentID); 435
397 if (activeClient != null) 436 GroupRecord groupInfo = m_groupData.GetGroupRecord(UUID.Zero, GroupID, null);
437 if (groupInfo != null)
398 { 438 {
399 GroupRecord groupInfo = m_groupData.GetGroupRecord(UUID.Zero, GroupID, null); 439 if (m_debugEnabled) m_log.DebugFormat("[GROUPS-MESSAGING]: Sending chatterbox invite instant message");
400 if (groupInfo != null) 440
401 { 441 // Force? open the group session dialog???
402 if (m_debugEnabled) m_log.DebugFormat("[GROUPS-MESSAGING]: Sending chatterbox invite instant message"); 442 // and simultanously deliver the message, so we don't need to do a seperate client.SendInstantMessage(msg);
403 443 IEventQueue eq = client.Scene.RequestModuleInterface<IEventQueue>();
404 // Force? open the group session dialog??? 444 eq.ChatterboxInvitation(
405 // and simultanously deliver the message, so we don't need to do a seperate client.SendInstantMessage(msg); 445 GroupID
406 IEventQueue eq = activeClient.Scene.RequestModuleInterface<IEventQueue>(); 446 , groupInfo.GroupName
407 eq.ChatterboxInvitation( 447 , new UUID(msg.fromAgentID)
408 GroupID 448 , msg.message
409 , groupInfo.GroupName 449 , new UUID(msg.toAgentID)
410 , new UUID(msg.fromAgentID) 450 , msg.fromAgentName
411 , msg.message 451 , msg.dialog
412 , new UUID(msg.toAgentID) 452 , msg.timestamp
413 , msg.fromAgentName 453 , msg.offline == 1
414 , msg.dialog 454 , (int)msg.ParentEstateID
415 , msg.timestamp 455 , msg.Position
416 , msg.offline == 1 456 , 1
417 , (int)msg.ParentEstateID 457 , new UUID(msg.imSessionID)
418 , msg.Position 458 , msg.fromGroup
419 , 1 459 , Utils.StringToBytes(groupInfo.GroupName)
420 , new UUID(msg.imSessionID) 460 );
421 , msg.fromGroup 461
422 , Utils.StringToBytes(groupInfo.GroupName) 462 eq.ChatterBoxSessionAgentListUpdates(
423 ); 463 new UUID(GroupID)
424 464 , new UUID(msg.fromAgentID)
425 eq.ChatterBoxSessionAgentListUpdates( 465 , new UUID(msg.toAgentID)
426 new UUID(GroupID) 466 , false //canVoiceChat
427 , new UUID(msg.fromAgentID) 467 , false //isModerator
428 , new UUID(msg.toAgentID) 468 , false //text mute
429 , false //canVoiceChat 469 );
430 , false //isModerator
431 , false //text mute
432 );
433 }
434 } 470 }
471
472 break;
435 } 473 }
436 else if (!m_groupData.hasAgentDroppedGroupChatSession(AgentID, GroupID)) 474 else if (!m_groupData.hasAgentDroppedGroupChatSession(AgentID, GroupID))
437 { 475 {
438 // User hasn't dropped, so they're in the session, 476 // User hasn't dropped, so they're in the session,
439 // maybe we should deliver it. 477 // maybe we should deliver it.
440 IClientAPI client = GetActiveClient(new UUID(msg.toAgentID)); 478 client.SendInstantMessage(msg);
441 if (client != null)
442 {
443 // Deliver locally, directly
444 if (m_debugEnabled) m_log.DebugFormat("[GROUPS-MESSAGING]: Delivering to {0} locally", client.Name);
445 client.SendInstantMessage(msg);
446 }
447 else
448 {
449 m_log.WarnFormat("[GROUPS-MESSAGING]: Received a message over the grid for a client that isn't here: {0}", msg.toAgentID);
450 }
451 } 479 }
480
452 break; 481 break;
453 482
454 default: 483 default:
455 m_log.WarnFormat("[GROUPS-MESSAGING]: I don't know how to proccess a {0} message.", ((InstantMessageDialog)msg.dialog).ToString()); 484 client.SendInstantMessage(msg);
456 break; 485
486 break;;
457 } 487 }
458 } 488 }
459 489
@@ -549,13 +579,13 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
549 if (m_debugEnabled && im.dialog != (byte)InstantMessageDialog.MessageFromAgent) 579 if (m_debugEnabled && im.dialog != (byte)InstantMessageDialog.MessageFromAgent)
550 { 580 {
551 m_log.WarnFormat("[GROUPS-MESSAGING]: IM: fromGroup({0})", im.fromGroup ? "True" : "False"); 581 m_log.WarnFormat("[GROUPS-MESSAGING]: IM: fromGroup({0})", im.fromGroup ? "True" : "False");
552 m_log.WarnFormat("[GROUPS-MESSAGING]: IM: Dialog({0})", ((InstantMessageDialog)im.dialog).ToString()); 582 m_log.WarnFormat("[GROUPS-MESSAGING]: IM: Dialog({0})", (InstantMessageDialog)im.dialog);
553 m_log.WarnFormat("[GROUPS-MESSAGING]: IM: fromAgentID({0})", im.fromAgentID.ToString()); 583 m_log.WarnFormat("[GROUPS-MESSAGING]: IM: fromAgentID({0})", im.fromAgentID);
554 m_log.WarnFormat("[GROUPS-MESSAGING]: IM: fromAgentName({0})", im.fromAgentName.ToString()); 584 m_log.WarnFormat("[GROUPS-MESSAGING]: IM: fromAgentName({0})", im.fromAgentName);
555 m_log.WarnFormat("[GROUPS-MESSAGING]: IM: imSessionID({0})", im.imSessionID.ToString()); 585 m_log.WarnFormat("[GROUPS-MESSAGING]: IM: imSessionID({0})", im.imSessionID);
556 m_log.WarnFormat("[GROUPS-MESSAGING]: IM: message({0})", im.message.ToString()); 586 m_log.WarnFormat("[GROUPS-MESSAGING]: IM: message({0})", im.message);
557 m_log.WarnFormat("[GROUPS-MESSAGING]: IM: offline({0})", im.offline.ToString()); 587 m_log.WarnFormat("[GROUPS-MESSAGING]: IM: offline({0})", im.offline);
558 m_log.WarnFormat("[GROUPS-MESSAGING]: IM: toAgentID({0})", im.toAgentID.ToString()); 588 m_log.WarnFormat("[GROUPS-MESSAGING]: IM: toAgentID({0})", im.toAgentID);
559 m_log.WarnFormat("[GROUPS-MESSAGING]: IM: binaryBucket({0})", OpenMetaverse.Utils.BytesToHexString(im.binaryBucket, "BinaryBucket")); 589 m_log.WarnFormat("[GROUPS-MESSAGING]: IM: binaryBucket({0})", OpenMetaverse.Utils.BytesToHexString(im.binaryBucket, "BinaryBucket"));
560 } 590 }
561 } 591 }
diff --git a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs
index 62020ee..d4f70a7 100644
--- a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs
+++ b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs
@@ -77,9 +77,11 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
77 77
78 private List<Scene> m_sceneList = new List<Scene>(); 78 private List<Scene> m_sceneList = new List<Scene>();
79 79
80 private IMessageTransferModule m_msgTransferModule = null; 80 private IMessageTransferModule m_msgTransferModule;
81
82 private IGroupsMessagingModule m_groupsMessagingModule;
81 83
82 private IGroupsServicesConnector m_groupData = null; 84 private IGroupsServicesConnector m_groupData;
83 85
84 // Configuration settings 86 // Configuration settings
85 private bool m_groupsEnabled = false; 87 private bool m_groupsEnabled = false;
@@ -185,10 +187,19 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
185 if (m_msgTransferModule == null) 187 if (m_msgTransferModule == null)
186 { 188 {
187 m_groupsEnabled = false; 189 m_groupsEnabled = false;
188 m_log.Warn("[GROUPS]: Could not get MessageTransferModule"); 190 m_log.Warn("[GROUPS]: Could not get IMessageTransferModule");
189 } 191 }
190 } 192 }
191 193
194 if (m_groupsMessagingModule == null)
195 {
196 m_groupsMessagingModule = scene.RequestModuleInterface<IGroupsMessagingModule>();
197
198 // No message transfer module, no notices, group invites, rejects, ejects, etc
199 if (m_groupsMessagingModule == null)
200 m_log.Warn("[GROUPS]: Could not get IGroupsMessagingModule");
201 }
202
192 lock (m_sceneList) 203 lock (m_sceneList)
193 { 204 {
194 m_sceneList.Add(scene); 205 m_sceneList.Add(scene);
@@ -497,32 +508,37 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
497 OnNewGroupNotice(GroupID, NoticeID); 508 OnNewGroupNotice(GroupID, NoticeID);
498 } 509 }
499 510
500 /*** We would insert call code here ***/ 511 if (m_debugEnabled)
501 // Send notice out to everyone that wants notices
502 foreach (GroupMembersData member in m_groupData.GetGroupMembers(GetRequestingAgentID(remoteClient), GroupID))
503 { 512 {
504 if (m_debugEnabled) 513 foreach (GroupMembersData member in m_groupData.GetGroupMembers(GetRequestingAgentID(remoteClient), GroupID))
505 { 514 {
506 UserAccount targetUser = m_sceneList[0].UserAccountService.GetUserAccount(remoteClient.Scene.RegionInfo.ScopeID, member.AgentID); 515 if (m_debugEnabled)
507 if (targetUser != null)
508 { 516 {
509 m_log.DebugFormat("[GROUPS]: Prepping group notice {0} for agent: {1} who Accepts Notices ({2})", NoticeID, targetUser.FirstName + " " + targetUser.LastName, member.AcceptNotices); 517 UserAccount targetUser
510 } 518 = m_sceneList[0].UserAccountService.GetUserAccount(
511 else 519 remoteClient.Scene.RegionInfo.ScopeID, member.AgentID);
512 { 520
513 m_log.DebugFormat("[GROUPS]: Prepping group notice {0} for agent: {1} who Accepts Notices ({2})", NoticeID, member.AgentID, member.AcceptNotices); 521 if (targetUser != null)
522 {
523 m_log.DebugFormat(
524 "[GROUPS]: Prepping group notice {0} for agent: {1} who Accepts Notices ({2})",
525 NoticeID, targetUser.FirstName + " " + targetUser.LastName, member.AcceptNotices);
526 }
527 else
528 {
529 m_log.DebugFormat(
530 "[GROUPS]: Prepping group notice {0} for agent: {1} who Accepts Notices ({2})",
531 NoticeID, member.AgentID, member.AcceptNotices);
532 }
514 } 533 }
515 } 534 }
535 }
516 536
517 if (member.AcceptNotices) 537 GridInstantMessage msg
518 { 538 = CreateGroupNoticeIM(UUID.Zero, NoticeID, (byte)OpenMetaverse.InstantMessageDialog.GroupNotice);
519 // Build notice IM
520 GridInstantMessage msg = CreateGroupNoticeIM(UUID.Zero, NoticeID, (byte)OpenMetaverse.InstantMessageDialog.GroupNotice);
521 539
522 msg.toAgentID = member.AgentID.Guid; 540 if (m_groupsMessagingModule != null)
523 OutgoingInstantMessage(msg, member.AgentID); 541 m_groupsMessagingModule.SendMessageToGroup(msg, GroupID, gmd => gmd.AcceptNotices);
524 }
525 }
526 } 542 }
527 } 543 }
528 544
diff --git a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/Tests/GroupsModuleTests.cs b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/Tests/GroupsModuleTests.cs
index 08a93b8..71f1098 100644
--- a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/Tests/GroupsModuleTests.cs
+++ b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/Tests/GroupsModuleTests.cs
@@ -41,6 +41,7 @@ using OpenSim.Framework.Communications;
41using OpenSim.Framework.Servers; 41using OpenSim.Framework.Servers;
42using OpenSim.Framework.Servers.HttpServer; 42using OpenSim.Framework.Servers.HttpServer;
43using OpenSim.Region.ClientStack.Linden; 43using OpenSim.Region.ClientStack.Linden;
44using OpenSim.Region.CoreModules.Avatar.InstantMessage;
44using OpenSim.Region.CoreModules.Framework; 45using OpenSim.Region.CoreModules.Framework;
45using OpenSim.Region.Framework.Scenes; 46using OpenSim.Region.Framework.Scenes;
46using OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups; 47using OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups;
@@ -127,15 +128,28 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups.Tests
127// TestHelpers.EnableLogging(); 128// TestHelpers.EnableLogging();
128 129
129 TestScene scene = new SceneHelpers().SetupScene(); 130 TestScene scene = new SceneHelpers().SetupScene();
130 IConfigSource configSource = new IniConfigSource();
131 IConfig config = configSource.AddConfig("Groups");
132 config.Set("Enabled", true);
133 config.Set("Module", "GroupsModule");
134 config.Set("DebugEnabled", true);
135 131
132 MessageTransferModule mtm = new MessageTransferModule();
136 GroupsModule gm = new GroupsModule(); 133 GroupsModule gm = new GroupsModule();
134 GroupsMessagingModule gmm = new GroupsMessagingModule();
135
136 IConfigSource configSource = new IniConfigSource();
137
138 {
139 IConfig config = configSource.AddConfig("Messaging");
140 config.Set("MessageTransferModule", mtm.Name);
141 }
142
143 {
144 IConfig config = configSource.AddConfig("Groups");
145 config.Set("Enabled", true);
146 config.Set("Module", gm.Name);
147 config.Set("DebugEnabled", true);
148 config.Set("MessagingModule", gmm.Name);
149 config.Set("MessagingEnabled", true);
150 }
137 151
138 SceneHelpers.SetupSceneModules(scene, configSource, gm, new MockGroupsServicesConnector()); 152 SceneHelpers.SetupSceneModules(scene, configSource, new MockGroupsServicesConnector(), mtm, gm, gmm);
139 153
140 UUID userId = TestHelpers.ParseTail(0x1); 154 UUID userId = TestHelpers.ParseTail(0x1);
141 string subjectText = "newman"; 155 string subjectText = "newman";