#!/usr/bin/php -q ", ":", ";", ",", "'", "\"", "&", "$", "#", "*", "(", ")", "|", "~", "`", "!", "{", "}"]; $string = trim(str_replace($special_chars, "", $string)); $string = preg_replace('~[^0-9a-z -_]~i', '', $string); $string = preg_replace('~[- ]~i', '_', $string); return trim($string); } /* Call this when using the subject field in email or agents. Do not use when showing the subject in a browser. Removes all HTML entities from subject line, is specifically targetting the my_temp() function, which adds ' °' */ function clean_subject($subject) { $subject = preg_replace("/&#?[a-z0-9]{2,8};/i"," ",$subject); return $subject; } /** * Wrap string values in double quotes for INI compatibility and escape quotes/backslashes. * Numeric types remain unquoted so they can be parsed as-is. */ function ini_encode_value($value) { if (is_int($value) || is_float($value)) return $value; if (is_bool($value)) return $value ? 'true' : 'false'; $value = (string)$value; return '"'.strtr($value, ["\\"=>"\\\\", '"' => '\\"']).'"'; } function build_ini_string(array $data) { $lines = []; foreach ($data as $key => $value) { $lines[] = "{$key}=".ini_encode_value($value); } return implode("\n", $lines)."\n"; } /** * Trims and unescapes strings (eg quotes, backslashes) if necessary. */ function ini_decode_value($value) { $value = trim($value); $length = strlen($value); if ($length >= 2 && $value[0] === '"' && $value[$length-1] === '"') { return stripslashes(substr($value, 1, -1)); } return $value; } // start if ($argc == 1) exit(usage()); extract(parse_plugin_cfg("dynamix",true)); $path = _var($notify,'path','/tmp/notifications'); $unread = "$path/unread"; $archive = "$path/archive"; $agents_dir = "/boot/config/plugins/dynamix/notifications/agents"; if (is_dir($agents_dir)) { $agents = []; foreach (array_diff(scandir($agents_dir), ['.','..']) as $p) { if (file_exists("{$agents_dir}/{$p}")) $agents[] = "{$agents_dir}/{$p}"; } } else { $agents = NULL; } switch ($argv[1][0]=='-' ? 'add' : $argv[1]) { case 'init': $files = glob("$unread/*.notify", GLOB_NOSORT); foreach ($files as $file) if (!is_readable($file)) chmod($file,0666); break; case 'smtp-init': @mkdir($unread,0755,true); @mkdir($archive,0755,true); $conf = []; $conf[] = "# Generated settings:"; $conf[] = "Root={$ssmtp['root']}"; $domain = strtok($ssmtp['root'],'@'); $domain = strtok('@'); $conf[] = "rewriteDomain=$domain"; $conf[] = "FromLineOverride=YES"; $conf[] = "Mailhub={$ssmtp['server']}:{$ssmtp['port']}"; $conf[] = "UseTLS={$ssmtp['UseTLS']}"; $conf[] = "UseSTARTTLS={$ssmtp['UseSTARTTLS']}"; if ($ssmtp['AuthMethod'] != "none") { $conf[] = "AuthMethod={$ssmtp['AuthMethod']}"; $conf[] = "AuthUser={$ssmtp['AuthUser']}"; $conf[] = "AuthPass=".base64_decrypt($ssmtp['AuthPass']); } $conf[] = ""; file_put_contents("/etc/ssmtp/ssmtp.conf", implode("\n", $conf)); break; case 'cron-init': @mkdir($unread,0755,true); @mkdir($archive,0755,true); $text = empty($notify['status']) ? "" : "# Generated array status check schedule:\n{$notify['status']} $docroot/plugins/dynamix/scripts/statuscheck &> /dev/null\n\n"; parse_cron_cfg("dynamix", "status-check", $text); $text = empty($notify['unraidos']) ? "" : "# Generated Unraid OS update check schedule:\n{$notify['unraidos']} $docroot/plugins/dynamix.plugin.manager/scripts/unraidcheck &> /dev/null\n\n"; parse_cron_cfg("dynamix", "unraid-check", $text); $text = empty($notify['version']) ? "" : "# Generated plugins version check schedule:\n{$notify['version']} $docroot/plugins/dynamix.plugin.manager/scripts/plugincheck &> /dev/null\n\n"; parse_cron_cfg("dynamix", "plugin-check", $text); $text = empty($notify['system']) ? "" : "# Generated system monitoring schedule:\n{$notify['system']} $docroot/plugins/dynamix/scripts/monitor &> /dev/null\n\n"; parse_cron_cfg("dynamix", "monitor", $text); $text = empty($notify['docker_update']) ? "" : "# Generated docker monitoring schedule:\n{$notify['docker_update']} $docroot/plugins/dynamix.docker.manager/scripts/dockerupdate check &> /dev/null\n\n"; parse_cron_cfg("dynamix", "docker-update", $text); $text = empty($notify['language_update']) ? "" : "# Generated languages version check schedule:\n{$notify['language_update']} $docroot/plugins/dynamix.plugin.manager/scripts/languagecheck &> /dev/null\n\n"; parse_cron_cfg("dynamix", "language-check", $text); break; case 'add': $event = 'Unraid Status'; $subject = 'Notification'; $description = 'No description'; $importance = 'normal'; $message = $recipients = $link = $fqdnlink = ''; $timestamp = time(); $ticket = $timestamp; $mailtest = false; $overrule = false; $noBrowser = false; $options = getopt("l:e:s:d:i:m:r:xtb"); foreach ($options as $option => $value) { switch ($option) { case 'e': $event = $value; break; case 's': $subject = $value; break; case 'd': $description = $value; break; case 'i': $importance = strtok($value,' '); $overrule = strtok(' '); break; case 'm': $message = $value; break; case 'r': $recipients = $value; break; case 'x': $ticket = 'ticket'; break; case 't': $mailtest = true; break; case 'b': $noBrowser = true; break; case 'l': $nginx = (array)@parse_ini_file('/var/local/emhttp/nginx.ini'); $link = $value; $fqdnlink = (strpos($link,"http") === 0) ? $link : ($nginx['NGINX_DEFAULTURL']??'').$link; break; } } $unread = "{$unread}/".safe_filename("{$event}-{$ticket}.notify"); $archive = "{$archive}/".safe_filename("{$event}-{$ticket}.notify"); if (file_exists($archive)) break; $entity = $overrule===false ? $notify[$importance] : $overrule; $cleanSubject = clean_subject($subject); $archiveData = [ 'timestamp' => $timestamp, 'event' => $event, 'subject' => $cleanSubject, 'description' => $description, 'importance' => $importance, ]; if ($message) $archiveData['message'] = str_replace('\n','
',$message); if (!$mailtest) file_put_contents($archive, build_ini_string($archiveData)); if (($entity & 1)==1 && !$mailtest && !$noBrowser) { $unreadData = [ 'timestamp' => $timestamp, 'event' => $event, 'subject' => $cleanSubject, 'description' => $description, 'importance' => $importance, 'link' => $link, ]; file_put_contents($unread, build_ini_string($unreadData)); } if (($entity & 2)==2 || $mailtest) generate_email($event, $cleanSubject, str_replace('
','. ',$description), $importance, $message, $recipients, $fqdnlink); if (($entity & 4)==4 && !$mailtest) { if (is_array($agents)) {foreach ($agents as $agent) {exec("TIMESTAMP='$timestamp' EVENT=".escapeshellarg($event)." SUBJECT=".escapeshellarg($cleanSubject)." DESCRIPTION=".escapeshellarg($description)." IMPORTANCE=".escapeshellarg($importance)." CONTENT=".escapeshellarg($message)." LINK=".escapeshellarg($fqdnlink)." bash ".$agent);};}}; break; case 'get': $output = []; $json = []; $files = glob("$unread/*.notify", GLOB_NOSORT); usort($files, function($a,$b){return filemtime($a)-filemtime($b);}); $i = 0; foreach ($files as $file) { $fields = file($file,FILE_IGNORE_NEW_LINES|FILE_SKIP_EMPTY_LINES); $time = true; $output[$i]['file'] = basename($file); $output[$i]['show'] = (fileperms($file) & 0x0FFF)==0400 ? 0 : 1; foreach ($fields as $field) { if (!$field) continue; # limit the explode('=', …) used during reads to two pieces so values containing = remain intact [$key,$val] = array_pad(explode('=', $field, 2),2,''); if ($time) {$val = date($notify['date'].' '.$notify['time'], $val); $time = false;} # unescape the value before emitting JSON, so the browser UI # and any scripts calling `notify get` still see plain strings $output[$i][trim($key)] = ini_decode_value($val); } $i++; } echo json_encode($output, JSON_UNESCAPED_SLASHES|JSON_UNESCAPED_UNICODE); break; case 'archive': if ($argc != 3) exit(usage()); $file = $argv[2]; if (strpos(realpath("$unread/$file"),$unread.'/')===0) @unlink("$unread/$file"); break; } exit(0); ?>