XMPP.pm 3.7 KB

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