<commit_before><?php

/**
 * SMTP libs
 * @package modules
 * @subpackage smtp
 */

if (!defined('DEBUG_MODE')) { die(); }

/**
 * SMTP connection manager
 * @subpackage smtp/lib
 */
class Hm_SMTP_List {
    
    use Hm_Server_List;

    public static function service_connect($id, $server, $user, $pass, $cache=false) {
        $config = array(
            'server'    => $server['server'],
            'port'      => $server['port'],
            'tls'       => $server['tls'],
            'username'  => $user,
            'password'  => $pass
        );
        if (array_key_exists('auth', $server)) {
            $config['auth'] = $server['auth'];
        }
        self::$server_list[$id]['object'] = new Hm_SMTP($config);
        if (!self::$server_list[$id]['object']->connect()) {
            return self::$server_list[$id]['object'];
        }
        return false;
    }
    public static function get_cache($session, $id) {
        return false;
    }
}

/**
 * Connect to and interact with SMTP servers
 * @subpackage smtp/lib
 */
class Hm_SMTP {
    private $config;
    private $server;
    private $starttls;
    private $port;
    private $tls;
    private $auth;
    private $handle;
    private $debug;
    private $hostname;
    private $command_count;
    private $commands;
    private $responses;
    private $smtp_err;
    private $banner;
    private $capability;
    private $connected;
    private $crlf;
    private $line_length;
    private $username;
    private $password;
    public $state;
    private $request_auths = array();

    function __construct($conf) {

        $this->hostname = php_uname('n');
        if (preg_match("/:\d+$/", $this->hostname)) {
            $this->hostname = substr($this->hostname, 0, strpos($this->hostname, ':'));
        }
        $this->debug = array();
        if (isset($conf['server'])) {
            $this->server = $conf['server'];
        }
        else {
            $this->server = '127.0.0.1';
        }
        if (isset($conf['port'])) {
            $this->port = $conf['port'];
        }
        else {
            $this->port = 25;
        }
        if (isset($conf['tls']) && $conf['tls']) {
            $this->tls = true;
        }
        else {
            $this->tls = false;
        }
        if (!$this->tls) {
            $this->starttls = true;
        }
        $this->request_auths = array('cram-md5', 'login', 'plain');
        if (isset($conf['auth'])) {
            array_unshift($this->request_auths, $conf['auth']);
        }
        $this->smtp_err = '';
        $this->supports_tls = false;
        $this->auth = true;
        $this->supports_auth = array();
        $this->handle = false;
        $this->state = 'started';
        $this->command_count = 0;
        $this->commands = array();
        $this->responses = array();
        $this->banner = '';
        $this->crlf = "\r\n";
        $this->capability = '';
        $this->line_length = 2048;
        $this->connected = false;
        $this->username = $conf['username'];
        $this->password = $conf['password'];
        $this->max_message_size = 0;
    }

    /* send command to the server. Append "\r\n" to the end. */
    function send_command($command) {
        if (is_resource($this->handle)) {
            fputs($this->handle, $command.$this->crlf);
        }
        $this->commands[] = trim($command);
    }

    /* loop through "lines" returned from smtp and parse
       them. It can return the lines in a raw format, or 
       parsed into atoms. 
    */
    function get_response($chunked=true) {
        $n = -1;
        $result = array();
        $chunked_result = array();
        do {
            $n++;
            if (!is_resource($this->handle)) {
                break;
            }
            $result[$n] = fgets($this->handle, $this->line_length);
            $chunks = $this->parse_line($result[$n]);
            if ($chunked) {
                $chunked_result[] = $chunks;
            }
            if (!trim($result[$n])) {
                unset($result[$n]);
                break;
            }
            $cont = false;
            if (strlen($result[$n]) > 3 && substr($result[$n], 3, 1) == '-') {
                $cont = true;
            }
        } while ($cont);
        $this->responses[] = $result;
        if ($chunked) {
            $result = $chunked_result;
        }
        return $result;
    }

