2017-12-09 20:17:15 +08:00
// Base64 functions
var Base64 = { _keyStr : "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=" , encode : function ( r ) { var t , e , o , a , h , n , c , d = "" , C = 0 ; for ( r = Base64 . _utf8 _encode ( r ) ; C < r . length ; ) a = ( t = r . charCodeAt ( C ++ ) ) >> 2 , h = ( 3 & t ) << 4 | ( e = r . charCodeAt ( C ++ ) ) >> 4 , n = ( 15 & e ) << 2 | ( o = r . charCodeAt ( C ++ ) ) >> 6 , c = 63 & o , isNaN ( e ) ? n = c = 64 : isNaN ( o ) && ( c = 64 ) , d = d + this . _keyStr . charAt ( a ) + this . _keyStr . charAt ( h ) + this . _keyStr . charAt ( n ) + this . _keyStr . charAt ( c ) ; return d } , decode : function ( r ) { var t , e , o , a , h , n , c = "" , d = 0 ; for ( r = r . replace ( /[^A-Za-z0-9\+\/\=]/g , "" ) ; d < r . length ; ) t = this . _keyStr . indexOf ( r . charAt ( d ++ ) ) << 2 | ( a = this . _keyStr . indexOf ( r . charAt ( d ++ ) ) ) >> 4 , e = ( 15 & a ) << 4 | ( h = this . _keyStr . indexOf ( r . charAt ( d ++ ) ) ) >> 2 , o = ( 3 & h ) << 6 | ( n = this . _keyStr . indexOf ( r . charAt ( d ++ ) ) ) , c += String . fromCharCode ( t ) , 64 != h && ( c += String . fromCharCode ( e ) ) , 64 != n && ( c += String . fromCharCode ( o ) ) ; return c = Base64 . _utf8 _decode ( c ) } , _utf8 _encode : function ( r ) { r = r . replace ( /\r\n/g , "\n" ) ; for ( var t = "" , e = 0 ; e < r . length ; e ++ ) { var o = r . charCodeAt ( e ) ; o < 128 ? t += String . fromCharCode ( o ) : o > 127 && o < 2048 ? ( t += String . fromCharCode ( o >> 6 | 192 ) , t += String . fromCharCode ( 63 & o | 128 ) ) : ( t += String . fromCharCode ( o >> 12 | 224 ) , t += String . fromCharCode ( o >> 6 & 63 | 128 ) , t += String . fromCharCode ( 63 & o | 128 ) ) } return t } , _utf8 _decode : function ( r ) { for ( var t = "" , e = 0 , o = c1 = c2 = 0 ; e < r . length ; ) ( o = r . charCodeAt ( e ) ) < 128 ? ( t += String . fromCharCode ( o ) , e ++ ) : o > 191 && o < 224 ? ( c2 = r . charCodeAt ( e + 1 ) , t += String . fromCharCode ( ( 31 & o ) << 6 | 63 & c2 ) , e += 2 ) : ( c2 = r . charCodeAt ( e + 1 ) , c3 = r . charCodeAt ( e + 2 ) , t += String . fromCharCode ( ( 15 & o ) << 12 | ( 63 & c2 ) << 6 | 63 & c3 ) , e += 3 ) ; return t } } ;
2019-03-13 04:54:31 +08:00
2017-12-09 20:17:15 +08:00
jQuery ( function ( $ ) {
2019-01-29 07:20:39 +08:00
acl _data = JSON . parse ( acl ) ;
2017-12-09 20:17:15 +08:00
// http://stackoverflow.com/questions/24816/escaping-html-strings-with-jquery
var entityMap = { "&" : "&" , "<" : "<" , ">" : ">" , '"' : """ , "'" : "'" , "/" : "/" , "`" : "`" , "=" : "=" } ;
function escapeHtml ( n ) { return String ( n ) . replace ( /[&<>"'`=\/]/g , function ( n ) { return entityMap [ n ] } ) }
function humanFileSize ( i ) { if ( Math . abs ( i ) < 1024 ) return i + " B" ; var B = [ "KiB" , "MiB" , "GiB" , "TiB" , "PiB" , "EiB" , "ZiB" , "YiB" ] , e = - 1 ; do { i /= 1024 , ++ e } while ( Math . abs ( i ) >= 1024 && e < B . length - 1 ) ; return i . toFixed ( 1 ) + " " + B [ e ] }
2020-02-23 02:23:57 +08:00
// Set paging
$ ( '[data-page-size]' ) . on ( 'click' , function ( e ) {
e . preventDefault ( ) ;
var new _size = $ ( this ) . data ( 'page-size' ) ;
var parent _ul = $ ( this ) . closest ( 'ul' ) ;
var table _id = $ ( parent _ul ) . data ( 'table-id' ) ;
FooTable . get ( '#' + table _id ) . pageSize ( new _size ) ;
//$(this).parent().addClass('active').siblings().removeClass('active')
heading = $ ( this ) . parents ( '.panel' ) . find ( '.panel-heading' )
var n _results = $ ( heading ) . children ( '.table-lines' ) . text ( ) . split ( ' / ' ) [ 1 ] ;
$ ( heading ) . children ( '.table-lines' ) . text ( function ( ) {
if ( new _size > n _results ) {
new _size = n _results ;
}
return new _size + ' / ' + n _results ;
} )
} ) ;
$ ( ".refresh_table" ) . on ( 'click' , function ( e ) {
e . preventDefault ( ) ;
var table _name = $ ( this ) . data ( 'table' ) ;
$ ( '#' + table _name ) . find ( "tr.footable-empty" ) . remove ( ) ;
draw _table = $ ( this ) . data ( 'draw' ) ;
eval ( draw _table + '()' ) ;
} ) ;
function table _quarantine _ready ( ft , name ) {
$ ( '.refresh_table' ) . prop ( "disabled" , false ) ;
heading = ft . $el . parents ( '.panel' ) . find ( '.panel-heading' )
var ft _paging = ft . use ( FooTable . Paging )
$ ( heading ) . children ( '.table-lines' ) . text ( function ( ) {
var total _rows = ft _paging . totalRows ;
var size = ft _paging . size ;
if ( size > total _rows ) {
size = total _rows ;
}
return size + ' / ' + total _rows ;
} )
}
2018-02-09 03:13:36 +08:00
function draw _quarantine _table ( ) {
ft _quarantinetable = FooTable . init ( '#quarantinetable' , {
2017-12-09 20:17:15 +08:00
"columns" : [
2019-01-29 07:20:39 +08:00
{ "name" : "chkbox" , "title" : "" , "style" : { "maxWidth" : "60px" , "width" : "60px" } , "filterable" : false , "sortable" : false , "type" : "html" } ,
2017-12-09 20:17:15 +08:00
{ "name" : "id" , "type" : "ID" , "filterable" : false , "sorted" : true , "direction" : "DESC" , "title" : "ID" , "style" : { "width" : "50px" } } ,
2019-01-29 07:20:39 +08:00
{ "name" : "qid" , "breakpoints" : "all" , "type" : "text" , "title" : lang . qid , "style" : { "width" : "125px" } } ,
{ "name" : "sender" , "title" : lang . sender } ,
2019-11-11 23:59:39 +08:00
{ "name" : "subject" , "title" : lang . subj , "type" : "text" } ,
2020-11-06 21:26:48 +08:00
{ "name" : "rspamdaction" , "title" : lang . rspamd _result , "type" : "html" } ,
2019-01-29 07:20:39 +08:00
{ "name" : "rcpt" , "title" : lang . rcpt , "breakpoints" : "xs sm md" , "type" : "text" } ,
{ "name" : "virus" , "title" : lang . danger , "type" : "text" } ,
2019-07-24 01:52:46 +08:00
{ "name" : "score" , "title" : lang . spam _score , "type" : "text" } ,
2019-11-11 23:59:39 +08:00
{ "name" : "notified" , "title" : lang . notified , "type" : "text" } ,
2020-09-22 00:29:30 +08:00
{ "name" : "created" , "formatter" : function unix _time _format ( tm ) { var date = new Date ( tm ? tm * 1000 : 0 ) ; return date . toLocaleDateString ( undefined , { year : "numeric" , month : "2-digit" , day : "2-digit" , hour : "2-digit" , minute : "2-digit" , second : "2-digit" } ) ; } , "title" : lang . received , "style" : { "width" : "170px" } } ,
2020-03-25 01:46:11 +08:00
{ "name" : "action" , "filterable" : false , "sortable" : false , "style" : { "text-align" : "right" } , "style" : { "min-width" : "200px" } , "type" : "html" , "title" : lang . action , "breakpoints" : "xs sm md" }
2017-12-09 20:17:15 +08:00
] ,
"rows" : $ . ajax ( {
dataType : 'json' ,
2018-02-09 03:13:36 +08:00
url : '/api/v1/get/quarantine/all' ,
2017-12-09 20:17:15 +08:00
jsonp : false ,
error : function ( ) {
2018-02-09 03:13:36 +08:00
console . log ( 'Cannot draw quarantine table' ) ;
2017-12-09 20:17:15 +08:00
} ,
success : function ( data ) {
$ . each ( data , function ( i , item ) {
2019-01-18 05:00:18 +08:00
if ( item . subject === null ) {
2019-01-29 07:20:39 +08:00
item . subject = '' ;
} else {
2019-01-18 05:00:18 +08:00
item . subject = escapeHtml ( item . subject ) ;
}
2019-07-24 01:52:46 +08:00
if ( item . score === null ) {
item . score = '-' ;
}
2019-01-29 07:20:39 +08:00
if ( item . virus _flag > 0 ) {
2020-11-06 21:26:48 +08:00
item . virus = '<span class="label label-danger">' + lang . high _danger + '</span>' ;
2019-01-29 07:20:39 +08:00
} else {
2020-11-06 21:26:48 +08:00
item . virus = '<span class="label label-default">' + lang . neutral _danger + '</span>' ;
}
if ( item . action === "reject" ) {
item . rspamdaction = '<span class="label label-danger">' + lang . rejected + '</span>' ;
} else if ( item . action === "add header" ) {
item . rspamdaction = '<span class="label label-warning">' + lang . junk _folder + '</span>' ;
2019-01-29 07:20:39 +08:00
}
2019-11-11 23:59:39 +08:00
if ( item . notified > 0 ) {
item . notified = '✔' ;
} else {
item . notified = '✖' ;
}
2019-01-29 07:20:39 +08:00
if ( acl _data . login _as === 1 ) {
2017-12-09 20:17:15 +08:00
item . action = '<div class="btn-group">' +
'<a href="#" data-item="' + encodeURI ( item . id ) + '" class="btn btn-xs btn-info show_qid_info"><span class="glyphicon glyphicon-modal-window"></span> ' + lang . show _item + '</a>' +
[Docker API] Use TLS encryption for communication with "on-the-fly" created key paris (non-exposed)
[Docker API] Create pipe to pass Rspamd UI worker password
[Dovecot] Pull Spamassassin ruleset to be read by Rspamd (MANY THANKS to Peer Heinlein!)
[Dovecot] Garbage collector for deleted maildirs (set keep time via MAILDIR_GC_TIME which defaults to 1440 minutes)
[Web] Flush memcached after mailbox item changes, fixes #1808
[Web] Fix duplicate IDs, fixes #1792
[Compose] Use SQL sockets
[PHP-FPM] Update APCu and Redis libs
[Dovecot] Encrypt maildir with global key pair in crypt-vol-1 (BACKUP!), also fixes #1791
[Web] Fix deletion of spam aliases
[Helper] Add "crypt" to backup script
[Helper] Override file for external SQL socket (not supported!)
[Compose] New images for Rspamd, PHP-FPM, SOGo, Dovecot, Docker API, Watchdog, ACME, Postfix
2018-09-30 04:01:23 +08:00
'<a href="#" data-action="delete_selected" data-id="del-single-qitem" data-api-url="delete/qitem" data-item="' + encodeURI ( item . id ) + '" class="btn btn-xs btn-danger"><span class="glyphicon glyphicon-trash"></span> ' + lang . remove + '</a>' +
2017-12-09 20:17:15 +08:00
'</div>' ;
2019-01-29 07:20:39 +08:00
}
else {
item . action = '<div class="btn-group">' +
'<a href="#" data-item="' + encodeURI ( item . id ) + '" class="btn btn-xs btn-info show_qid_info"><span class="glyphicon glyphicon-modal-window"></span> ' + lang . show _item + '</a>' +
'</div>' ;
}
2017-12-09 20:17:15 +08:00
item . chkbox = '<input type="checkbox" data-id="qitems" name="multi_select" value="' + item . id + '" />' ;
} ) ;
}
} ) ,
"empty" : lang . empty ,
"paging" : { "enabled" : true , "limit" : 5 , "size" : pagination _size } ,
"sorting" : { "enabled" : true } ,
"filtering" : { "enabled" : true , "position" : "left" , "connectors" : false , "placeholder" : lang . filter _table } ,
2020-02-23 02:23:57 +08:00
"toggleSelector" : "table tbody span.footable-toggle" ,
"on" : {
"destroy.ft.table" : function ( e , ft ) {
$ ( '.refresh_table' ) . attr ( 'disabled' , 'true' ) ;
} ,
"ready.ft.table" : function ( e , ft ) {
table _quarantine _ready ( ft , 'quarantinetable' ) ;
} ,
"after.ft.filtering" : function ( e , ft ) {
table _quarantine _ready ( ft , 'quarantinetable' ) ;
}
} ,
2017-12-09 20:17:15 +08:00
} ) ;
}
2019-03-13 04:54:31 +08:00
$ ( 'body' ) . on ( 'click' , '.show_qid_info' , function ( e ) {
e . preventDefault ( ) ;
var qitem = $ ( this ) . data ( 'item' ) ;
var qError = $ ( "#qid_error" ) ;
$ ( '#qidDetailModal' ) . modal ( 'show' ) ;
qError . hide ( ) ;
$ . ajax ( {
url : '/inc/ajax/qitem_details.php' ,
data : { id : qitem } ,
dataType : 'json' ,
success : function ( data ) {
2020-11-09 21:42:26 +08:00
2019-03-13 04:54:31 +08:00
$ ( '[data-id="qitems_single"]' ) . each ( function ( index ) {
$ ( this ) . attr ( "data-item" , qitem ) ;
} ) ;
$ ( '#qid_detail_subj' ) . text ( data . subject ) ;
2020-06-06 19:25:32 +08:00
$ ( '#qid_detail_hfrom' ) . text ( data . header _from ) ;
$ ( '#qid_detail_efrom' ) . text ( data . env _from ) ;
2020-11-06 21:26:48 +08:00
$ ( '#qid_detail_score' ) . html ( '' ) ;
$ ( '#qid_detail_recipients' ) . html ( '' ) ;
2019-10-10 04:07:26 +08:00
$ ( '#qid_detail_symbols' ) . html ( '' ) ;
2020-10-24 22:27:31 +08:00
$ ( '#qid_detail_fuzzy' ) . html ( '' ) ;
2019-10-10 04:07:26 +08:00
if ( typeof data . symbols !== 'undefined' ) {
data . symbols . sort ( function ( a , b ) {
if ( a . score === 0 ) return 1
if ( b . score === 0 ) return - 1
2019-10-12 19:31:10 +08:00
if ( b . score < 0 && a . score < 0 ) {
return a . score - b . score
}
if ( b . score > 0 && a . score > 0 ) {
return b . score - a . score
}
2019-10-10 04:07:26 +08:00
return b . score - a . score
} )
$ . each ( data . symbols , function ( index , value ) {
var highlightClass = ''
if ( value . score > 0 ) highlightClass = 'negative'
else if ( value . score < 0 ) highlightClass = 'positive'
else highlightClass = 'neutral'
2020-03-05 20:09:38 +08:00
$ ( '#qid_detail_symbols' ) . append ( '<span data-toggle="tooltip" class="rspamd-symbol ' + highlightClass + '" title="' + ( value . options ? value . options . join ( ', ' ) : '' ) + '">' + value . name + ' (<span class="score">' + value . score + '</span>)</span>' ) ;
2019-10-10 04:07:26 +08:00
} ) ;
2020-03-05 20:09:38 +08:00
$ ( '[data-toggle="tooltip"]' ) . tooltip ( )
2019-10-10 04:07:26 +08:00
}
2020-11-06 21:26:48 +08:00
if ( typeof data . fuzzy _hashes === 'object' && data . fuzzy _hashes !== null && data . fuzzy _hashes . length !== 0 ) {
2020-10-24 22:27:31 +08:00
$ . each ( data . fuzzy _hashes , function ( index , value ) {
$ ( '#qid_detail_fuzzy' ) . append ( '<p style="font-family:monospace">' + value + '</p>' ) ;
} ) ;
} else {
$ ( '#qid_detail_fuzzy' ) . append ( '-' ) ;
}
2020-11-06 21:26:48 +08:00
if ( typeof data . score !== 'undefined' && typeof data . action !== 'undefined' ) {
if ( data . action == "add header" ) {
$ ( '#qid_detail_score' ) . append ( '<span class="label-rspamd-action label label-warning"><b>' + data . score + '</b> - ' + lang . junk _folder + '</span>' ) ;
} else {
$ ( '#qid_detail_score' ) . append ( '<span class="label-rspamd-action label label-danger"><b>' + data . score + '</b> - ' + lang . rejected + '</span>' ) ;
}
}
2019-05-01 06:56:12 +08:00
if ( typeof data . recipients !== 'undefined' ) {
$ . each ( data . recipients , function ( index , value ) {
2019-05-01 07:03:16 +08:00
var elem = $ ( '<span class="mail-address-item"></span>' ) ;
2020-06-07 16:45:40 +08:00
elem . text ( value . address + ' (' + value . type . toUpperCase ( ) + ')' ) ;
2019-05-01 07:03:16 +08:00
$ ( '#qid_detail_recipients' ) . append ( elem ) ;
2019-05-01 06:56:12 +08:00
} ) ;
}
2020-11-06 21:26:48 +08:00
$ ( '#qid_detail_text' ) . text ( data . text _plain ) ;
$ ( '#qid_detail_text_from_html' ) . text ( data . text _html ) ;
2019-05-01 06:56:12 +08:00
var qAtts = $ ( "#qid_detail_atts" ) ;
2019-03-13 04:54:31 +08:00
if ( typeof data . attachments !== 'undefined' ) {
qAtts . text ( '' ) ;
$ . each ( data . attachments , function ( index , value ) {
qAtts . append (
'<p><a href="/inc/ajax/qitem_details.php?id=' + qitem + '&att=' + index + '" target="_blank">' + value [ 0 ] + '</a> (' + value [ 1 ] + ')' +
' - <small><a href="' + value [ 3 ] + '" target="_blank">' + lang . check _hash + '</a></small></p>'
) ;
2018-11-27 17:20:42 +08:00
} ) ;
2018-01-18 16:13:36 +08:00
}
2019-03-13 04:54:31 +08:00
else {
qAtts . text ( '-' ) ;
}
2020-11-09 21:42:26 +08:00
} ,
error : function ( data ) {
if ( typeof data . error !== 'undefined' ) {
qError . text ( "Error loading quarantine item" ) ;
qError . show ( ) ;
}
2019-03-13 04:54:31 +08:00
}
} ) ;
} ) ;
2019-07-28 00:56:51 +08:00
$ ( 'body' ) . on ( 'click' , 'span.footable-toggle' , function ( ) {
2019-07-27 23:14:56 +08:00
event . stopPropagation ( ) ;
} )
2017-12-09 20:17:15 +08:00
// Initial table drawings
2018-02-09 03:13:36 +08:00
draw _quarantine _table ( ) ;
2018-01-19 02:14:18 +08:00
} ) ;