XMPP.pm 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. package Cpanel::iContact::Provider::XMPP;
  2. use strict;
  3. use warnings;
  4. use parent 'Cpanel::iContact::Provider';
  5. sub send {
  6. my ($self) = @_;
  7. my $args_hr = $self->{'args'};
  8. my @errs;
  9. my $subject_copy = $args_hr->{'subject'};
  10. my $body_copy = ${ $args_hr->{'text_body'} };
  11. require Encode;
  12. my $subject = Encode::decode_utf8( $subject_copy, $Encode::FB_QUIET );
  13. my $body = Encode::decode_utf8( $body_copy, $Encode::FB_QUIET );
  14. foreach my $destination ( @{ $args_hr->{'to'} } ) {
  15. local $@;
  16. eval {
  17. my $response;
  18. $self->_send(
  19. 'destination' => $destination,
  20. 'subject' => $subject,
  21. 'content' => $body
  22. );
  23. };
  24. push( @errs, $@ ) if $@;
  25. }
  26. if (@errs) {
  27. die "One or more notification attempts failed. Details below:\n"
  28. . join( "\n", @errs );
  29. }
  30. return 1;
  31. }
  32. sub _send {
  33. my ( $self, %args ) = @_;
  34. # Unfortunately you need this for Net::XMPP::Client to work.
  35. # Just requiring Net::XMPP::Client won't work.
  36. require Net::XMPP;
  37. my $user_name = substr( $self->{'contact'}{'XMPPUSERNAME'}, 0, index( $self->{'contact'}{'XMPPUSERNAME'}, '@' ));
  38. my $srvr_name = substr( $self->{'contact'}{'XMPPUSERNAME'}, index( $self->{'contact'}{'XMPPUSERNAME'}, '@' ) + 1 );
  39. # Safest assumption unless we the user gives a component name for override is to use base server name
  40. # Otherwise, expect a lot of "host-unknown" errors.
  41. my $cmpt_name = $self->{'contact'}{'XMPPCOMPONENTNAME'} || $srvr_name;
  42. my $xmpp_conn = Net::XMPP::Client->new(
  43. # Uncomment the below for debugging info
  44. #'debuglevel' => 2,
  45. #'debugfile' => "/usr/local/cpanel/logs/error_log",
  46. );
  47. require Mozilla::CA;
  48. # Will splash down without this
  49. my $cab_loc = Mozilla::CA::SSL_ca_file();
  50. # SIGALRM this to put a stop to folks who don't set SSL/TLS settings right (as Connect then foreverloops)
  51. my $status;
  52. {
  53. local $SIG{'ALRM'} = sub { die "Error: XMPP Connection failed: Timeout while attempting connection\n" };
  54. $self->{'_xmpp_alarm'} ||= 5; # For tests
  55. alarm $self->{'_xmpp_alarm'};
  56. $status = $xmpp_conn->Connect(
  57. 'hostname' => $srvr_name,
  58. 'componentname' => $cmpt_name,
  59. 'tls' => $self->{'contact'}{'XMPPUSETLS'},
  60. 'srv' => 1,
  61. 'ssl_ca_path' => $cab_loc,
  62. 'ssl_verify' => $self->{'contact'}{'XMPPVERIFYCERT'},
  63. );
  64. alarm 0;
  65. }
  66. if( !defined($status) ) {
  67. require Data::Dumper;
  68. die("Error: XMPP connection failed: " . Data::Dumper::Dumper($xmpp_conn->GetErrorCode()) );
  69. }
  70. my @result = $xmpp_conn->AuthSend(
  71. 'username' => $user_name,
  72. 'password' => $self->{'contact'}{'XMPPPASSWORD'},
  73. 'resource' => 'cPanel & WHM',
  74. );
  75. if( !@result || $result[0] ne "ok" ) {
  76. require Data::Dumper;
  77. die("Error: XMPP authentication failed: " . Data::Dumper::Dumper($xmpp_conn->GetErrorCode()) );
  78. }
  79. # TODO Error handling? There doesn't seem to be a good return from this sub.
  80. $xmpp_conn->MessageSend(
  81. 'to' => $args{'destination'},
  82. 'subject' => $args{'subject'},
  83. 'body' => $args{'content'},
  84. 'thread' => "cPNotifySpam",
  85. 'priority' => 10,
  86. );
  87. $xmpp_conn->Disconnect();
  88. return;
  89. }
  90. 1;