    /* parse out a line */
    function parse_line($line) {
        $parts = array();

        $code = substr($line, 0, 3);
        $parts[] = $code;

        $remainder = explode(' ',substr($line, 4));
        $parts[] = $remainder;

        return $parts;
        
    }
    /* Checks if the numeric response matches the code in $check. 
       The return value is simalar to strcmp
       Returns <0 if $check is less than the response
       Returns  0 if $check is equal to the response
       Returns >0 if $check is greater than the response
    */
    function compare_response($chunked_response, $check) {
        $size = count($chunked_response);
        if ($size) {
            $last = $chunked_response[$size-1];
            $code = $last[0];
        }
        else {
            $code = false;
        }
        $return_val = strcmp($check,$code);
        if ($return_val) {
            if (isset($chunked_response[0][1])) {
                $this->smtp_err = join(' ', $chunked_response[0][1]);
            }
        }
        return $return_val;
    }

    /* determine what capabilities the server has.
       Pass it the chunked response from EHLO  */
    function capabilities($ehlo_response) {
        foreach($ehlo_response as $line) {
            $feature = trim($line[1][0]);
            switch(strtolower($feature)) {
                case 'starttls': // supports starttls
                    $this->supports_tls = true;
                    break;
                case 'auth': // supported auth mechanisims
                    $auth_mecs = array_slice($line[1], 1);
                    $this->supports_auth = array_map(function($v) { return strtolower($v); }, $auth_mecs);
                    break;
                case 'size': // advisary maximum message size
                    if(isset($line[1][1]) && is_numeric($line[1][1])) {
                        $this->max_message_size = $line[1][1];
                    }
                    break;
            }
        }

    }

    /* establish a connection to the server. */
    function connect() {
        $certfile = false;
        $certpass = false;
        $result = 'An error occured connecting to the SMTP server';
        $server = $this->server;

        if ($this->tls) {
            $server = 'tls://'.$server;
        } 
        $this->debug[] = 'Connecting to '.$server.' on port '.$this->port;
        $this->handle = @fsockopen($server, $this->port, $errorno, $errorstr, 30);
        if (is_resource($this->handle)) {
            $this->debug[] = 'Successfully opened port to the SMTP server';
            $this->connected = true;
            $this->state = 'connected';
        }
        else {
            $this->debug[] = 'Could not connect to the SMTP server';
            $this->debug[] = 'fsockopen errors #'.$errorno.'. '.$errorstr;
            $result = 'Could not connect to the configured SMTP server';
        }
        $this->banner = $this->get_response();
        $command = 'EHLO '.$this->hostname;
        $this->send_command($command);
        $response = $this->get_response();
        $this->capabilities($response);
        if ($this->starttls && $this->supports_tls) {
            $command = 'STARTTLS';
            $this->send_command($command);
            $response = $this->get_response();
            if ($this->compare_response($response, '220') != 0) {
                $result = 'An error occured during the STARTTLS command';
            }
            if(isset($certfile) && $certfile) {
                stream_context_set_option($this->handle, 'tls', 'local_cert', $certfile);
                if($certpass) {
                    stream_context_set_option($this->handle, 'tls', 'passphrase', $certpass);
                }
            }
            stream_socket_enable_crypto($this->handle, true, STREAM_CRYPTO_METHOD_TLS_CLIENT);
            $command = 'EHLO '.$this->hostname;
            $this->send_command($command);
            $response = $this->get_response();
            $this->capabilities($response);
        }
        if($this->compare_response($response,'250') != 0) {
            $result = 'An error occured during the EHLO command';
        }
        else {
            if($this->auth) {
                $mech = $this->choose_auth();
                if ($mech) {
                    $result = $this->authenticate($this->username, $this->password, $mech);
                }
            }
            else {
                if ($this->state == 'connected') {
                    $result = false;
                }
            }
        }
        return $result;
    }

    function choose_auth() {
        if (empty($this->supports_auth)) {
            return false;
        }
        $intersect = array_intersect($this->request_auths, $this->supports_auth);
        if(count($intersect) > 0) {
            return array_shift($intersect);
        }
        return $requested[ count($requested) - 1 ];
    }

    /**
     * authenticate the username and password to the server
     * @todo fix xoauth2 error handling
     */
    function authenticate($username, $password, $mech) {
        $result = false;
        switch (strtolower($mech)) {
            case 'external':
                $command = 'AUTH EXTERNAL '.base64_encode($username);
                $this->send_command($command);
                break;<commit_msg>remove todo<commit_after><?php

/**
 * SMTP libs
 * @package modules
 * @subpackage smtp
 */

if (!defined('DEBUG_MODE')) { die(); }

/**
 * SMTP connection manager
 * @subpackage smtp/lib
 */
class Hm_SMTP_List {
    
    use Hm_Server_List;

    public static function service_connect($id, $server, $user, $pass, $cache=false) {
        $config = array(
            'server'    => $server['server'],
            'port'      => $server['port'],
            'tls'       => $server['tls'],
            'username'  => $user,
            'password'  => $<PASSWORD>
        );
        if (array_key_exists('auth', $server)) {
            $config['auth'] = $server['auth'];
        }
        self::$server_list[$id]['object'] = new Hm_SMTP($config);
        if (!self::$server_list[$id]['object']->connect()) {
            return self::$server_list[$id]['object'];
        }
        return false;
    }
    public static function get_cache($session, $id) {
        return false;
    }
}

/**
 * Connect to and interact with SMTP servers
 * @subpackage smtp/lib
 */
class Hm_SMTP {
    private $config;
    private $server;
    private $starttls;
    private $port;
    private $tls;
    private $auth;
    private $handle;
    private $debug;
    private $hostname;
    private $command_count;
    private $commands;
    private $responses;
    private $smtp_err;
    private $banner;
    private $capability;
    private $connected;
    private $crlf;
    private $line_length;
    private $username;
    private $password;
    public $state;
    private $request_auths = array();

    function __construct($conf) {

        $this->hostname = php_uname('n');
        if (preg_match("/:\d+$/", $this->hostname)) {
            $this->hostname = substr($this->hostname, 0, strpos($this->hostname, ':'));
        }
        $this->debug = array();
        if (isset($conf['server'])) {
            $this->server = $conf['server'];
        }
        else {
            $this->server = '127.0.0.1';
        }
        if (isset($conf['port'])) {
            $this->port = $conf['port'];
        }
        else {
            $this->port = 25;
        }
        if (isset($conf['tls']) && $conf['tls']) {
            $this->tls = true;
        }
        else {
            $this->tls = false;
        }
        if (!$this->tls) {
            $this->starttls = true;
        }
        $this->request_auths = array('<PASSWORD>', 'login', 'plain');
        if (isset($conf['auth'])) {
            array_unshift($this->request_auths, $conf['auth']);
        }
        $this->smtp_err = '';
        $this->supports_tls = false;
        $this->auth = true;
        $this->supports_auth = array();
        $this->handle = false;
        $this->state = 'started';
        $this->command_count = 0;
        $this->commands = array();
        $this->responses = array();
        $this->banner = '';
        $this->crlf = "\r\n";
        $this->capability = '';
        $this->line_length = 2048;
        $this->connected = false;
        $this->username = $conf['username'];
        $this->password = $conf['password'];
        $this->max_message_size = 0;
    }

    /* send command to the server. Append "\r\n" to the end. */
    function send_command($command) {
        if (is_resource($this->handle)) {
            fputs($this->handle, $command.$this->crlf);
        }
        $this->commands[] = trim($command);
    }

    /* loop through "lines" returned from smtp and parse
       them. It can return the lines in a raw format, or 
       parsed into atoms. 
    */
    function get_response($chunked=true) {
        $n = -1;
        $result = array();
        $chunked_result = array();
        do {
            $n++;
            if (!is_resource($this->handle)) {
                break;
            }
            $result[$n] = fgets($this->handle, $this->line_length);
            $chunks = $this->parse_line($result[$n]);
            if ($chunked) {
                $chunked_result[] = $chunks;
            }
            if (!trim($result[$n])) {
                unset($result[$n]);
                break;
            }
            $cont = false;
            if (strlen($result[$n]) > 3 && substr($result[$n], 3, 1) == '-') {
                $cont = true;
            }
        } while ($cont);
        $this->responses[] = $result;
        if ($chunked) {
            $result = $chunked_result;
        }
        return $result;
    }

    /* parse out a line */
    function parse_line($line) {
        $parts = array();

        $code = substr($line, 0, 3);
        $parts[] = $code;

        $remainder = explode(' ',substr($line, 4));
        $parts[] = $remainder;

        return $parts;
        
    }
    /* Checks if the numeric response matches the code in $check. 
       The return value is simalar to strcmp
       Returns <0 if $check is less than the response
       Returns  0 if $check is equal to the response
       Returns >0 if $check is greater than the response
    */
    function compare_response($chunked_response, $check) {
        $size = count($chunked_response);
        if ($size) {
            $last = $chunked_response[$size-1];
            $code = $last[0];
        }
        else {
            $code = false;
        }
        $return_val = strcmp($check,$code);
        if ($return_val) {
            if (isset($chunked_response[0][1])) {
                $this->smtp_err = join(' ', $chunked_response[0][1]);
            }
        }
        return $return_val;
    }

    /* determine what capabilities the server has.
       Pass it the chunked response from EHLO  */
    function capabilities($ehlo_response) {
        foreach($ehlo_response as $line) {
            $feature = trim($line[1][0]);
            switch(strtolower($feature)) {
                case 'starttls': // supports starttls
                    $this->supports_tls = true;
                    break;
                case 'auth': // supported auth mechanisims
                    $auth_mecs = array_slice($line[1], 1);
                    $this->supports_auth = array_map(function($v) { return strtolower($v); }, $auth_mecs);
                    break;
                case 'size': // advisary maximum message size
                    if(isset($line[1][1]) && is_numeric($line[1][1])) {
                        $this->max_message_size = $line[1][1];
                    }
                    break;
            }
        }

    }

    /* establish a connection to the server. */
    function connect() {
        $certfile = false;
        $certpass = false;
        $result = 'An error occured connecting to the SMTP server';
        $server = $this->server;

        if ($this->tls) {
            $server = 'tls://'.$server;
        } 
        $this->debug[] = 'Connecting to '.$server.' on port '.$this->port;
        $this->handle = @fsockopen($server, $this->port, $errorno, $errorstr, 30);
        if (is_resource($this->handle)) {
            $this->debug[] = 'Successfully opened port to the SMTP server';
            $this->connected = true;
            $this->state = 'connected';
        }
        else {
            $this->debug[] = 'Could not connect to the SMTP server';
            $this->debug[] = 'fsockopen errors #'.$errorno.'. '.$errorstr;
            $result = 'Could not connect to the configured SMTP server';
        }
        $this->banner = $this->get_response();
        $command = 'EHLO '.$this->hostname;
        $this->send_command($command);
        $response = $this->get_response();
        $this->capabilities($response);
        if ($this->starttls && $this->supports_tls) {
            $command = 'STARTTLS';
            $this->send_command($command);
            $response = $this->get_response();
            if ($this->compare_response($response, '220') != 0) {
                $result = 'An error occured during the STARTTLS command';
            }
            if(isset($certfile) && $certfile) {
                stream_context_set_option($this->handle, 'tls', 'local_cert', $certfile);
                if($certpass) {
                    stream_context_set_option($this->handle, 'tls', 'passphrase', $certpass);
                }
            }
            stream_socket_enable_crypto($this->handle, true, STREAM_CRYPTO_METHOD_TLS_CLIENT);
            $command = 'EHLO '.$this->hostname;
            $this->send_command($command);
            $response = $this->get_response();
            $this->capabilities($response);
        }
        if($this->compare_response($response,'250') != 0) {
            $result = 'An error occured during the EHLO command';
        }
        else {
            if($this->auth) {
                $mech = $this->choose_auth();
                if ($mech) {
                    $result = $this->authenticate($this->username, $this->password, $mech);
                }
            }
            else {
                if ($this->state == 'connected') {
                    $result = false;
                }
            }
        }
        return $result;
    }

    function choose_auth() {
        if (empty($this->supports_auth)) {
            return false;
        }
        $intersect = array_intersect($this->request_auths, $this->supports_auth);
        if(count($intersect) > 0) {
            return array_shift($intersect);
        }
        return $requested[ count($requested) - 1 ];
    }

    /**
     * authenticate the username and password to the server
     */
    function authenticate($username, $password, $mech) {
        $result = false;
        switch (strtolower($mech)) {
            case 'external':
                $command = 'AUTH EXTERNAL '.base64_encode($username);
                $this->send_command($command);
                break;
{'fraction_non_alphanumeric': 0.1527763522528995, 'fraction_numerical': 0.005747716309145027, 'mean_word_length': 1.7148230704931735, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 197, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 2, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4519632', 'n_tokens_mistral': 5761, 'n_tokens_neox': 5605, 'n_words': 1245}