mirror of
				https://bitbucket.org/jsuto/piler.git
				synced 2025-10-31 06:52:26 +01:00 
			
		
		
		
	Merge branch 'master' of bitbucket.org:jsuto/piler
This commit is contained in:
		| @@ -1,6 +1,3 @@ | |||||||
| - Introduced the archive_address feature, see etc/example.conf for the details |  | ||||||
| - Introduced the raw: search label |  | ||||||
|  |  | ||||||
| 1.3.12: | 1.3.12: | ||||||
| ------- | ------- | ||||||
|  |  | ||||||
| @@ -14,6 +11,17 @@ | |||||||
|   - TLSv1.2 (default) |   - TLSv1.2 (default) | ||||||
|   - TLSv1.3 |   - TLSv1.3 | ||||||
|  |  | ||||||
|  | - Introduced the archive_address feature, see etc/example.conf for the details | ||||||
|  | - Introduced the raw: search label | ||||||
|  | - Added Italian translation. Credits: Stefano Gatto | ||||||
|  | - timestamp signing sorts by 'id' column | ||||||
|  | - timestamp hash value defaults to sha256 | ||||||
|  | - Minor fixes | ||||||
|  | - Added support for php 8.1 | ||||||
|  | - Fixed handling long email addresses | ||||||
|  |  | ||||||
|  | Be sure to apply util/db-upgrade.sql | ||||||
|  |  | ||||||
|  |  | ||||||
| 1.3.11: | 1.3.11: | ||||||
| ------- | ------- | ||||||
|   | |||||||
| @@ -18,5 +18,5 @@ pipelines: | |||||||
|           - mysql -u piler -ppiler123 piler1 < /usr/share/piler/db-mysql.sql |           - mysql -u piler -ppiler123 piler1 < /usr/share/piler/db-mysql.sql | ||||||
|           - cd unit_tests |           - cd unit_tests | ||||||
|           - ./run.sh |           - ./run.sh | ||||||
|           - cd .. |           - cd ../webui | ||||||
|           - phpunit |           - phpunit | ||||||
|   | |||||||
| @@ -88,6 +88,7 @@ $config['LDAP_MAIL_ATTR'] = 'mail'; | |||||||
| $config['LDAP_AUDITOR_MEMBER_DN'] = ''; | $config['LDAP_AUDITOR_MEMBER_DN'] = ''; | ||||||
| $config['LDAP_ADMIN_MEMBER_DN'] = ''; | $config['LDAP_ADMIN_MEMBER_DN'] = ''; | ||||||
| $config['LDAP_BASE_DN'] = ''; | $config['LDAP_BASE_DN'] = ''; | ||||||
|  | $config['LDAP_USE_START_TLS'] = 0; | ||||||
|  |  | ||||||
| // AD specific settings | // AD specific settings | ||||||
| // | // | ||||||
| @@ -324,10 +325,12 @@ $langs = array( | |||||||
|                 'es', |                 'es', | ||||||
|                 'fr', |                 'fr', | ||||||
|                 'hu', |                 'hu', | ||||||
|  |                 'it', | ||||||
|                 'pl', |                 'pl', | ||||||
|                 'pt', |                 'pt', | ||||||
|                 'ru', |                 'ru', | ||||||
|                 'tr' |                 'tr', | ||||||
|  |                 'tw' | ||||||
|                ); |                ); | ||||||
|  |  | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										176
									
								
								contrib/installer/focal.sh
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										176
									
								
								contrib/installer/focal.sh
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,176 @@ | |||||||
|  | #!/bin/bash | ||||||
|  |  | ||||||
|  | set -o errexit | ||||||
|  | set -o pipefail | ||||||
|  | set -o nounset | ||||||
|  | set -x | ||||||
|  |  | ||||||
|  | PILER_HOSTNAME="${PILER_HOSTNAME:-archive.yourdomain.com}" | ||||||
|  | MYSQL_ROOT_PASSWORD="${MYSQL_ROOT_PASSWORD:-abcde123}" | ||||||
|  | MYSQL_PILER_PASSWORD="${MYSQL_PILER_PASSWORD:-piler123}" | ||||||
|  | SERVER_ID="${SERVER_ID:-0}" | ||||||
|  | USE_SMTP_GATEWAY="${USE_SMTP_GATEWAY:-0}" | ||||||
|  | SPHINX_WORKER_LISTEN_ADDRESS="${SPHINX_WORKER_LISTEN_ADDRESS:-}" | ||||||
|  | PHP_FPM_SOCKET="/var/run/php/php7.4-fpm.sock" | ||||||
|  |  | ||||||
|  | MYSQL_HOSTNAME="localhost" | ||||||
|  | MYSQL_DATABASE="piler" | ||||||
|  | MYSQL_USERNAME="piler" | ||||||
|  |  | ||||||
|  | SPHINX_TARGZ="sphinx-3.3.1-bin.tar.gz" | ||||||
|  | DOWNLOAD_URL="https://download.mailpiler.com" | ||||||
|  | PILER_DEB="piler_1.3.12-focal-a1b71bdd_amd64.deb" | ||||||
|  | PILER_USER="piler" | ||||||
|  | CONFIG_SITE_PHP="/etc/piler/config-site.php" | ||||||
|  |  | ||||||
|  | export DEBIAN_FRONTEND=noninteractive | ||||||
|  |  | ||||||
|  | install_prerequisites() { | ||||||
|  |    apt-get update | ||||||
|  |    apt-get -y --no-install-recommends install \ | ||||||
|  |       wget rsyslog openssl sysstat php7.4-cli php7.4-cgi php7.4-mysql php7.4-fpm php7.4-zip php7.4-ldap \ | ||||||
|  |       php7.4-gd php7.4-curl php7.4-xml ca-certificates zip catdoc unrtf poppler-utils nginx tnef libzip5 \ | ||||||
|  |       libtre5 libwrap0 cron libmariadb-dev python3 python3-mysqldb libmariadb-dev mariadb-client-core-10.3 \ | ||||||
|  |       mariadb-server-10.3 | ||||||
|  |  | ||||||
|  |    wget -q -O "/tmp/${SPHINX_TARGZ}" "${DOWNLOAD_URL}/generic-local/${SPHINX_TARGZ}" | ||||||
|  |    tar -C / -zxvf "/tmp/${SPHINX_TARGZ}" | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | fix_mysql_settings() { | ||||||
|  |    cat > /etc/mysql/mariadb.conf.d/99-piler.cnf << PILER_CNF | ||||||
|  | [mysqld] | ||||||
|  |  | ||||||
|  | innodb_buffer_pool_size=512M | ||||||
|  | innodb_flush_log_at_trx_commit=1 | ||||||
|  | innodb_log_buffer_size=64M | ||||||
|  | innodb_log_file_size=64M | ||||||
|  | innodb_read_io_threads=4 | ||||||
|  | innodb_write_io_threads=4 | ||||||
|  | innodb_log_files_in_group=2 | ||||||
|  |  | ||||||
|  | innodb_file_per_table | ||||||
|  | PILER_CNF | ||||||
|  | } | ||||||
|  |  | ||||||
|  | start_mysql() { | ||||||
|  |    fix_mysql_settings | ||||||
|  |  | ||||||
|  |    service mysql restart | ||||||
|  |    mysqladmin -u root password "${MYSQL_ROOT_PASSWORD}" | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | install_piler() { | ||||||
|  |    wget "${DOWNLOAD_URL}/piler/${PILER_DEB}" | ||||||
|  |    dpkg -i "$PILER_DEB" | ||||||
|  |    rm -f "$PILER_DEB" | ||||||
|  |  | ||||||
|  |    crontab -u "$PILER_USER" /usr/share/piler/piler.cron | ||||||
|  |  | ||||||
|  |    rm -f "$PILER_DEB" /etc/nginx/sites-enabled/default | ||||||
|  |    ln -sf /etc/piler/piler-nginx.conf /etc/nginx/sites-enabled/piler.conf | ||||||
|  |  | ||||||
|  |    touch /var/piler/.bash_history | ||||||
|  |    chown "${PILER_USER}:${PILER_USER}" /var/piler/.bash_history | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | create_my_cnf() { | ||||||
|  |    local user=$1 | ||||||
|  |    local password=$2 | ||||||
|  |    local my_cnf=$3 | ||||||
|  |  | ||||||
|  |    printf "[client]\\n\\nhost = %s\\nuser = %s\\npassword = %s\\n" "$MYSQL_HOSTNAME" "$user" "$password" > "$my_cnf" | ||||||
|  |    printf "\\n\\n[mysqldump]\\n\\nhost = %s\\nuser = %s\\npassword = %s\\n" "$MYSQL_HOSTNAME" "$user" "$password" >> "$my_cnf" | ||||||
|  |    chown $PILER_USER:$PILER_USER "$my_cnf" | ||||||
|  |    chmod 600 "$my_cnf" | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | fix_config_site_php() { | ||||||
|  |    sed -i -e "s%HOSTNAME%${PILER_HOSTNAME}%g" -e "s%MYSQL_PASSWORD%${MYSQL_PILER_PASSWORD}%g" "$CONFIG_SITE_PHP" | ||||||
|  |  | ||||||
|  |    { | ||||||
|  |       echo "\$config['SERVER_ID'] = $SERVER_ID;" | ||||||
|  |       echo "\$config['USE_SMTP_GATEWAY'] = $USE_SMTP_GATEWAY;" | ||||||
|  |       echo "\$config['SPHINX_VERSION'] = 331;" | ||||||
|  |    } >> "$CONFIG_SITE_PHP" | ||||||
|  |  | ||||||
|  |    if [[ "$SPHINX_WORKER_LISTEN_ADDRESS" ]]; then | ||||||
|  |       echo "\$config['SPHINX_WORKER_LISTEN_ADDRESS'] = '$SPHINX_WORKER_LISTEN_ADDRESS';" >> "$CONFIG_SITE_PHP" | ||||||
|  |    fi | ||||||
|  |  | ||||||
|  |    echo "\$config['ARCHIVE_HOST'] = '$PILER_HOSTNAME';" >> "$CONFIG_SITE_PHP" | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | init_db() { | ||||||
|  |    sed -e "s%MYSQL_HOSTNAME%$MYSQL_HOSTNAME%g" -e "s%MYSQL_DATABASE%$MYSQL_DATABASE%g" -e "s%MYSQL_USERNAME%$MYSQL_USERNAME%g" -e "s%MYSQL_PASSWORD%$MYSQL_PILER_PASSWORD%g" \ | ||||||
|  |       /usr/share/piler/db-mysql-root.sql.in | mysql --defaults-file=/etc/piler/.my.cnf-root -h $MYSQL_HOSTNAME | ||||||
|  |    mysql --defaults-file=/etc/piler/.my.cnf -h $MYSQL_HOSTNAME $MYSQL_DATABASE < /usr/share/piler/db-mysql.sql | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | add_systemd_services() { | ||||||
|  |    pushd /etc/systemd/system | ||||||
|  |  | ||||||
|  |    ln -sf /usr/libexec/piler/piler.service . | ||||||
|  |    ln -sf /usr/libexec/piler/piler-smtp.service . | ||||||
|  |    ln -sf /usr/libexec/piler/pilersearch.service . | ||||||
|  |  | ||||||
|  |    popd | ||||||
|  |  | ||||||
|  |    systemctl daemon-reload | ||||||
|  |  | ||||||
|  |    systemctl enable piler | ||||||
|  |    systemctl enable piler-smtp | ||||||
|  |    systemctl enable pilersearch | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | fix_configs() { | ||||||
|  |    if [[ ! -f /etc/piler/piler-nginx.conf ]]; then | ||||||
|  |       sed -e "s%PILER_HOST%$PILER_HOSTNAME%g" -e "s%PHP_FPM_SOCKET%$PHP_FPM_SOCKET%g" /etc/piler/piler-nginx.conf.dist > /etc/piler/piler-nginx.conf | ||||||
|  |       nginx -t | ||||||
|  |       nginx -s reload | ||||||
|  |    fi | ||||||
|  |  | ||||||
|  |    if [[ ! -f /etc/piler/piler.conf ]]; then | ||||||
|  |       sed -e "s/verystrongpassword/$MYSQL_PILER_PASSWORD/g" -e "s/piler.yourdomain.com/$PILER_HOSTNAME/g" /etc/piler/piler.conf.dist > /etc/piler/piler.conf | ||||||
|  |       chmod 600 /etc/piler/piler.conf | ||||||
|  |       chown $PILER_USER:$PILER_USER /etc/piler/piler.conf | ||||||
|  |    fi | ||||||
|  |  | ||||||
|  |    sed -i -e "s/MYSQL_HOSTNAME/${MYSQL_HOSTNAME}/g" \ | ||||||
|  |           -e "s/MYSQL_DATABASE/${MYSQL_DATABASE}/g" \ | ||||||
|  |           -e "s/MYSQL_USERNAME/${MYSQL_USERNAME}/g" \ | ||||||
|  |           -e "s/MYSQL_PASSWORD/${MYSQL_PILER_PASSWORD}/g" \ | ||||||
|  |           /etc/piler/sphinx.conf | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | install_prerequisites | ||||||
|  |  | ||||||
|  | start_mysql | ||||||
|  |  | ||||||
|  | install_piler | ||||||
|  |  | ||||||
|  | create_my_cnf "root" "${MYSQL_ROOT_PASSWORD}" /etc/piler/.my.cnf-root | ||||||
|  | create_my_cnf "piler" "${MYSQL_PILER_PASSWORD}" /etc/piler/.my.cnf | ||||||
|  |  | ||||||
|  | fix_config_site_php | ||||||
|  |  | ||||||
|  | add_systemd_services | ||||||
|  |  | ||||||
|  | fix_configs | ||||||
|  | init_db | ||||||
|  |  | ||||||
|  | su -c "indexer --all -c /etc/piler/sphinx.conf" $PILER_USER | ||||||
|  |  | ||||||
|  | [[ ! -d /var/run/piler ]] || mkdir -p /var/run/piler | ||||||
|  |  | ||||||
|  | systemctl start pilersearch | ||||||
|  | systemctl start piler | ||||||
|  | systemctl start piler-smtp | ||||||
| @@ -6,9 +6,9 @@ | |||||||
| */15 * * * * /usr/bin/indexer --config SYSCONFDIR/piler/sphinx.conf --quiet note1 --rotate | */15 * * * * /usr/bin/indexer --config SYSCONFDIR/piler/sphinx.conf --quiet note1 --rotate | ||||||
| */5 * * * *  /usr/bin/find LOCALSTATEDIR/piler/www/tmp -type f -name i.\* -exec rm -f {} \; | */5 * * * *  /usr/bin/find LOCALSTATEDIR/piler/www/tmp -type f -name i.\* -exec rm -f {} \; | ||||||
| */5 * * * * /usr/bin/find LOCALSTATEDIR/piler/error -type f|wc -l > LOCALSTATEDIR/piler/stat/error | */5 * * * * /usr/bin/find LOCALSTATEDIR/piler/error -type f|wc -l > LOCALSTATEDIR/piler/stat/error | ||||||
| 2 0 * * * LIBEXECDIR/piler/pilerpurge.py |  | ||||||
|  |  | ||||||
| ### optional: populate accouting data | ### optional | ||||||
| ###30 6 * * * /usr/bin/php LIBEXECDIR/piler/generate_stats.php --webui LOCALSTATEDIR/piler/www >/dev/null | ###30 6 * * * /usr/bin/php LIBEXECDIR/piler/generate_stats.php --webui LOCALSTATEDIR/piler/www >/dev/null | ||||||
|  | ###*/5 * * * * LIBEXECDIR/piler/import.sh | ||||||
|  |  | ||||||
| ### PILEREND | ### PILEREND | ||||||
|   | |||||||
| @@ -277,7 +277,7 @@ int retrieve_email_from_archive(struct session_data *sdata, FILE *dest, struct c | |||||||
|       return 1; |       return 1; | ||||||
|    } |    } | ||||||
|  |  | ||||||
|    snprintf(filename, sizeof(filename)-1, "%s/%02x/%c%c%c/%c%c/%c%c/%s.m", cfg->queuedir, cfg->server_id, *(sdata->ttmpfile+8), *(sdata->ttmpfile+9), *(sdata->ttmpfile+10), *(sdata->ttmpfile+RND_STR_LEN-4), *(sdata->ttmpfile+RND_STR_LEN-3), *(sdata->ttmpfile+RND_STR_LEN-2), *(sdata->ttmpfile+RND_STR_LEN-1), sdata->ttmpfile); |    snprintf(filename, sizeof(filename)-1, "%s/%c%c/%c%c%c/%c%c/%c%c/%s.m", cfg->queuedir, *(sdata->ttmpfile+24), *(sdata->ttmpfile+25), *(sdata->ttmpfile+8), *(sdata->ttmpfile+9), *(sdata->ttmpfile+10), *(sdata->ttmpfile+RND_STR_LEN-4), *(sdata->ttmpfile+RND_STR_LEN-3), *(sdata->ttmpfile+RND_STR_LEN-2), *(sdata->ttmpfile+RND_STR_LEN-1), sdata->ttmpfile); | ||||||
| #ifdef HAVE_SUPPORT_FOR_COMPAT_STORAGE_LAYOUT | #ifdef HAVE_SUPPORT_FOR_COMPAT_STORAGE_LAYOUT | ||||||
|    if(stat(filename, &st)){ |    if(stat(filename, &st)){ | ||||||
|       snprintf(filename, sizeof(filename)-1, "%s/%02x/%c%c/%c%c/%c%c/%s.m", cfg->queuedir, cfg->server_id, *(sdata->ttmpfile+RND_STR_LEN-6), *(sdata->ttmpfile+RND_STR_LEN-5), *(sdata->ttmpfile+RND_STR_LEN-4), *(sdata->ttmpfile+RND_STR_LEN-3), *(sdata->ttmpfile+RND_STR_LEN-2), *(sdata->ttmpfile+RND_STR_LEN-1), sdata->ttmpfile); |       snprintf(filename, sizeof(filename)-1, "%s/%02x/%c%c/%c%c/%c%c/%s.m", cfg->queuedir, cfg->server_id, *(sdata->ttmpfile+RND_STR_LEN-6), *(sdata->ttmpfile+RND_STR_LEN-5), *(sdata->ttmpfile+RND_STR_LEN-4), *(sdata->ttmpfile+RND_STR_LEN-3), *(sdata->ttmpfile+RND_STR_LEN-2), *(sdata->ttmpfile+RND_STR_LEN-1), sdata->ttmpfile); | ||||||
| @@ -304,7 +304,7 @@ int retrieve_email_from_archive(struct session_data *sdata, FILE *dest, struct c | |||||||
|                buffer = p + strlen(pointer); |                buffer = p + strlen(pointer); | ||||||
|  |  | ||||||
|                if(strlen(ptr_arr[i].piler_id) == RND_STR_LEN){ |                if(strlen(ptr_arr[i].piler_id) == RND_STR_LEN){ | ||||||
|                   snprintf(filename, sizeof(filename)-1, "%s/%02x/%c%c%c/%c%c/%c%c/%s.a%d", cfg->queuedir, cfg->server_id, ptr_arr[i].piler_id[8], ptr_arr[i].piler_id[9], ptr_arr[i].piler_id[10], ptr_arr[i].piler_id[RND_STR_LEN-4], ptr_arr[i].piler_id[RND_STR_LEN-3], ptr_arr[i].piler_id[RND_STR_LEN-2], ptr_arr[i].piler_id[RND_STR_LEN-1], ptr_arr[i].piler_id, ptr_arr[i].attachment_id); |                   snprintf(filename, sizeof(filename)-1, "%s/%c%c/%c%c%c/%c%c/%c%c/%s.a%d", cfg->queuedir, ptr_arr[i].piler_id[24], ptr_arr[i].piler_id[25], ptr_arr[i].piler_id[8], ptr_arr[i].piler_id[9], ptr_arr[i].piler_id[10], ptr_arr[i].piler_id[RND_STR_LEN-4], ptr_arr[i].piler_id[RND_STR_LEN-3], ptr_arr[i].piler_id[RND_STR_LEN-2], ptr_arr[i].piler_id[RND_STR_LEN-1], ptr_arr[i].piler_id, ptr_arr[i].attachment_id); | ||||||
|  |  | ||||||
|                #ifdef HAVE_SUPPORT_FOR_COMPAT_STORAGE_LAYOUT |                #ifdef HAVE_SUPPORT_FOR_COMPAT_STORAGE_LAYOUT | ||||||
|                   if(stat(filename, &st)){ |                   if(stat(filename, &st)){ | ||||||
|   | |||||||
| @@ -152,7 +152,9 @@ int get_tls_protocol_number(char *protocol){ | |||||||
|       { "TLSv1", TLS1_VERSION }, |       { "TLSv1", TLS1_VERSION }, | ||||||
|       { "TLSv1.1", TLS1_1_VERSION }, |       { "TLSv1.1", TLS1_1_VERSION }, | ||||||
|       { "TLSv1.2", TLS1_2_VERSION }, |       { "TLSv1.2", TLS1_2_VERSION }, | ||||||
|  |    #ifdef TLS1_3_VERSION | ||||||
|       { "TLSv1.3", TLS1_3_VERSION }, |       { "TLSv1.3", TLS1_3_VERSION }, | ||||||
|  |    #endif | ||||||
|    }; |    }; | ||||||
|  |  | ||||||
|    for(unsigned int i=0; i<sizeof(tls_protocols)/sizeof(struct tls_protocol); i++){ |    for(unsigned int i=0; i<sizeof(tls_protocols)/sizeof(struct tls_protocol); i++){ | ||||||
|   | |||||||
							
								
								
									
										17
									
								
								src/config.h
									
									
									
									
									
								
							
							
						
						
									
										17
									
								
								src/config.h
									
									
									
									
									
								
							| @@ -39,6 +39,20 @@ | |||||||
| #define IPLEN 16+1 | #define IPLEN 16+1 | ||||||
| #define KEYLEN 56 | #define KEYLEN 56 | ||||||
| #define MIN_EMAIL_ADDRESS_LEN 9 | #define MIN_EMAIL_ADDRESS_LEN 9 | ||||||
|  | // Sphinx 3.x has an issue with tokens longer than 41 characters. | ||||||
|  | // | ||||||
|  | // When a regular user executes a query, then his default email address filter | ||||||
|  | // causes the query to fail with the below error message, even when the query | ||||||
|  | // itself is correct: | ||||||
|  | // | ||||||
|  | // SELECT id FROM main1,dailydelta1,delta1 WHERE MATCH(' ( (@sender thisisanextremelylongemailaddressyesareallylongoneyeahitolyouXaddressXcom ) | (@rcpt thisisanextremelylongemailaddressyesareallylongoneyeahitolyouXaddressXcom) ) ') ORDER BY `sent` DESC LIMIT 0,20 OPTION max_matches=1000' | ||||||
|  | // | ||||||
|  | // ERROR 1064 (42000): index dailydelta1,delta1,main1: syntax error, unexpected $end near ' ' | ||||||
|  | // | ||||||
|  | // Note that we use 42, because the parser adds a trailing space to the tokens | ||||||
|  | // See https://www.mailpiler.org/wiki/current:sphinx3 and | ||||||
|  | // https://bitbucket.org/jsuto/piler/issues/1082/no-sphinx-results-with-long-email for more | ||||||
|  | #define MAX_EMAIL_ADDRESS_SPHINX_LEN 42 | ||||||
|  |  | ||||||
| #define CRLF "\n" | #define CRLF "\n" | ||||||
|  |  | ||||||
| @@ -108,9 +122,10 @@ | |||||||
| #define SQL_PREPARED_STMT_GET_FOLDER_ID              "SELECT `id` FROM " SQL_FOLDER_TABLE " WHERE `name`=? AND `parent_id`=?" | #define SQL_PREPARED_STMT_GET_FOLDER_ID              "SELECT `id` FROM " SQL_FOLDER_TABLE " WHERE `name`=? AND `parent_id`=?" | ||||||
| #define SQL_PREPARED_STMT_INSERT_INTO_FOLDER_TABLE   "INSERT INTO `" SQL_FOLDER_TABLE "` (`name`, `parent_id`) VALUES(?,?)" | #define SQL_PREPARED_STMT_INSERT_INTO_FOLDER_TABLE   "INSERT INTO `" SQL_FOLDER_TABLE "` (`name`, `parent_id`) VALUES(?,?)" | ||||||
| #define SQL_PREPARED_STMT_UPDATE_METADATA_REFERENCE  "UPDATE " SQL_METADATA_TABLE " SET reference=? WHERE message_id=? AND reference=''" | #define SQL_PREPARED_STMT_UPDATE_METADATA_REFERENCE  "UPDATE " SQL_METADATA_TABLE " SET reference=? WHERE message_id=? AND reference=''" | ||||||
|  | #define SQL_PREPARED_STMT_GET_METADATA_REFERENCE     "SELECT COUNT(*) AS count FROM " SQL_METADATA_TABLE " WHERE reference=?" | ||||||
| #define SQL_PREPARED_STMT_GET_GUI_IMPORT_JOBS        "SELECT id, type, username, password, server FROM " SQL_IMPORT_TABLE " WHERE started=0 ORDER BY id LIMIT 0,1" | #define SQL_PREPARED_STMT_GET_GUI_IMPORT_JOBS        "SELECT id, type, username, password, server FROM " SQL_IMPORT_TABLE " WHERE started=0 ORDER BY id LIMIT 0,1" | ||||||
| #define SQL_PREPARED_STMT_INSERT_FOLDER_MESSAGE      "INSERT INTO " SQL_FOLDER_MESSAGE_TABLE " (`folder_id`, `id`) VALUES(?,?)" | #define SQL_PREPARED_STMT_INSERT_FOLDER_MESSAGE      "INSERT INTO " SQL_FOLDER_MESSAGE_TABLE " (`folder_id`, `id`) VALUES(?,?)" | ||||||
| #define SQL_PREPARED_STMT_UPDATE_IMPORT_TABLE        "UPDATE " SQL_IMPORT_TABLE " SET status=?, imported=? WHERE id=?" | #define SQL_PREPARED_STMT_UPDATE_IMPORT_TABLE        "UPDATE " SQL_IMPORT_TABLE " SET started=?, status=?, imported=? WHERE id=?" | ||||||
|  |  | ||||||
| /* Error codes */ | /* Error codes */ | ||||||
|  |  | ||||||
|   | |||||||
| @@ -14,6 +14,7 @@ | |||||||
|    #include <tre/regex.h> |    #include <tre/regex.h> | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|  | #include <openssl/md5.h> | ||||||
| #include <openssl/sha.h> | #include <openssl/sha.h> | ||||||
| #include <openssl/ssl.h> | #include <openssl/ssl.h> | ||||||
| #include <netinet/in.h> | #include <netinet/in.h> | ||||||
| @@ -171,6 +172,7 @@ struct parser_state { | |||||||
|    int qp; |    int qp; | ||||||
|    int htmltag; |    int htmltag; | ||||||
|    int style; |    int style; | ||||||
|  |    int meta_content_type; | ||||||
|    int skip_html; |    int skip_html; | ||||||
|    int has_to_dump; |    int has_to_dump; | ||||||
|    int has_to_dump_whole_body; |    int has_to_dump_whole_body; | ||||||
| @@ -184,11 +186,13 @@ struct parser_state { | |||||||
|    int saved_size; |    int saved_size; | ||||||
|    unsigned int writebufpos; |    unsigned int writebufpos; | ||||||
|    unsigned int abufpos; |    unsigned int abufpos; | ||||||
|  |    unsigned int received_header; | ||||||
|    char attachedfile[RND_STR_LEN+SMALLBUFSIZE]; |    char attachedfile[RND_STR_LEN+SMALLBUFSIZE]; | ||||||
|    char message_id[SMALLBUFSIZE]; |    char message_id[SMALLBUFSIZE]; | ||||||
|    char message_id_hash[2*DIGEST_LENGTH+1]; |    char message_id_hash[2*DIGEST_LENGTH+1]; | ||||||
|    char miscbuf[MAX_TOKEN_LEN]; |    char miscbuf[MAX_TOKEN_LEN]; | ||||||
|    char qpbuf[MAX_TOKEN_LEN]; |    char qpbuf[MAX_TOKEN_LEN]; | ||||||
|  |    char receivedbuf[SMALLBUFSIZE]; | ||||||
|    unsigned long n_token; |    unsigned long n_token; | ||||||
|    unsigned long n_subject_token; |    unsigned long n_subject_token; | ||||||
|    unsigned long n_body_token; |    unsigned long n_body_token; | ||||||
| @@ -218,7 +222,7 @@ struct parser_state { | |||||||
|    unsigned int todomainlen; |    unsigned int todomainlen; | ||||||
|    unsigned int found_security_header; |    unsigned int found_security_header; | ||||||
|  |  | ||||||
|    int journaltolen; |    long unsigned int journaltolen; | ||||||
|  |  | ||||||
|    int retention; |    int retention; | ||||||
| }; | }; | ||||||
| @@ -315,6 +319,7 @@ struct import { | |||||||
|    int port; |    int port; | ||||||
|    int seq; |    int seq; | ||||||
|    int table_id; |    int table_id; | ||||||
|  |    int delay; | ||||||
|    char *server; |    char *server; | ||||||
|    char *username; |    char *username; | ||||||
|    char *password; |    char *password; | ||||||
| @@ -399,6 +404,7 @@ struct smtp_session { | |||||||
|    char rcptto[MAX_RCPT_TO][SMALLBUFSIZE]; |    char rcptto[MAX_RCPT_TO][SMALLBUFSIZE]; | ||||||
|    char buf[MAXBUFSIZE]; |    char buf[MAXBUFSIZE]; | ||||||
|    char remote_host[INET6_ADDRSTRLEN+1]; |    char remote_host[INET6_ADDRSTRLEN+1]; | ||||||
|  |    char nullbyte; | ||||||
|    time_t lasttime; |    time_t lasttime; | ||||||
|    int protocol_state; |    int protocol_state; | ||||||
|    int slot; |    int slot; | ||||||
|   | |||||||
							
								
								
									
										24
									
								
								src/digest.c
									
									
									
									
									
								
							
							
						
						
									
										24
									
								
								src/digest.c
									
									
									
									
									
								
							| @@ -132,3 +132,27 @@ void digest_string(char *s, char *digest){ | |||||||
|       snprintf(digest + i*2, 2*DIGEST_LENGTH, "%02x", md[i]); |       snprintf(digest + i*2, 2*DIGEST_LENGTH, "%02x", md[i]); | ||||||
|  |  | ||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | void md5_string(char *s, char *digest){ | ||||||
|  |    int i; | ||||||
|  |    unsigned char md[MD5_DIGEST_LENGTH]; | ||||||
|  |    MD5_CTX context; | ||||||
|  |  | ||||||
|  |    memset(digest, 0, 2*MD5_DIGEST_LENGTH+2); | ||||||
|  |  | ||||||
|  |    MD5_Init(&context); | ||||||
|  |  | ||||||
|  |    MD5_Update(&context, s, strlen(s)); | ||||||
|  |  | ||||||
|  |    MD5_Final(md, &context); | ||||||
|  |  | ||||||
|  |    for(i=0;i<MD5_DIGEST_LENGTH;i++) | ||||||
|  |       snprintf(digest + i*2, 2*MD5_DIGEST_LENGTH, "%02x", md[i]); | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | void create_md5_from_email_address(char *puf, char *md5buf){ | ||||||
|  |    md5_string(puf, md5buf); | ||||||
|  |    md5buf[2*MD5_DIGEST_LENGTH] = ' '; | ||||||
|  | } | ||||||
|   | |||||||
							
								
								
									
										10
									
								
								src/imap.c
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								src/imap.c
									
									
									
									
									
								
							| @@ -159,7 +159,7 @@ int imap_select_cmd_on_folder(char *folder, struct data *data){ | |||||||
|       } |       } | ||||||
|    } |    } | ||||||
|  |  | ||||||
|    printf("found %d messages\n", messages); |    if(data->quiet == 0){printf("found %d messages\n", messages); } | ||||||
|  |  | ||||||
|    data->import->total_messages += messages; |    data->import->total_messages += messages; | ||||||
|  |  | ||||||
| @@ -356,7 +356,7 @@ int process_imap_folder(char *folder, struct session_data *sdata, struct data *d | |||||||
|    } |    } | ||||||
|  |  | ||||||
|  |  | ||||||
|    printf("\n"); |    if(data->quiet == 0){printf("\n"); } | ||||||
|  |  | ||||||
|    return OK; |    return OK; | ||||||
| } | } | ||||||
| @@ -375,7 +375,7 @@ int list_folders(struct data *data){ | |||||||
|    char attrs[SMALLBUFSIZE], folder[SMALLBUFSIZE]; |    char attrs[SMALLBUFSIZE], folder[SMALLBUFSIZE]; | ||||||
|    int len=MAXBUFSIZE+3, pos=0, n, rc=ERR, fldrlen=0, result; |    int len=MAXBUFSIZE+3, pos=0, n, rc=ERR, fldrlen=0, result; | ||||||
|  |  | ||||||
|    printf("List of IMAP folders:\n"); |    if(data->quiet == 0){printf("List of IMAP folders:\n"); } | ||||||
|  |  | ||||||
|    buf = malloc(len); |    buf = malloc(len); | ||||||
|    if(!buf) return rc; |    if(!buf) return rc; | ||||||
| @@ -478,9 +478,9 @@ int list_folders(struct data *data){ | |||||||
|                if(!strstr(attrs, "\\Noselect")){ |                if(!strstr(attrs, "\\Noselect")){ | ||||||
|                   addnode(data->imapfolders, folder); |                   addnode(data->imapfolders, folder); | ||||||
|                } |                } | ||||||
|                else printf("skipping "); |                else if(data->quiet == 0){printf("skipping "); } | ||||||
|  |  | ||||||
|                printf("=> '%s [%s]'\n", folder, attrs); |                if(data->quiet == 0){printf("=> '%s [%s]'\n", folder, attrs); } | ||||||
|  |  | ||||||
|                memset(attrs, 0, sizeof(attrs)); |                memset(attrs, 0, sizeof(attrs)); | ||||||
|             } |             } | ||||||
|   | |||||||
							
								
								
									
										14
									
								
								src/import.c
									
									
									
									
									
								
							
							
						
						
									
										14
									
								
								src/import.c
									
									
									
									
									
								
							| @@ -25,6 +25,14 @@ int import_message(struct session_data *sdata, struct data *data, struct config | |||||||
|    struct parser_state state; |    struct parser_state state; | ||||||
|    struct counters counters; |    struct counters counters; | ||||||
|  |  | ||||||
|  |    if(data->import->delay > 0){ | ||||||
|  |       struct timespec req; | ||||||
|  |  | ||||||
|  |       req.tv_sec = 0; | ||||||
|  |       req.tv_nsec = 1000000 * data->import->delay; | ||||||
|  |  | ||||||
|  |       nanosleep(&req, NULL); | ||||||
|  |    } | ||||||
|  |  | ||||||
|    init_session_data(sdata, cfg); |    init_session_data(sdata, cfg); | ||||||
|  |  | ||||||
| @@ -89,7 +97,10 @@ int import_message(struct session_data *sdata, struct data *data, struct config | |||||||
|          // When importing emails, we should add the retention value (later) to the original sent value |          // When importing emails, we should add the retention value (later) to the original sent value | ||||||
|          sdata->retained = sdata->sent; |          sdata->retained = sdata->sent; | ||||||
|  |  | ||||||
|  |          // backup original value of data->folder | ||||||
|  |          int folder = data->folder; | ||||||
|          rc = process_message(sdata, &state, data, cfg); |          rc = process_message(sdata, &state, data, cfg); | ||||||
|  |          data->folder = folder; | ||||||
|          unlink(state.message_id_hash); |          unlink(state.message_id_hash); | ||||||
|       } |       } | ||||||
|    } |    } | ||||||
| @@ -145,13 +156,14 @@ int import_message(struct session_data *sdata, struct data *data, struct config | |||||||
|  |  | ||||||
|  |  | ||||||
| int update_import_table(struct session_data *sdata, struct data *data) { | int update_import_table(struct session_data *sdata, struct data *data) { | ||||||
|    int ret=ERR, status=2; |    int ret=ERR, status=2, started=1; | ||||||
|    struct sql sql; |    struct sql sql; | ||||||
|  |  | ||||||
|    if(prepare_sql_statement(sdata, &sql, SQL_PREPARED_STMT_UPDATE_IMPORT_TABLE) == ERR) return ret; |    if(prepare_sql_statement(sdata, &sql, SQL_PREPARED_STMT_UPDATE_IMPORT_TABLE) == ERR) return ret; | ||||||
|  |  | ||||||
|    p_bind_init(&sql); |    p_bind_init(&sql); | ||||||
|  |  | ||||||
|  |    sql.sql[sql.pos] = (char *)&(started); sql.type[sql.pos] = TYPE_LONG; sql.pos++; | ||||||
|    sql.sql[sql.pos] = (char *)&(status); sql.type[sql.pos] = TYPE_LONG; sql.pos++; |    sql.sql[sql.pos] = (char *)&(status); sql.type[sql.pos] = TYPE_LONG; sql.pos++; | ||||||
|    sql.sql[sql.pos] = (char *)&(data->import->tot_msgs); sql.type[sql.pos] = TYPE_LONG; sql.pos++; |    sql.sql[sql.pos] = (char *)&(data->import->tot_msgs); sql.type[sql.pos] = TYPE_LONG; sql.pos++; | ||||||
|    sql.sql[sql.pos] = (char *)&(data->import->table_id); sql.type[sql.pos] = TYPE_LONG; sql.pos++; |    sql.sql[sql.pos] = (char *)&(data->import->table_id); sql.type[sql.pos] = TYPE_LONG; sql.pos++; | ||||||
|   | |||||||
| @@ -58,7 +58,7 @@ void process_buffer(char *buf, int buflen, uint64 *count, struct session_data *s | |||||||
|  |  | ||||||
|  |  | ||||||
| void import_from_pilerexport(struct session_data *sdata, struct data *data, struct config *cfg){ | void import_from_pilerexport(struct session_data *sdata, struct data *data, struct config *cfg){ | ||||||
|    int n, rc, savedlen=0, puflen; |    int n, rc, nullbyte, savedlen=0, puflen; | ||||||
|    uint64 count=0; |    uint64 count=0; | ||||||
|    char *p, copybuf[2*BIGBUFSIZE+1], buf[BIGBUFSIZE], savedbuf[BIGBUFSIZE], puf[BIGBUFSIZE]; |    char *p, copybuf[2*BIGBUFSIZE+1], buf[BIGBUFSIZE], savedbuf[BIGBUFSIZE], puf[BIGBUFSIZE]; | ||||||
|  |  | ||||||
| @@ -70,12 +70,16 @@ void import_from_pilerexport(struct session_data *sdata, struct data *data, stru | |||||||
|       memset(buf, 0, sizeof(buf)); |       memset(buf, 0, sizeof(buf)); | ||||||
|       n = fread(buf, 1, sizeof(buf)-1, stdin); |       n = fread(buf, 1, sizeof(buf)-1, stdin); | ||||||
|  |  | ||||||
|  |       int remaininglen = n; | ||||||
|  |  | ||||||
|       if(savedlen > 0){ |       if(savedlen > 0){ | ||||||
|          memset(copybuf, 0, sizeof(copybuf)); |          memset(copybuf, 0, sizeof(copybuf)); | ||||||
|  |  | ||||||
|          memcpy(copybuf, savedbuf, savedlen); |          memcpy(copybuf, savedbuf, savedlen); | ||||||
|          memcpy(©buf[savedlen], buf, n); |          memcpy(©buf[savedlen], buf, n); | ||||||
|  |  | ||||||
|  |          remaininglen += savedlen; | ||||||
|  |  | ||||||
|          savedlen = 0; |          savedlen = 0; | ||||||
|          memset(savedbuf, 0, sizeof(savedbuf)); |          memset(savedbuf, 0, sizeof(savedbuf)); | ||||||
|  |  | ||||||
| @@ -86,8 +90,9 @@ void import_from_pilerexport(struct session_data *sdata, struct data *data, stru | |||||||
|       } |       } | ||||||
|  |  | ||||||
|       do { |       do { | ||||||
|          puflen = read_one_line(p, '\n', puf, sizeof(puf), &rc); |          puflen = read_one_line(p, remaininglen, '\n', puf, sizeof(puf), &rc, &nullbyte); | ||||||
|          p += puflen; |          p += puflen; | ||||||
|  |          remaininglen -= puflen; | ||||||
|  |  | ||||||
|          if(puflen > 0){ |          if(puflen > 0){ | ||||||
|             if(rc == OK){ |             if(rc == OK){ | ||||||
|   | |||||||
| @@ -213,6 +213,33 @@ int store_meta_data(struct session_data *sdata, struct parser_state *state, stru | |||||||
|       digest_string(state->reference, &ref[0]); |       digest_string(state->reference, &ref[0]); | ||||||
|       update_metadata_reference(sdata, state, &ref[0], cfg); |       update_metadata_reference(sdata, state, &ref[0], cfg); | ||||||
|    } |    } | ||||||
|  |    else if(state->reference[0] == 0){ | ||||||
|  |       // during import, the order of messages is often random | ||||||
|  |       // check if this is a message which is already referenced | ||||||
|  |       uint64 count=0; | ||||||
|  |  | ||||||
|  |       digest_string(state->message_id, &ref[0]); | ||||||
|  |       if(prepare_sql_statement(sdata, &sql, SQL_PREPARED_STMT_GET_METADATA_REFERENCE) != ERR){ | ||||||
|  |          p_bind_init(&sql); | ||||||
|  |  | ||||||
|  |          sql.sql[sql.pos] = &ref[0]; sql.type[sql.pos] = TYPE_STRING; sql.pos++; | ||||||
|  |  | ||||||
|  |          if(p_exec_stmt(sdata, &sql) == OK){ | ||||||
|  | 	    p_bind_init(&sql); | ||||||
|  |  | ||||||
|  | 	    sql.sql[sql.pos] = (char *)&count; sql.type[sql.pos] = TYPE_LONGLONG; sql.len[sql.pos] = sizeof(uint64); sql.pos++; | ||||||
|  | 	    p_store_results(&sql); | ||||||
|  | 	    p_fetch_results(&sql); | ||||||
|  | 	    p_free_results(&sql); | ||||||
|  | 	 } | ||||||
|  |       } | ||||||
|  |  | ||||||
|  |       close_prepared_statement(&sql); | ||||||
|  |  | ||||||
|  |       // no reference yet | ||||||
|  |       if(count <= 0) | ||||||
|  |          ref[0] = 0; | ||||||
|  |    } | ||||||
|  |  | ||||||
|  |  | ||||||
|    if(prepare_sql_statement(sdata, &sql, SQL_PREPARED_STMT_INSERT_INTO_META_TABLE) == ERR) return ERR; |    if(prepare_sql_statement(sdata, &sql, SQL_PREPARED_STMT_INSERT_INTO_META_TABLE) == ERR) return ERR; | ||||||
| @@ -308,7 +335,7 @@ void remove_stripped_attachments(struct parser_state *state){ | |||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
| int process_message(struct session_data *sdata, struct parser_state *state, struct data *data, struct config *cfg){ | int is_duplicated_message(struct session_data *sdata, struct parser_state *state, struct data *data, struct config *cfg){ | ||||||
|    int fd; |    int fd; | ||||||
|    char piler_id[SMALLBUFSIZE]; |    char piler_id[SMALLBUFSIZE]; | ||||||
|  |  | ||||||
| @@ -319,7 +346,7 @@ int process_message(struct session_data *sdata, struct parser_state *state, stru | |||||||
|    if(sdata->duplicate_id > 0){ |    if(sdata->duplicate_id > 0){ | ||||||
|       remove_stripped_attachments(state); |       remove_stripped_attachments(state); | ||||||
|  |  | ||||||
|       if(strlen(state->b_journal_to) > 0){ |       if(sdata->restored_copy == 0 && strlen(state->b_journal_to) > 0){ | ||||||
|          if(cfg->verbosity >= _LOG_DEBUG) syslog(LOG_PRIORITY, "%s: trying to add journal rcpt (%s) to id=%llu for message-id: '%s'", sdata->ttmpfile, state->b_journal_to, sdata->duplicate_id, state->message_id); |          if(cfg->verbosity >= _LOG_DEBUG) syslog(LOG_PRIORITY, "%s: trying to add journal rcpt (%s) to id=%llu for message-id: '%s'", sdata->ttmpfile, state->b_journal_to, sdata->duplicate_id, state->message_id); | ||||||
|          store_recipients(sdata, state->b_journal_to, sdata->duplicate_id, cfg); |          store_recipients(sdata, state->b_journal_to, sdata->duplicate_id, cfg); | ||||||
|       } |       } | ||||||
| @@ -338,7 +365,6 @@ int process_message(struct session_data *sdata, struct parser_state *state, stru | |||||||
|    if(cfg->verbosity >= _LOG_DEBUG) syslog(LOG_PRIORITY, "%s: touch %s OK (%s)", sdata->ttmpfile, state->message_id_hash, state->message_id); |    if(cfg->verbosity >= _LOG_DEBUG) syslog(LOG_PRIORITY, "%s: touch %s OK (%s)", sdata->ttmpfile, state->message_id_hash, state->message_id); | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|    if(cfg->mmap_dedup_test == 1 && data->dedup != MAP_FAILED && data->child_serial >= 0 && data->child_serial < MAXCHILDREN){ |    if(cfg->mmap_dedup_test == 1 && data->dedup != MAP_FAILED && data->child_serial >= 0 && data->child_serial < MAXCHILDREN){ | ||||||
|  |  | ||||||
|       if(strstr(data->dedup, state->message_id_hash)){ |       if(strstr(data->dedup, state->message_id_hash)){ | ||||||
| @@ -354,6 +380,14 @@ int process_message(struct session_data *sdata, struct parser_state *state, stru | |||||||
|       memcpy(data->dedup + data->child_serial*DIGEST_LENGTH*2, state->message_id_hash, DIGEST_LENGTH*2); |       memcpy(data->dedup + data->child_serial*DIGEST_LENGTH*2, state->message_id_hash, DIGEST_LENGTH*2); | ||||||
|    } |    } | ||||||
|  |  | ||||||
|  |    return OK; | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | int process_message(struct session_data *sdata, struct parser_state *state, struct data *data, struct config *cfg){ | ||||||
|  |  | ||||||
|  |    if(is_duplicated_message(sdata, state, data, cfg) == ERR_EXISTS) | ||||||
|  |       return ERR_EXISTS; | ||||||
|  |  | ||||||
|    sdata->retained += query_retain_period(data, state, sdata->tot_len, sdata->spam_message, cfg); |    sdata->retained += query_retain_period(data, state, sdata->tot_len, sdata->spam_message, cfg); | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										28
									
								
								src/misc.c
									
									
									
									
									
								
							
							
						
						
									
										28
									
								
								src/misc.c
									
									
									
									
									
								
							| @@ -652,34 +652,42 @@ void move_email(struct smtp_session *session){ | |||||||
|  |  | ||||||
|    snprintf(buf, sizeof(buf)-1, "%d/%s", session->ttmpfile[0] % session->cfg->number_of_worker_processes, session->ttmpfile); |    snprintf(buf, sizeof(buf)-1, "%d/%s", session->ttmpfile[0] % session->cfg->number_of_worker_processes, session->ttmpfile); | ||||||
|  |  | ||||||
|  |    if(session->nullbyte){ | ||||||
|  |       snprintf(buf, sizeof(buf)-1, "%s/%s", ERROR_DIR, session->ttmpfile); | ||||||
|  |       syslog(LOG_PRIORITY, "ERROR: %s contains an invalid NUL-byte, moving it to %s", session->ttmpfile, ERROR_DIR); | ||||||
|  |    } | ||||||
|  |  | ||||||
|    if(rename(session->ttmpfile, buf)){ |    if(rename(session->ttmpfile, buf)){ | ||||||
|       syslog(LOG_PRIORITY, "ERROR: couldn't rename %s to %s (reason: %s)", session->ttmpfile, buf, strerror(errno)); |       syslog(LOG_PRIORITY, "ERROR: couldn't rename %s to %s (reason: %s)", session->ttmpfile, buf, strerror(errno)); | ||||||
|    } |    } | ||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
| int read_one_line(char *s, int c, char *buf, int buflen, int *rc){ | int read_one_line(char *s, int slen, int c, char *buf, int buflen, int *rc, int *nullbyte){ | ||||||
|    int i=0; |    int i=0; | ||||||
|  |  | ||||||
|    *rc = ERR; |    *rc = ERR; | ||||||
|  |    *nullbyte = 0; | ||||||
|  |  | ||||||
|    memset(buf, 0, buflen); |    memset(buf, 0, buflen); | ||||||
|  |  | ||||||
|    if(s == NULL){ |    for(int j=0; j<slen; j++){ | ||||||
|       return i; |  | ||||||
|    } |  | ||||||
|  |  | ||||||
|    for(; *s; s++){ |  | ||||||
|       if(i<buflen-2){ |       if(i<buflen-2){ | ||||||
|          buf[i] = *s; |          if(*(s+j) == 0){ | ||||||
|  |             *nullbyte = 1; | ||||||
|  |          } | ||||||
|  |  | ||||||
|  |          buf[i] = *(s+j); | ||||||
|          i++; |          i++; | ||||||
|  |  | ||||||
|          if(*s == c){ |          if(*(s+j) == c){ | ||||||
|             *rc = OK; |             *rc = OK; | ||||||
|             break; |             break; | ||||||
|          } |          } | ||||||
|       } |       } | ||||||
|       else break; |       else { | ||||||
|  |          break; | ||||||
|  |       } | ||||||
|    } |    } | ||||||
|  |  | ||||||
|    return i; |    return i; | ||||||
| @@ -708,7 +716,7 @@ int init_ssl_to_server(struct data *data){ | |||||||
|    n = SSL_connect(data->net->ssl); |    n = SSL_connect(data->net->ssl); | ||||||
|    CHK_SSL(n, "internal ssl error"); |    CHK_SSL(n, "internal ssl error"); | ||||||
|  |  | ||||||
|    printf("Cipher: %s\n", SSL_get_cipher(data->net->ssl)); |    //printf("Cipher: %s\n", SSL_get_cipher(data->net->ssl)); | ||||||
|  |  | ||||||
|    server_cert = SSL_get_peer_certificate(data->net->ssl); |    server_cert = SSL_get_peer_certificate(data->net->ssl); | ||||||
|    CHK_NULL(server_cert, "server cert error"); |    CHK_NULL(server_cert, "server cert error"); | ||||||
|   | |||||||
| @@ -46,7 +46,7 @@ int create_and_bind(char *listen_addr, int listen_port); | |||||||
| int can_i_write_directory(char *dir); | int can_i_write_directory(char *dir); | ||||||
|  |  | ||||||
| void move_email(struct smtp_session *session); | void move_email(struct smtp_session *session); | ||||||
| int read_one_line(char *s, int c, char *buf, int buflen, int *rc); | int read_one_line(char *s, int slen, int c, char *buf, int buflen, int *rc, int *nullbyte); | ||||||
|  |  | ||||||
| int init_ssl_to_server(struct data *data); | int init_ssl_to_server(struct data *data); | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										60
									
								
								src/parser.c
									
									
									
									
									
								
							
							
						
						
									
										60
									
								
								src/parser.c
									
									
									
									
									
								
							| @@ -65,7 +65,9 @@ struct parser_state parse_message(struct session_data *sdata, int take_into_piec | |||||||
|    fclose(f); |    fclose(f); | ||||||
|  |  | ||||||
|    if(data->import && data->import->extra_recipient){ |    if(data->import && data->import->extra_recipient){ | ||||||
|       add_recipient(data->import->extra_recipient, strlen(data->import->extra_recipient), sdata, &state, data, cfg); |       char tmpbuf[SMALLBUFSIZE]; | ||||||
|  |       snprintf(tmpbuf, sizeof(tmpbuf)-1, "%s", data->import->extra_recipient); | ||||||
|  |       add_recipient(tmpbuf, strlen(tmpbuf), sdata, &state, data, cfg); | ||||||
|    } |    } | ||||||
|  |  | ||||||
|    // If both Sender: and From: headers exist, and they are different, then append |    // If both Sender: and From: headers exist, and they are different, then append | ||||||
| @@ -110,6 +112,15 @@ void post_parse(struct session_data *sdata, struct parser_state *state, struct c | |||||||
|       if(sdata->internal_recipient == 1 && sdata->external_recipient == 1) sdata->direction = DIRECTION_INTERNAL_AND_OUTGOING; |       if(sdata->internal_recipient == 1 && sdata->external_recipient == 1) sdata->direction = DIRECTION_INTERNAL_AND_OUTGOING; | ||||||
|    } |    } | ||||||
|  |  | ||||||
|  |    char *q = strrchr(state->receivedbuf, ';'); | ||||||
|  |    if(q){ | ||||||
|  |       time_t received_timestamp = parse_date_header(q+1); | ||||||
|  |       if(received_timestamp > 10000000){ | ||||||
|  |          // If the calculated date based on Date: header line differs more than 1 week | ||||||
|  |          // then we'll override it with the data parsed from the first Received: line | ||||||
|  |          if(labs(received_timestamp - sdata->sent) > 604800) sdata->sent = received_timestamp; | ||||||
|  |       } | ||||||
|  |    } | ||||||
|  |  | ||||||
|    for(i=1; i<=state->n_attachments; i++){ |    for(i=1; i<=state->n_attachments; i++){ | ||||||
|       char puf[SMALLBUFSIZE]; |       char puf[SMALLBUFSIZE]; | ||||||
| @@ -123,7 +134,7 @@ void post_parse(struct session_data *sdata, struct parser_state *state, struct c | |||||||
|  |  | ||||||
|       digest_file(state->attachments[i].internalname, &(state->attachments[i].digest[0])); |       digest_file(state->attachments[i].internalname, &(state->attachments[i].digest[0])); | ||||||
|  |  | ||||||
|       if(cfg->verbosity >= _LOG_DEBUG) syslog(LOG_PRIORITY, "%s: attachment list: i:%d, name=*%s*, type: *%s*, size: %d, int.name: %s, digest: %s", sdata->ttmpfile, i, state->attachments[i].filename, state->attachments[i].type, state->attachments[i].size, state->attachments[i].internalname, state->attachments[i].digest); |       if(cfg->verbosity >= _LOG_DEBUG) syslog(LOG_PRIORITY, "%s: attachment list: i:%d, name=*%s*, type: *%s*, size: %d, int.name: %s, digest: %s, dumped: %d", sdata->ttmpfile, i, state->attachments[i].filename, state->attachments[i].type, state->attachments[i].size, state->attachments[i].internalname, state->attachments[i].digest, state->attachments[i].dumped); | ||||||
|  |  | ||||||
|       char *p = determine_attachment_type(state->attachments[i].filename, state->attachments[i].type); |       char *p = determine_attachment_type(state->attachments[i].filename, state->attachments[i].type); | ||||||
|       len = strlen(p); |       len = strlen(p); | ||||||
| @@ -406,7 +417,10 @@ int parse_line(char *buf, struct parser_state *state, struct session_data *sdata | |||||||
|          state->message_state = MSG_CC; |          state->message_state = MSG_CC; | ||||||
|          buf += strlen("Bcc:"); |          buf += strlen("Bcc:"); | ||||||
|       } |       } | ||||||
|       else if(strncasecmp(buf, "Message-Id:", 11) == 0) state->message_state = MSG_MESSAGE_ID; |       else if(strncasecmp(buf, "Message-Id:", 11) == 0){ | ||||||
|  |          state->message_state = MSG_MESSAGE_ID; | ||||||
|  |          buf += strlen("Message-Id:"); | ||||||
|  |       } | ||||||
|       else if(strncasecmp(buf, "References:", 11) == 0) state->message_state = MSG_REFERENCES; |       else if(strncasecmp(buf, "References:", 11) == 0) state->message_state = MSG_REFERENCES; | ||||||
|       else if(strncasecmp(buf, "Subject:", strlen("Subject:")) == 0){ |       else if(strncasecmp(buf, "Subject:", strlen("Subject:")) == 0){ | ||||||
|          state->message_state = MSG_SUBJECT; |          state->message_state = MSG_SUBJECT; | ||||||
| @@ -430,32 +444,39 @@ int parse_line(char *buf, struct parser_state *state, struct session_data *sdata | |||||||
|  |  | ||||||
|          if(strstr(buf, "=?") && strstr(buf, "?=")) fixupEncodedHeaderLine(buf, MAXBUFSIZE); |          if(strstr(buf, "=?") && strstr(buf, "?=")) fixupEncodedHeaderLine(buf, MAXBUFSIZE); | ||||||
|  |  | ||||||
|          sdata->sent = parse_date_header(buf); |          sdata->sent = parse_date_header(buf+5); | ||||||
|  |  | ||||||
|          /* allow +2 days drift in the parsed Date: value */ |          /* allow +2 days drift in the parsed Date: value */ | ||||||
|  |  | ||||||
|          if(sdata->sent - sdata->now > 2*86400) sdata->sent = sdata->now; |          if(sdata->sent - sdata->now > 2*86400) sdata->sent = sdata->now; | ||||||
|       } |       } | ||||||
|  |  | ||||||
|       else if(strncasecmp(buf, "Delivery-date:", strlen("Delivery-date:")) == 0 && sdata->delivered == 0) sdata->delivered = parse_date_header(buf); |       else if(strncasecmp(buf, "Delivery-date:", strlen("Delivery-date:")) == 0 && sdata->delivered == 0) sdata->delivered = parse_date_header(buf+14); | ||||||
|       else if(strncasecmp(buf, "Received:", strlen("Received:")) == 0) state->message_state = MSG_RECEIVED; |       else if(strncasecmp(buf, "Received:", strlen("Received:")) == 0){ | ||||||
|  |          state->message_state = MSG_RECEIVED; | ||||||
|  |          state->received_header++; | ||||||
|  |       } | ||||||
|       else if(cfg->extra_to_field[0] != '\0' && strncasecmp(buf, cfg->extra_to_field, strlen(cfg->extra_to_field)) == 0){ |       else if(cfg->extra_to_field[0] != '\0' && strncasecmp(buf, cfg->extra_to_field, strlen(cfg->extra_to_field)) == 0){ | ||||||
|          state->message_state = MSG_TO; |          state->message_state = MSG_RECIPIENT; | ||||||
|          buf += strlen(cfg->extra_to_field); |          buf += strlen(cfg->extra_to_field); | ||||||
|       } |       } | ||||||
|  |  | ||||||
|       if(state->message_state == MSG_MESSAGE_ID && state->message_id[0] == 0){ |       if(state->message_state == MSG_MESSAGE_ID && state->message_id[0] == 0){ | ||||||
|          p = strchr(buf+11, ' '); |          while(isspace(*buf)){ | ||||||
|          if(p) p = buf + 12; |             buf++; | ||||||
|          else p = buf + 11; |          } | ||||||
|  |  | ||||||
|          snprintf(state->message_id, SMALLBUFSIZE-1, "%s", p); |          snprintf(state->message_id, SMALLBUFSIZE-1, "%s", buf); | ||||||
|       } |       } | ||||||
|  |  | ||||||
|       if(state->message_state == MSG_CONTENT_TYPE || state->message_state == MSG_CONTENT_DISPOSITION){ |       if(state->message_state == MSG_CONTENT_TYPE || state->message_state == MSG_CONTENT_DISPOSITION){ | ||||||
|          fill_attachment_name_buf(state, buf); |          fill_attachment_name_buf(state, buf); | ||||||
|       } |       } | ||||||
|  |  | ||||||
|  |       if(state->received_header == 1 && state->message_state == MSG_RECEIVED && strlen(state->receivedbuf) + len < sizeof(state->receivedbuf)){ | ||||||
|  |          memcpy(&(state->receivedbuf[strlen(state->receivedbuf)]), buf, len); | ||||||
|  |       } | ||||||
|  |  | ||||||
|       /* we are interested in only From:, To:, Subject:, Received:, Content-*: header lines */ |       /* we are interested in only From:, To:, Subject:, Received:, Content-*: header lines */ | ||||||
|       if(state->message_state <= 0) return 0; |       if(state->message_state <= 0) return 0; | ||||||
|    } |    } | ||||||
| @@ -553,6 +574,8 @@ int parse_line(char *buf, struct parser_state *state, struct session_data *sdata | |||||||
|          state->message_rfc822 = 1; |          state->message_rfc822 = 1; | ||||||
|          state->is_header = 1; |          state->is_header = 1; | ||||||
|  |  | ||||||
|  |          state->has_to_dump = 0; | ||||||
|  |  | ||||||
|          if(sdata->ms_journal == 1){ |          if(sdata->ms_journal == 1){ | ||||||
|             state->is_1st_header = 1; |             state->is_1st_header = 1; | ||||||
|  |  | ||||||
| @@ -618,7 +641,7 @@ int parse_line(char *buf, struct parser_state *state, struct session_data *sdata | |||||||
|       state->pushed_pointer = 0; |       state->pushed_pointer = 0; | ||||||
|  |  | ||||||
|       memset(state->type, 0, TINYBUFSIZE); |       memset(state->type, 0, TINYBUFSIZE); | ||||||
|       snprintf(state->charset, TINYBUFSIZE-1, "unknown"); |       memset(state->charset, 0, TINYBUFSIZE); | ||||||
|  |  | ||||||
|       memset(state->attachment_name_buf, 0, SMALLBUFSIZE); |       memset(state->attachment_name_buf, 0, SMALLBUFSIZE); | ||||||
|       state->anamepos = 0; |       state->anamepos = 0; | ||||||
| @@ -661,7 +684,18 @@ int parse_line(char *buf, struct parser_state *state, struct session_data *sdata | |||||||
|    if(state->texthtml == 1 && state->message_state == MSG_BODY) markHTML(buf, state); |    if(state->texthtml == 1 && state->message_state == MSG_BODY) markHTML(buf, state); | ||||||
|  |  | ||||||
|  |  | ||||||
|    if(state->texthtml == 1) decodeHTML(buf, state->utf8); |    if(state->texthtml == 1){ | ||||||
|  |       size_t buflen = strlen(buf); | ||||||
|  |       decodeHTML(buf, state->utf8); | ||||||
|  |       /* decodeHTML converted some entities to iso-8859-1 */ | ||||||
|  |       if(state->utf8 != 1 && strlen(buf) != buflen){ | ||||||
|  |         /* no charset or us-ascii: switch to iso-8859-1 */ | ||||||
|  |         if (state->charset[0] == 0 || strcasecmp(state->charset, "us-ascii") == 0){ | ||||||
|  |           syslog(LOG_PRIORITY, "%s: assuming iso-8859-1 encoding for HTML (was '%s')", sdata->ttmpfile, state->charset); | ||||||
|  |           snprintf(state->charset, TINYBUFSIZE-1, "ISO8859-1"); | ||||||
|  |         } | ||||||
|  |       } | ||||||
|  |    } | ||||||
|  |  | ||||||
|    /* encode the body if it's not utf-8 encoded */ |    /* encode the body if it's not utf-8 encoded */ | ||||||
|    if(state->message_state == MSG_BODY && state->utf8 != 1){ |    if(state->message_state == MSG_BODY && state->utf8 != 1){ | ||||||
|   | |||||||
| @@ -20,7 +20,7 @@ void fixupEncodedHeaderLine(char *buf, int buflen); | |||||||
| void fixupSoftBreakInQuotedPritableLine(char *buf, struct parser_state *state); | void fixupSoftBreakInQuotedPritableLine(char *buf, struct parser_state *state); | ||||||
| void fixupBase64EncodedLine(char *buf, struct parser_state *state); | void fixupBase64EncodedLine(char *buf, struct parser_state *state); | ||||||
| void markHTML(char *buf, struct parser_state *state); | void markHTML(char *buf, struct parser_state *state); | ||||||
| void setStateHTMLStyle(char *htmlbuf, int pos, struct parser_state *state); | void setStateHTML(char *htmlbuf, int pos, struct parser_state *state); | ||||||
| void translateLine(unsigned char *p, struct parser_state *state); | void translateLine(unsigned char *p, struct parser_state *state); | ||||||
| void fix_email_address_for_sphinx(char *s); | void fix_email_address_for_sphinx(char *s); | ||||||
| void split_email_address(char *s); | void split_email_address(char *s); | ||||||
|   | |||||||
| @@ -40,6 +40,7 @@ void init_state(struct parser_state *state){ | |||||||
|  |  | ||||||
|    state->htmltag = 0; |    state->htmltag = 0; | ||||||
|    state->style = 0; |    state->style = 0; | ||||||
|  |    state->meta_content_type = 0; | ||||||
|  |  | ||||||
|    state->skip_html = 0; |    state->skip_html = 0; | ||||||
|  |  | ||||||
| @@ -49,8 +50,10 @@ void init_state(struct parser_state *state){ | |||||||
|    memset(state->message_id_hash, 0, 2*DIGEST_LENGTH+1); |    memset(state->message_id_hash, 0, 2*DIGEST_LENGTH+1); | ||||||
|    memset(state->miscbuf, 0, MAX_TOKEN_LEN); |    memset(state->miscbuf, 0, MAX_TOKEN_LEN); | ||||||
|    memset(state->qpbuf, 0, MAX_TOKEN_LEN); |    memset(state->qpbuf, 0, MAX_TOKEN_LEN); | ||||||
|  |    memset(state->receivedbuf, 0, sizeof(state->receivedbuf)); | ||||||
|  |  | ||||||
|    memset(state->type, 0, TINYBUFSIZE); |    memset(state->type, 0, TINYBUFSIZE); | ||||||
|  |    memset(state->charset, 0, TINYBUFSIZE); | ||||||
|  |  | ||||||
|    memset(state->attachment_name_buf, 0, SMALLBUFSIZE); |    memset(state->attachment_name_buf, 0, SMALLBUFSIZE); | ||||||
|    state->anamepos = 0; |    state->anamepos = 0; | ||||||
| @@ -67,6 +70,7 @@ void init_state(struct parser_state *state){ | |||||||
|  |  | ||||||
|    state->writebufpos = 0; |    state->writebufpos = 0; | ||||||
|    state->abufpos = 0; |    state->abufpos = 0; | ||||||
|  |    state->received_header = 0; | ||||||
|  |  | ||||||
|    inithash(state->boundaries); |    inithash(state->boundaries); | ||||||
|    inithash(state->rcpt); |    inithash(state->rcpt); | ||||||
| @@ -124,7 +128,6 @@ time_t parse_date_header(char *datestr){ | |||||||
|    char *p, *q, *r, *tz, s[SMALLBUFSIZE], tzh[4], tzm[3]; |    char *p, *q, *r, *tz, s[SMALLBUFSIZE], tzh[4], tzm[3]; | ||||||
|    struct tm tm; |    struct tm tm; | ||||||
|  |  | ||||||
|    datestr += 5; |  | ||||||
|    p = datestr; |    p = datestr; | ||||||
|  |  | ||||||
|    for(; *datestr; datestr++){ |    for(; *datestr; datestr++){ | ||||||
| @@ -550,7 +553,7 @@ void markHTML(char *buf, struct parser_state *state){ | |||||||
|  |  | ||||||
|             if(isspace(*s)){ |             if(isspace(*s)){ | ||||||
|                if(j > 0){ |                if(j > 0){ | ||||||
|                   setStateHTMLStyle(html, pos, state); |                   setStateHTML(html, pos, state); | ||||||
|                   memset(html, 0, SMALLBUFSIZE); j=0; |                   memset(html, 0, SMALLBUFSIZE); j=0; | ||||||
|                } |                } | ||||||
|                pos++; |                pos++; | ||||||
| @@ -575,23 +578,51 @@ void markHTML(char *buf, struct parser_state *state){ | |||||||
|  |  | ||||||
|          if(j > 0){ |          if(j > 0){ | ||||||
|             strncat(html, " ", SMALLBUFSIZE-1); |             strncat(html, " ", SMALLBUFSIZE-1); | ||||||
|             setStateHTMLStyle(html, pos, state); |             setStateHTML(html, pos, state); | ||||||
|             memset(html, 0, SMALLBUFSIZE); j=0; |             memset(html, 0, SMALLBUFSIZE); j=0; | ||||||
|          } |          } | ||||||
|  |          state->meta_content_type = 0; | ||||||
|       } |       } | ||||||
|  |  | ||||||
|    } |    } | ||||||
|  |  | ||||||
|    //printf("append last in line:*%s*, html=+%s+, j=%d\n", puf, html, j); |    //printf("append last in line:*%s*, html=+%s+, j=%d\n", puf, html, j); | ||||||
|    if(j > 0){ setStateHTMLStyle(html, pos, state); } |    if(j > 0){ setStateHTML(html, pos, state); } | ||||||
|  |  | ||||||
|    strcpy(buf, puf); |    strcpy(buf, puf); | ||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
| void setStateHTMLStyle(char *htmlbuf, int pos, struct parser_state *state){ | void setStateHTML(char *htmlbuf, int pos, struct parser_state *state){ | ||||||
|    if(pos == 0 && strncmp(htmlbuf, "style ", 6) == 0) state->style = 1; |    if(pos == 0 && strncmp(htmlbuf, "style ", 6) == 0) state->style = 1; | ||||||
|    if(pos == 0 && strncmp(htmlbuf, "/style ", 7) == 0) state->style = 0; |    if(pos == 0 && strncmp(htmlbuf, "/style ", 7) == 0) state->style = 0; | ||||||
|  |  | ||||||
|  |    if(pos == 0 && state->charset[0] == 0 && strncmp(htmlbuf, "meta ", 5) == 0) state->meta_content_type = 0x1; | ||||||
|  |    if(state->meta_content_type){ | ||||||
|  |      if((state->meta_content_type & 0x2) == 0 && strstr(htmlbuf, "http-equiv=content-type ")) | ||||||
|  |        state->meta_content_type |= 0x2; | ||||||
|  |  | ||||||
|  |      if((state->meta_content_type & 0x4) == 0 && strstr(htmlbuf, "content=text/html;")) | ||||||
|  |        state->meta_content_type |= 0x4; | ||||||
|  |  | ||||||
|  |      if(state->meta_content_type == 0x7){ | ||||||
|  |        char *p, *q; | ||||||
|  |  | ||||||
|  |        p = strstr(htmlbuf, "charset="); | ||||||
|  |        if(p){ | ||||||
|  |          p += 8; | ||||||
|  |          for(q = p; isalnum(*q) || index("-_", *q); q++) | ||||||
|  |            ; | ||||||
|  |  | ||||||
|  |          if(q > p && q-p+1 < (int) sizeof(state->charset)){ | ||||||
|  |            syslog(LOG_PRIORITY, "Changing HTML charset from '%s' to '%*s' due to meta tag", state->charset, (int)(q-p), p); | ||||||
|  |            strncpy(state->charset, p, q-p); | ||||||
|  |            state->charset[q-p+1] = '\0'; | ||||||
|  |            state->meta_content_type = 0; | ||||||
|  |          } | ||||||
|  |        } | ||||||
|  |      } | ||||||
|  |    } | ||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
|   | |||||||
| @@ -38,6 +38,7 @@ int do_av_check(char *filename, struct config *cfg); | |||||||
| int make_digests(struct session_data *sdata, struct config *cfg); | int make_digests(struct session_data *sdata, struct config *cfg); | ||||||
| void digest_file(char *filename, char *digest); | void digest_file(char *filename, char *digest); | ||||||
| void digest_string(char *s, char *digest); | void digest_string(char *s, char *digest); | ||||||
|  | void create_md5_from_email_address(char *puf, char *md5buf); | ||||||
|  |  | ||||||
| void remove_stripped_attachments(struct parser_state *state); | void remove_stripped_attachments(struct parser_state *state); | ||||||
| int process_message(struct session_data *sdata, struct parser_state *state, struct data *data, struct config *cfg); | int process_message(struct session_data *sdata, struct parser_state *state, struct data *data, struct config *cfg); | ||||||
|   | |||||||
| @@ -46,7 +46,7 @@ int main(int argc, char **argv){ | |||||||
|       return 1; |       return 1; | ||||||
|    } |    } | ||||||
|  |  | ||||||
|    snprintf(filename, sizeof(filename)-1, "%s/%02x/%c%c%c/%c%c/%c%c/%s.a%d", cfg.queuedir, cfg.server_id, argv[1][8], argv[1][9], argv[1][10], argv[1][RND_STR_LEN-4], argv[1][RND_STR_LEN-3], argv[1][RND_STR_LEN-2], argv[1][RND_STR_LEN-1], argv[1], atoi(argv[2])); |    snprintf(filename, sizeof(filename)-1, "%s/%c%c/%c%c%c/%c%c/%c%c/%s.a%d", cfg.queuedir, argv[1][24], argv[1][25], argv[1][8], argv[1][9], argv[1][10], argv[1][RND_STR_LEN-4], argv[1][RND_STR_LEN-3], argv[1][RND_STR_LEN-2], argv[1][RND_STR_LEN-1], argv[1], atoi(argv[2])); | ||||||
| #ifdef HAVE_SUPPORT_FOR_COMPAT_STORAGE_LAYOUT | #ifdef HAVE_SUPPORT_FOR_COMPAT_STORAGE_LAYOUT | ||||||
|    if(stat(filename, &st)){ |    if(stat(filename, &st)){ | ||||||
|       snprintf(filename, sizeof(filename)-1, "%s/%02x/%c%c/%c%c/%c%c/%s.a%d", cfg.queuedir, cfg.server_id, argv[1][RND_STR_LEN-6], argv[1][RND_STR_LEN-5], argv[1][RND_STR_LEN-4], argv[1][RND_STR_LEN-3], argv[1][RND_STR_LEN-2], argv[1][RND_STR_LEN-1], argv[1], atoi(argv[2])); |       snprintf(filename, sizeof(filename)-1, "%s/%02x/%c%c/%c%c/%c%c/%s.a%d", cfg.queuedir, cfg.server_id, argv[1][RND_STR_LEN-6], argv[1][RND_STR_LEN-5], argv[1][RND_STR_LEN-4], argv[1][RND_STR_LEN-3], argv[1][RND_STR_LEN-2], argv[1][RND_STR_LEN-1], argv[1], atoi(argv[2])); | ||||||
|   | |||||||
| @@ -53,6 +53,7 @@ void usage(){ | |||||||
|    printf("    -j <failed folder>                Move failed to import emails to this folder\n"); |    printf("    -j <failed folder>                Move failed to import emails to this folder\n"); | ||||||
|    printf("    -a <recipient>                    Add recipient to the To:/Cc: list\n"); |    printf("    -a <recipient>                    Add recipient to the To:/Cc: list\n"); | ||||||
|    printf("    -T <id>                           Update import table at id=<id>\n"); |    printf("    -T <id>                           Update import table at id=<id>\n"); | ||||||
|  |    printf("    -Z <ms>                           Delay Z milliseconds in between emails being imported\n"); | ||||||
|    printf("    -D                                Dry-run, do not import anything\n"); |    printf("    -D                                Dry-run, do not import anything\n"); | ||||||
|    printf("    -y                                Read pilerexport data from stdin\n"); |    printf("    -y                                Read pilerexport data from stdin\n"); | ||||||
|    printf("    -o                                Only download emails for POP3/IMAP import\n"); |    printf("    -o                                Only download emails for POP3/IMAP import\n"); | ||||||
| @@ -100,6 +101,7 @@ int main(int argc, char **argv){ | |||||||
|    import.tot_msgs = 0; |    import.tot_msgs = 0; | ||||||
|    import.table_id = 0; |    import.table_id = 0; | ||||||
|    import.folder = NULL; |    import.folder = NULL; | ||||||
|  |    import.delay = 0; | ||||||
|  |  | ||||||
|    data.import = &import; |    data.import = &import; | ||||||
|  |  | ||||||
| @@ -136,6 +138,7 @@ int main(int argc, char **argv){ | |||||||
|             {"timeout",      required_argument,  0,  't' }, |             {"timeout",      required_argument,  0,  't' }, | ||||||
|             {"start-position",required_argument,  0,  's' }, |             {"start-position",required_argument,  0,  's' }, | ||||||
|             {"table-id",     required_argument,  0,  'T' }, |             {"table-id",     required_argument,  0,  'T' }, | ||||||
|  |             {"delay",        required_argument,  0,  'Z' }, | ||||||
|             {"quiet",        no_argument,        0,  'q' }, |             {"quiet",        no_argument,        0,  'q' }, | ||||||
|             {"recursive",    no_argument,        0,  'R' }, |             {"recursive",    no_argument,        0,  'R' }, | ||||||
|             {"remove-after-import",no_argument,  0,  'r' }, |             {"remove-after-import",no_argument,  0,  'r' }, | ||||||
| @@ -150,9 +153,9 @@ int main(int argc, char **argv){ | |||||||
|  |  | ||||||
|       int option_index = 0; |       int option_index = 0; | ||||||
|  |  | ||||||
|       int c = getopt_long(argc, argv, "c:m:M:e:d:i:K:u:p:P:x:F:f:a:b:t:s:g:j:T:yDRroqh?", long_options, &option_index); |       int c = getopt_long(argc, argv, "c:m:M:e:d:i:K:u:p:P:x:F:f:a:b:t:s:g:j:T:Z:yDRroqh?", long_options, &option_index); | ||||||
| #else | #else | ||||||
|       int c = getopt(argc, argv, "c:m:M:e:d:i:K:u:p:P:x:F:f:a:b:t:s:g:j:T:yDRroqh?"); |       int c = getopt(argc, argv, "c:m:M:e:d:i:K:u:p:P:x:F:f:a:b:t:s:g:j:T:Z:yDRroqh?"); | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|       if(c == -1) break; |       if(c == -1) break; | ||||||
| @@ -271,6 +274,15 @@ int main(int argc, char **argv){ | |||||||
|                     data.import->table_id = atoi(optarg); |                     data.import->table_id = atoi(optarg); | ||||||
|                     break; |                     break; | ||||||
|  |  | ||||||
|  |          case 'Z' : | ||||||
|  |                     if(atoi(optarg) < 1){ | ||||||
|  |                        printf("invalid delay value: %s\n", optarg); | ||||||
|  |                        return -1; | ||||||
|  |                     } | ||||||
|  |  | ||||||
|  |                     data.import->delay = atoi(optarg); | ||||||
|  |                     break; | ||||||
|  |  | ||||||
|          case 'y' : |          case 'y' : | ||||||
|                     read_from_pilerexport = 1; |                     read_from_pilerexport = 1; | ||||||
|                     break; |                     break; | ||||||
| @@ -316,6 +328,9 @@ int main(int argc, char **argv){ | |||||||
|    /* make sure we don't discard messages without a valid Message-Id when importing manually */ |    /* make sure we don't discard messages without a valid Message-Id when importing manually */ | ||||||
|    cfg.archive_emails_not_having_message_id = 1; |    cfg.archive_emails_not_having_message_id = 1; | ||||||
|  |  | ||||||
|  |    /* The mmap_dedup_test feature is expected to work with the piler daemon only */ | ||||||
|  |    cfg.mmap_dedup_test = 0; | ||||||
|  |  | ||||||
|    if(read_key(&cfg)){ |    if(read_key(&cfg)){ | ||||||
|       printf("%s\n", ERR_READING_KEY); |       printf("%s\n", ERR_READING_KEY); | ||||||
|       return ERR; |       return ERR; | ||||||
|   | |||||||
							
								
								
									
										104
									
								
								src/pop3.c
									
									
									
									
									
								
							
							
						
						
									
										104
									
								
								src/pop3.c
									
									
									
									
									
								
							| @@ -23,16 +23,6 @@ | |||||||
| #include <piler.h> | #include <piler.h> | ||||||
|  |  | ||||||
|  |  | ||||||
| int is_last_complete_pop3_packet(char *s, int len){ |  | ||||||
|  |  | ||||||
|    if(*(s+len-5) == '\r' && *(s+len-4) == '\n' && *(s+len-3) == '.' && *(s+len-2) == '\r' && *(s+len-1) == '\n'){ |  | ||||||
|       return 1; |  | ||||||
|    } |  | ||||||
|  |  | ||||||
|    return 0; |  | ||||||
| } |  | ||||||
|  |  | ||||||
|  |  | ||||||
| int connect_to_pop3_server(struct data *data){ | int connect_to_pop3_server(struct data *data){ | ||||||
|    char buf[MAXBUFSIZE]; |    char buf[MAXBUFSIZE]; | ||||||
|  |  | ||||||
| @@ -86,66 +76,86 @@ void get_number_of_total_messages(struct data *data){ | |||||||
|  |  | ||||||
|  |  | ||||||
| int pop3_download_email(struct data *data, int i){ | int pop3_download_email(struct data *data, int i){ | ||||||
|    int n, fd, pos=0, lastpos=0, nreads=0; |    char *p, buf[MAXBUFSIZE], savedbuf[MAXBUFSIZE], copybuf[2*MAXBUFSIZE]; | ||||||
|    char *p, buf[MAXBUFSIZE]; |  | ||||||
|    char aggrbuf[3*MAXBUFSIZE]; |  | ||||||
|  |  | ||||||
|    data->import->processed_messages++; |    data->import->processed_messages++; | ||||||
|  |  | ||||||
|    snprintf(data->import->filename, SMALLBUFSIZE-1, "pop3-tmp-%d-%d.txt", getpid(), i); |    snprintf(data->import->filename, SMALLBUFSIZE-1, "pop3-tmp-%d-%d.txt", getpid(), i); | ||||||
|    unlink(data->import->filename); |    unlink(data->import->filename); | ||||||
|  |  | ||||||
|    fd = open(data->import->filename, O_CREAT|O_EXCL|O_RDWR|O_TRUNC, S_IRUSR|S_IWUSR); |    int fd = open(data->import->filename, O_CREAT|O_EXCL|O_RDWR|O_TRUNC, S_IRUSR|S_IWUSR); | ||||||
|    if(fd == -1){ |    if(fd == -1){ | ||||||
|       printf("cannot open: %s\n", data->import->filename); |       printf("cannot open: %s\n", data->import->filename); | ||||||
|       return ERR; |       return ERR; | ||||||
|    } |    } | ||||||
|  |  | ||||||
|  |    memset(savedbuf, 0, sizeof(savedbuf)); | ||||||
|  |  | ||||||
|    snprintf(buf, sizeof(buf)-1, "RETR %d\r\n", i); |    snprintf(buf, sizeof(buf)-1, "RETR %d\r\n", i); | ||||||
|    write1(data->net, buf, strlen(buf)); |    write1(data->net, buf, strlen(buf)); | ||||||
|  |  | ||||||
|    memset(aggrbuf, 0, sizeof(aggrbuf)); |    int nlines = 0; | ||||||
|  |    int endofmessage = 0; | ||||||
|  |    int savedlen = 0; | ||||||
|  |    int n = 0; | ||||||
|  |  | ||||||
|    while((n = recvtimeoutssl(data->net, buf, sizeof(buf))) > 0){ |    while((n = recvtimeoutssl(data->net, buf, sizeof(buf))) > 0){ | ||||||
|       nreads++; |       int remaininglen = n; | ||||||
|  |  | ||||||
|       if(nreads == 1){ |       if(savedlen){ | ||||||
|  |          memset(copybuf, 0, sizeof(copybuf)); | ||||||
|  |          memcpy(copybuf, savedbuf, savedlen); | ||||||
|  |          memcpy(©buf[savedlen], buf, n); | ||||||
|  |  | ||||||
|          if(strncmp(buf, "+OK", 3) == 0){ |          remaininglen += savedlen; | ||||||
|             p = strchr(&buf[3], '\n'); |  | ||||||
|             if(p){ |          savedlen = 0; | ||||||
|                *p = '\0'; |          memset(savedbuf, 0, sizeof(savedbuf)); | ||||||
|                pos = strlen(buf)+1; |  | ||||||
|                *p = '\n'; |          p = ©buf[0]; | ||||||
|  |       } else { | ||||||
|  |          p = &buf[0]; | ||||||
|  |       } | ||||||
|  |  | ||||||
|  |       int puflen=0; | ||||||
|  |       int rc=OK; | ||||||
|  |       int nullbyte=0; | ||||||
|  |  | ||||||
|  |       do { | ||||||
|  |          char puf[MAXBUFSIZE]; | ||||||
|  |  | ||||||
|  |          puflen = read_one_line(p, remaininglen, '\n', puf, sizeof(puf)-1, &rc, &nullbyte); | ||||||
|  |          remaininglen -= puflen; | ||||||
|  |          nlines++; | ||||||
|  |  | ||||||
|  |          if(nlines == 1){ | ||||||
|  |             if(strncmp(puf, "+OK", 3)){ | ||||||
|  |                printf("error: %s", puf); | ||||||
|  |                return ERR; | ||||||
|  |             } | ||||||
|  |          } else { | ||||||
|  |             if(puf[puflen-1] == '\n'){ | ||||||
|  |                if(puflen == 3 && puf[0] == '.' && puf[1] == '\r' && puf[2] == '\n'){ | ||||||
|  |                   endofmessage = 1; | ||||||
|  |                   break; | ||||||
|  |                } | ||||||
|  |  | ||||||
|  |                int dotstuff = 0; | ||||||
|  |                if(puf[0] == '.' && puf[1] != '\r' && puf[1] != '\n') dotstuff = 1; | ||||||
|  |  | ||||||
|  |                if(write(fd, &puf[dotstuff], puflen-dotstuff) == -1) printf("ERROR: writing to fd\n"); | ||||||
|  |  | ||||||
|  |             } else if(puflen > 0) { | ||||||
|  |                savedlen = puflen; | ||||||
|  |                snprintf(savedbuf, sizeof(savedbuf)-1, "%s", puf); | ||||||
|             } |             } | ||||||
|          } |          } | ||||||
|          else { printf("error: %s", buf); return ERR; } |  | ||||||
|  |  | ||||||
|       } |          p += puflen; | ||||||
|  |  | ||||||
|       if((uint)(lastpos + 1 + n) < sizeof(aggrbuf)){ |       } while(puflen > 0); | ||||||
|  |  | ||||||
|          if(nreads == 1){ |       if(endofmessage){ | ||||||
|             memcpy(aggrbuf+lastpos, buf+pos, n-pos); |  | ||||||
|             lastpos += n-pos; |  | ||||||
|          } |  | ||||||
|          else { |  | ||||||
|             memcpy(aggrbuf+lastpos, buf, n); |  | ||||||
|             lastpos += n; |  | ||||||
|          } |  | ||||||
|       } |  | ||||||
|       else { |  | ||||||
|          if(write(fd, aggrbuf, sizeof(buf)) == -1) printf("ERROR: writing to fd\n"); |  | ||||||
|  |  | ||||||
|          memmove(aggrbuf, aggrbuf+sizeof(buf), lastpos-sizeof(buf)); |  | ||||||
|          lastpos -= sizeof(buf); |  | ||||||
|  |  | ||||||
|          memcpy(aggrbuf+lastpos, buf, n); |  | ||||||
|          lastpos += n; |  | ||||||
|       } |  | ||||||
|  |  | ||||||
|       if(is_last_complete_pop3_packet(aggrbuf, lastpos) == 1){ |  | ||||||
|          if(write(fd, aggrbuf, lastpos-3) == -1) printf("ERROR: writing to fd\n"); |  | ||||||
|          break; |          break; | ||||||
|       } |       } | ||||||
|    } |    } | ||||||
|   | |||||||
| @@ -75,12 +75,10 @@ uint64 get_max_meta_id(struct session_data *sdata){ | |||||||
|  |  | ||||||
| uint64 retrieve_email_by_metadata_id(struct session_data *sdata, struct data *data, uint64 from_id, uint64 to_id, struct config *cfg){ | uint64 retrieve_email_by_metadata_id(struct session_data *sdata, struct data *data, uint64 from_id, uint64 to_id, struct config *cfg){ | ||||||
|    char s[SMALLBUFSIZE]; |    char s[SMALLBUFSIZE]; | ||||||
|    uint64 stored_id=0, reindexed=0, delta; |    uint64 stored_id=0, reindexed=0; | ||||||
|    struct parser_state state; |    struct parser_state state; | ||||||
|    struct sql sql; |    struct sql sql; | ||||||
|  |  | ||||||
|    delta = to_id - from_id; |  | ||||||
|  |  | ||||||
|    if(cfg->enable_folders == 1) |    if(cfg->enable_folders == 1) | ||||||
|       snprintf(s, sizeof(s)-1, "SELECT m.`id`, `piler_id`, `arrived`, `sent`, f.folder_id FROM %s m, %s f WHERE m.id=f.id AND (m.id BETWEEN %llu AND %llu) AND `deleted`=0", SQL_METADATA_TABLE, SQL_FOLDER_MESSAGE_TABLE, from_id, to_id); |       snprintf(s, sizeof(s)-1, "SELECT m.`id`, `piler_id`, `arrived`, `sent`, f.folder_id FROM %s m, %s f WHERE m.id=f.id AND (m.id BETWEEN %llu AND %llu) AND `deleted`=0", SQL_METADATA_TABLE, SQL_FOLDER_MESSAGE_TABLE, from_id, to_id); | ||||||
|    else |    else | ||||||
| @@ -123,6 +121,12 @@ uint64 retrieve_email_by_metadata_id(struct session_data *sdata, struct data *da | |||||||
|  |  | ||||||
|             snprintf(sdata->filename, SMALLBUFSIZE-1, "%s", filename); |             snprintf(sdata->filename, SMALLBUFSIZE-1, "%s", filename); | ||||||
|  |  | ||||||
|  |             struct stat st; | ||||||
|  |             sdata->tot_len = stat(filename, &st) == 0 ? st.st_size : 0; | ||||||
|  |  | ||||||
|  |             sdata->internal_sender = sdata->internal_recipient = sdata->external_recipient = sdata->direction = 0; | ||||||
|  |             memset(sdata->attachments, 0, SMALLBUFSIZE); | ||||||
|  |  | ||||||
|             state = parse_message(sdata, 1, data, cfg); |             state = parse_message(sdata, 1, data, cfg); | ||||||
|             post_parse(sdata, &state, cfg); |             post_parse(sdata, &state, cfg); | ||||||
|  |  | ||||||
| @@ -137,6 +141,8 @@ uint64 retrieve_email_by_metadata_id(struct session_data *sdata, struct data *da | |||||||
|             unlink(filename); |             unlink(filename); | ||||||
|  |  | ||||||
|             if(progressbar){ |             if(progressbar){ | ||||||
|  |                uint64 delta = to_id - from_id + 1; | ||||||
|  |  | ||||||
|                printf("processed: %8llu [%3d%%]\r", reindexed, (int)(100*reindexed/delta)); |                printf("processed: %8llu [%3d%%]\r", reindexed, (int)(100*reindexed/delta)); | ||||||
|                fflush(stdout); |                fflush(stdout); | ||||||
|             } |             } | ||||||
|   | |||||||
| @@ -99,6 +99,7 @@ void init_smtp_session(struct smtp_session *session, int slot, int sd, char *cli | |||||||
|    session->net.ctx = NULL; |    session->net.ctx = NULL; | ||||||
|    session->net.ssl = NULL; |    session->net.ssl = NULL; | ||||||
|  |  | ||||||
|  |    session->nullbyte = 0; | ||||||
|    session->last_data_char = 0; |    session->last_data_char = 0; | ||||||
|  |  | ||||||
|    session->fd = -1; |    session->fd = -1; | ||||||
| @@ -160,11 +161,13 @@ void tear_down_session(struct smtp_session **sessions, int slot, int *num_connec | |||||||
|  |  | ||||||
|  |  | ||||||
| void handle_data(struct smtp_session *session, char *readbuf, int readlen, struct config *cfg){ | void handle_data(struct smtp_session *session, char *readbuf, int readlen, struct config *cfg){ | ||||||
|    int puflen, rc; |    int puflen, rc, nullbyte; | ||||||
|    char *p, copybuf[BIGBUFSIZE+MAXBUFSIZE], puf[MAXBUFSIZE]; |    char *p, copybuf[BIGBUFSIZE+MAXBUFSIZE], puf[MAXBUFSIZE]; | ||||||
|  |  | ||||||
|    // if there's something in the saved buffer, then let's merge them |    // if there's something in the saved buffer, then let's merge them | ||||||
|  |  | ||||||
|  |    int remaininglen = readlen + session->buflen; | ||||||
|  |  | ||||||
|    if(session->buflen > 0){ |    if(session->buflen > 0){ | ||||||
|       memset(copybuf, 0, sizeof(copybuf)); |       memset(copybuf, 0, sizeof(copybuf)); | ||||||
|  |  | ||||||
| @@ -183,30 +186,42 @@ void handle_data(struct smtp_session *session, char *readbuf, int readlen, struc | |||||||
|  |  | ||||||
|  |  | ||||||
|    do { |    do { | ||||||
|       puflen = read_one_line(p, '\n', puf, sizeof(puf)-1, &rc); |       puflen = read_one_line(p, remaininglen, '\n', puf, sizeof(puf)-1, &rc, &nullbyte); | ||||||
|       p += puflen; |       p += puflen; | ||||||
|  |       remaininglen -= puflen; | ||||||
|  |  | ||||||
|  |       if(nullbyte){ | ||||||
|  |          session->nullbyte = 1; | ||||||
|  |       } | ||||||
|  |  | ||||||
|  |       // complete line: rc == OK and puflen > 0 | ||||||
|  |       // incomplete line with something in the buffer: rc == ERR and puflen > 0 | ||||||
|  |  | ||||||
|       if(puflen > 0){ |       if(puflen > 0){ | ||||||
|          // Update lasttime if we have a line to process |          // Update lasttime if we have a line to process | ||||||
|          time(&(session->lasttime)); |          time(&(session->lasttime)); | ||||||
|  |  | ||||||
|          // pass the puffer to process_data() only if there was an '\n' |          // Save incomplete line to buffer | ||||||
|          // on the line or the puffer does not start with a period |          if(rc == ERR){ | ||||||
|          if(session->protocol_state == SMTP_STATE_DATA && (rc == OK || puf[0] != '.')){ |             memcpy(session->buf, puf, puflen); | ||||||
|             sig_block(SIGALRM); |  | ||||||
|             process_data(session, puf, puflen); |  | ||||||
|             sig_unblock(SIGALRM); |  | ||||||
|          } |  | ||||||
|          else if(session->protocol_state == SMTP_STATE_BDAT){ |  | ||||||
|             process_bdat(session, puf, puflen, cfg); |  | ||||||
|          } |  | ||||||
|          else if(rc == OK){ |  | ||||||
|             process_smtp_command(session, puf, cfg); |  | ||||||
|          } |  | ||||||
|          else { |  | ||||||
|             snprintf(session->buf, MAXBUFSIZE-1, "%s", puf); |  | ||||||
|             session->buflen = puflen; |             session->buflen = puflen; | ||||||
|          } |          } | ||||||
|  |  | ||||||
|  |          // We have a complete line to process | ||||||
|  |  | ||||||
|  |          if(rc == OK){ | ||||||
|  |             if(session->protocol_state == SMTP_STATE_BDAT){ | ||||||
|  |                process_bdat(session, puf, puflen, cfg); | ||||||
|  |             } | ||||||
|  |             else if(session->protocol_state == SMTP_STATE_DATA){ | ||||||
|  |                sig_block(SIGALRM); | ||||||
|  |                process_data(session, puf, puflen); | ||||||
|  |                sig_unblock(SIGALRM); | ||||||
|  |             } | ||||||
|  |             else { | ||||||
|  |                process_smtp_command(session, puf, cfg); | ||||||
|  |             } | ||||||
|  |          } | ||||||
|       } |       } | ||||||
|  |  | ||||||
|    } while(puflen > 0); |    } while(puflen > 0); | ||||||
|   | |||||||
							
								
								
									
										20
									
								
								src/smtp.c
									
									
									
									
									
								
							
							
						
						
									
										20
									
								
								src/smtp.c
									
									
									
									
									
								
							| @@ -84,14 +84,24 @@ void process_data(struct smtp_session *session, char *buf, int buflen){ | |||||||
|       // write line to file |       // write line to file | ||||||
|       int written=0, n_writes=0; |       int written=0, n_writes=0; | ||||||
|  |  | ||||||
|  |       // In the DATA phase skip the 1st character if it's a dot (.) | ||||||
|  |       // and there are more characters before the trailing CR-LF | ||||||
|  |       // | ||||||
|  |       // See https://www.ietf.org/rfc/rfc5321.html#section-4.5.2 for more. | ||||||
|  |  | ||||||
|  |       int dotstuff = 0; | ||||||
|  |       if(*buf == '.' && buflen > 1 && *(buf+1) != '\r' && *(buf+1) != '\n') dotstuff = 1; | ||||||
|  |  | ||||||
|       while(written < buflen) { |       while(written < buflen) { | ||||||
|          int len = write(session->fd, buf+written, buflen-written); |          int len = write(session->fd, buf+dotstuff+written, buflen-dotstuff-written); | ||||||
|  |  | ||||||
|          n_writes++; |          n_writes++; | ||||||
|  |  | ||||||
|          if(len > 0){ |          if(len > 0){ | ||||||
|             if(len != buflen) syslog(LOG_PRIORITY, "WARN: partial write: %d/%d bytes (round: %d)", len, buflen, n_writes); |             if(len != buflen-dotstuff) syslog(LOG_PRIORITY, "WARN: partial write: %d/%d bytes (round: %d)", len, buflen-dotstuff, n_writes); | ||||||
|             written += len; |             written += len + dotstuff; | ||||||
|             session->tot_len += len; |             session->tot_len += len; | ||||||
|  |             dotstuff = 0; | ||||||
|          } |          } | ||||||
|          else syslog(LOG_PRIORITY, "ERROR (line: %d) process_data(): written %d bytes", __LINE__, len); |          else syslog(LOG_PRIORITY, "ERROR (line: %d) process_data(): written %d bytes", __LINE__, len); | ||||||
|       } |       } | ||||||
| @@ -171,10 +181,14 @@ int init_ssl(struct smtp_session *session){ | |||||||
|       return 0; |       return 0; | ||||||
|    } |    } | ||||||
|  |  | ||||||
|  | #if OPENSSL_VERSION_NUMBER < 0x10100000L | ||||||
|  |    SSL_CTX_set_options(session->net.ctx, SSL_OP_NO_SSLv2|SSL_OP_NO_SSLv3|SSL_OP_NO_TLSv1|SSL_OP_NO_TLSv1_1); | ||||||
|  | #else | ||||||
|    if(SSL_CTX_set_min_proto_version(session->net.ctx, session->cfg->tls_min_version_number) == 0){ |    if(SSL_CTX_set_min_proto_version(session->net.ctx, session->cfg->tls_min_version_number) == 0){ | ||||||
|       syslog(LOG_PRIORITY, "failed SSL_CTX_set_min_proto_version() to %s/%d", session->cfg->tls_min_version, session->cfg->tls_min_version_number); |       syslog(LOG_PRIORITY, "failed SSL_CTX_set_min_proto_version() to %s/%d", session->cfg->tls_min_version, session->cfg->tls_min_version_number); | ||||||
|       return 0; |       return 0; | ||||||
|    } |    } | ||||||
|  | #endif | ||||||
|  |  | ||||||
|    if(SSL_CTX_set_cipher_list(session->net.ctx, session->cfg->cipher_list) == 0){ |    if(SSL_CTX_set_cipher_list(session->net.ctx, session->cfg->cipher_list) == 0){ | ||||||
|       syslog(LOG_PRIORITY, "failed to set cipher list: '%s'", session->cfg->cipher_list); |       syslog(LOG_PRIORITY, "failed to set cipher list: '%s'", session->cfg->cipher_list); | ||||||
|   | |||||||
| @@ -153,6 +153,7 @@ int main(int argc, char **argv){ | |||||||
|    printf("from: *%s (%s)*\n", state.b_from, state.b_from_domain); |    printf("from: *%s (%s)*\n", state.b_from, state.b_from_domain); | ||||||
|    printf("sender: *%s (%s)*\n", state.b_sender, state.b_sender_domain); |    printf("sender: *%s (%s)*\n", state.b_sender, state.b_sender_domain); | ||||||
|    printf("to: *%s (%s)*\n", state.b_to, state.b_to_domain); |    printf("to: *%s (%s)*\n", state.b_to, state.b_to_domain); | ||||||
|  |    printf("journal recipients: *%s*\n", state.b_journal_to); | ||||||
|    printf("reference: *%s*\n", state.reference); |    printf("reference: *%s*\n", state.reference); | ||||||
|    printf("subject: *%s*\n", state.b_subject); |    printf("subject: *%s*\n", state.b_subject); | ||||||
|    printf("body: *%s*\n", state.b_body); |    printf("body: *%s*\n", state.b_body); | ||||||
| @@ -183,7 +184,7 @@ int main(int argc, char **argv){ | |||||||
|    clearhash(data.mydomains); |    clearhash(data.mydomains); | ||||||
|  |  | ||||||
|    for(i=1; i<=state.n_attachments; i++){ |    for(i=1; i<=state.n_attachments; i++){ | ||||||
|       printf("i:%d, name=*%s*, type: *%s*, size: %d, int.name: %s, digest: %s\n", i, state.attachments[i].filename, state.attachments[i].type, state.attachments[i].size, state.attachments[i].internalname, state.attachments[i].digest); |       printf("i:%d, name=*%s*, type: *%s*, size: %d, int.name: %s, dumped: %d, digest: %s\n", i, state.attachments[i].filename, state.attachments[i].type, state.attachments[i].size, state.attachments[i].internalname, state.attachments[i].dumped, state.attachments[i].digest); | ||||||
|       unlink(state.attachments[i].internalname); |       unlink(state.attachments[i].internalname); | ||||||
|    } |    } | ||||||
|  |  | ||||||
| @@ -195,6 +196,8 @@ int main(int argc, char **argv){ | |||||||
|  |  | ||||||
|    printf("spam: %d\n", sdata.spam_message); |    printf("spam: %d\n", sdata.spam_message); | ||||||
|  |  | ||||||
|  |    printf("1st received line: %s\n", state.receivedbuf); | ||||||
|  |  | ||||||
|    if(sdata.internal_sender == 0 && sdata.internal_recipient == 0) printf("NOT IN mydomains\n"); |    if(sdata.internal_sender == 0 && sdata.internal_recipient == 0) printf("NOT IN mydomains\n"); | ||||||
|  |  | ||||||
|    printf("\n\n"); |    printf("\n\n"); | ||||||
|   | |||||||
| @@ -50,6 +50,8 @@ void tokenize(char *buf, struct parser_state *state, struct session_data *sdata, | |||||||
|          continue; |          continue; | ||||||
|       } |       } | ||||||
|  |  | ||||||
|  |       char md5buf[2*MD5_DIGEST_LENGTH+2]; | ||||||
|  |  | ||||||
|       if(state->message_state == MSG_FROM && state->is_1st_header == 1 && strlen(state->b_from) < SMALLBUFSIZE-len-1){ |       if(state->message_state == MSG_FROM && state->is_1st_header == 1 && strlen(state->b_from) < SMALLBUFSIZE-len-1){ | ||||||
|          strtolower(puf); |          strtolower(puf); | ||||||
|  |  | ||||||
| @@ -69,6 +71,11 @@ void tokenize(char *buf, struct parser_state *state, struct session_data *sdata, | |||||||
|  |  | ||||||
|             if(is_email_address_on_my_domains(puf, data) == 1) sdata->internal_sender = 1; |             if(is_email_address_on_my_domains(puf, data) == 1) sdata->internal_sender = 1; | ||||||
|  |  | ||||||
|  |             if(len >= MAX_EMAIL_ADDRESS_SPHINX_LEN && strlen(state->b_from) < SMALLBUFSIZE-len-1){ | ||||||
|  |                create_md5_from_email_address(puf, md5buf); | ||||||
|  |                memcpy(&(state->b_from[strlen(state->b_from)]), md5buf, strlen(md5buf)); | ||||||
|  |             } | ||||||
|  |  | ||||||
|             if(strlen(state->b_from) < SMALLBUFSIZE-len-1){ |             if(strlen(state->b_from) < SMALLBUFSIZE-len-1){ | ||||||
|                split_email_address(puf); |                split_email_address(puf); | ||||||
|                memcpy(&(state->b_from[strlen(state->b_from)]), puf, len); |                memcpy(&(state->b_from[strlen(state->b_from)]), puf, len); | ||||||
| @@ -88,6 +95,11 @@ void tokenize(char *buf, struct parser_state *state, struct session_data *sdata, | |||||||
|                memcpy(&(state->b_sender_domain), q+1, strlen(q+1)-1); |                memcpy(&(state->b_sender_domain), q+1, strlen(q+1)-1); | ||||||
|             } |             } | ||||||
|  |  | ||||||
|  |             if(len >= MAX_EMAIL_ADDRESS_SPHINX_LEN && strlen(state->b_sender) < SMALLBUFSIZE-len-1){ | ||||||
|  |                create_md5_from_email_address(puf, md5buf); | ||||||
|  |                memcpy(&(state->b_sender[strlen(state->b_sender)]), md5buf, strlen(md5buf)); | ||||||
|  |             } | ||||||
|  |  | ||||||
|             if(strlen(state->b_sender) < SMALLBUFSIZE-len-1){ |             if(strlen(state->b_sender) < SMALLBUFSIZE-len-1){ | ||||||
|                split_email_address(puf); |                split_email_address(puf); | ||||||
|                memcpy(&(state->b_sender[strlen(state->b_sender)]), puf, len); |                memcpy(&(state->b_sender[strlen(state->b_sender)]), puf, len); | ||||||
| @@ -101,12 +113,18 @@ void tokenize(char *buf, struct parser_state *state, struct session_data *sdata, | |||||||
|          q = strchr(puf, '@'); |          q = strchr(puf, '@'); | ||||||
|          if(q) fix_plus_sign_in_email_address(puf, &q, &len); |          if(q) fix_plus_sign_in_email_address(puf, &q, &len); | ||||||
|  |  | ||||||
|          if((state->message_state == MSG_RECIPIENT || state->message_state == MSG_ENVELOPE_TO) && findnode(state->journal_recipient, puf) == NULL){ |          if((state->message_state == MSG_RECIPIENT || state->message_state == MSG_ENVELOPE_TO) && findnode(state->journal_recipient, puf) == NULL && state->journaltolen < sizeof(state->b_journal_to)-len-1){ | ||||||
|             addnode(state->journal_recipient, puf); |             addnode(state->journal_recipient, puf); | ||||||
|             memcpy(&(state->b_journal_to[state->journaltolen]), puf, len); |             memcpy(&(state->b_journal_to[state->journaltolen]), puf, len); | ||||||
|  |             state->journaltolen += len; | ||||||
|             if(cfg->verbosity >= _LOG_DEBUG) syslog(LOG_PRIORITY, "%s: journal rcpt: '%s'", sdata->ttmpfile, puf); |             if(cfg->verbosity >= _LOG_DEBUG) syslog(LOG_PRIORITY, "%s: journal rcpt: '%s'", sdata->ttmpfile, puf); | ||||||
|          } |          } | ||||||
|  |  | ||||||
|  |          if(len >= MAX_EMAIL_ADDRESS_SPHINX_LEN){ | ||||||
|  |             create_md5_from_email_address(puf, md5buf); | ||||||
|  |             add_recipient(md5buf, strlen(md5buf), sdata, state, data, cfg); | ||||||
|  |          } | ||||||
|  |  | ||||||
|          add_recipient(puf, len, sdata, state, data, cfg); |          add_recipient(puf, len, sdata, state, data, cfg); | ||||||
|       } |       } | ||||||
|       else if(state->message_state == MSG_BODY && len >= (unsigned int)(cfg->min_word_len) && state->bodylen < BIGBUFSIZE-len-1){ |       else if(state->message_state == MSG_BODY && len >= (unsigned int)(cfg->min_word_len) && state->bodylen < BIGBUFSIZE-len-1){ | ||||||
|   | |||||||
| @@ -15,13 +15,14 @@ case1() { | |||||||
|    "$SMTP_SOURCE_PROG" -s $SMTP_HOST -r archive@cust1.acts.hu -p 25 -t 20 --dir "$EML_DIR/spam2" --socket --no-counter |    "$SMTP_SOURCE_PROG" -s $SMTP_HOST -r archive@cust1.acts.hu -p 25 -t 20 --dir "$EML_DIR/spam2" --socket --no-counter | ||||||
|    "$SMTP_SOURCE_PROG" -s $SMTP_HOST -r archive@cust1.acts.hu -p 25 -t 20 --dir "$EML_DIR/journal" --socket --no-counter |    "$SMTP_SOURCE_PROG" -s $SMTP_HOST -r archive@cust1.acts.hu -p 25 -t 20 --dir "$EML_DIR/journal" --socket --no-counter | ||||||
|    "$SMTP_SOURCE_PROG" -s $SMTP_HOST -r archive@cust1.acts.hu -p 25 -t 20 --dir "$EML_DIR/deduptest" --socket --no-counter |    "$SMTP_SOURCE_PROG" -s $SMTP_HOST -r archive@cust1.acts.hu -p 25 -t 20 --dir "$EML_DIR/deduptest" --socket --no-counter | ||||||
|  |    "$SMTP_SOURCE_PROG" -s $SMTP_HOST -r archive@cust1.acts.hu -p 25 -t 20 --dir "$EML_DIR/special" --socket --no-counter | ||||||
|    "$SMTP_SOURCE_PROG" -s $SMTP_HOST -r archive@cust1.acts.hu extra@addr.ess another@extra.addr -p 25 -t 20 --dir "$EML_DIR/virus" --socket --no-counter |    "$SMTP_SOURCE_PROG" -s $SMTP_HOST -r archive@cust1.acts.hu extra@addr.ess another@extra.addr -p 25 -t 20 --dir "$EML_DIR/virus" --socket --no-counter | ||||||
|  |  | ||||||
|  |  | ||||||
|    wait_until_emails_are_processed "piler1" 3007 |    wait_until_emails_are_processed "piler1" 3018 | ||||||
|    docker exec "piler1" su piler -c /usr/libexec/piler/indexer.delta.sh 2>/dev/null |    docker exec "piler1" su piler -c /usr/libexec/piler/indexer.delta.sh 2>/dev/null | ||||||
|  |  | ||||||
|    count_status_values 3007 2896 111 0 |    count_status_values 3018 2907 111 0 | ||||||
|  |  | ||||||
|    test_retrieved_messages_are_the_same "piler1" "piler" |    test_retrieved_messages_are_the_same "piler1" "piler" | ||||||
|  |  | ||||||
|   | |||||||
| @@ -13,6 +13,13 @@ setup() { | |||||||
|    add_data_officer "piler1" |    add_data_officer "piler1" | ||||||
| } | } | ||||||
|  |  | ||||||
|  | cleanup_package() { | ||||||
|  |    local pkg="$1" | ||||||
|  |  | ||||||
|  |    log "Removing ${PACKAGE_DIR}/${pkg}" | ||||||
|  |    rm -f "${PACKAGE_DIR}/${pkg}" | ||||||
|  | } | ||||||
|  |  | ||||||
| launch_containers() { | launch_containers() { | ||||||
|  |  | ||||||
|    log "starting syslog server" |    log "starting syslog server" | ||||||
| @@ -28,12 +35,14 @@ launch_containers() { | |||||||
|       "$docker_image" |       "$docker_image" | ||||||
|  |  | ||||||
|    wait_for_sleep_cycle_in_container "piler1" |    wait_for_sleep_cycle_in_container "piler1" | ||||||
|  |  | ||||||
|  |    cleanup_package "$PACKAGE" | ||||||
| } | } | ||||||
|  |  | ||||||
| create_rules() { | create_rules() { | ||||||
|    local container="$1" |    local container="$1" | ||||||
|  |  | ||||||
|    echo 'echo "insert into domain (domain, mapped) values(\"fictive.com\",\"fictive.com\"),(\"acts.hu\",\"acts.hu\"),(\"gtsce.com\",\"gtsce.com\"),(\"datanet.hu\",\"datanet.hu\"),(\"gtsdatanet.hu\",\"gtsdatanet.hu\"),(\"gts.hu\",\"gts.hu\"),(\"aaa.fu\",\"aaa.fu\")"| mysql --defaults-file=/etc/piler/.my.cnf piler' | docker exec -i "$container" sh |    echo 'echo "insert into domain (domain, mapped) values(\"fictive.com\",\"fictive.com\"),(\"address.com\",\"address.com\"),(\"acts.hu\",\"acts.hu\"),(\"gtsce.com\",\"gtsce.com\"),(\"datanet.hu\",\"datanet.hu\"),(\"gtsdatanet.hu\",\"gtsdatanet.hu\"),(\"gts.hu\",\"gts.hu\"),(\"aaa.fu\",\"aaa.fu\")"| mysql --defaults-file=/etc/piler/.my.cnf piler' | docker exec -i "$container" sh | ||||||
|  |  | ||||||
|    echo 'echo "insert into archiving_rule (subject) values (\"Android táblagép\")"| mysql --defaults-file=/etc/piler/.my.cnf piler'|docker exec -i "$container" sh |    echo 'echo "insert into archiving_rule (subject) values (\"Android táblagép\")"| mysql --defaults-file=/etc/piler/.my.cnf piler'|docker exec -i "$container" sh | ||||||
|    echo 'echo "insert into archiving_rule (\`from\`) values (\"@gmail.com\")"| mysql --defaults-file=/etc/piler/.my.cnf piler'|docker exec -i "$container" sh |    echo 'echo "insert into archiving_rule (\`from\`) values (\"@gmail.com\")"| mysql --defaults-file=/etc/piler/.my.cnf piler'|docker exec -i "$container" sh | ||||||
|   | |||||||
| @@ -39,7 +39,7 @@ static void test_parser(struct config *cfg){ | |||||||
|       {"18-spam-html-encoding.eml", "<list-435458392@mail.aaa.fu>", "a1 hitelcentrum kft Üveges szilvia a1hitelcentrum@t-online.hu a1hitelcentrum t online hu ", "t-online.hu", "postmaster postmaster@aaa.fu postmaster aaa fu ", "aaa.fu", "postmaster@aaa.fu postmaster aaa fu a1hitelcentrum@t-online.hu a1hitelcentrum t online hu ", "aaa.fu t-online.hu ", "", "TÁJÉKOZTATÁSVargay Péter", 0}, |       {"18-spam-html-encoding.eml", "<list-435458392@mail.aaa.fu>", "a1 hitelcentrum kft Üveges szilvia a1hitelcentrum@t-online.hu a1hitelcentrum t online hu ", "t-online.hu", "postmaster postmaster@aaa.fu postmaster aaa fu ", "aaa.fu", "postmaster@aaa.fu postmaster aaa fu a1hitelcentrum@t-online.hu a1hitelcentrum t online hu ", "aaa.fu t-online.hu ", "", "TÁJÉKOZTATÁSVargay Péter", 0}, | ||||||
|       {"19-pdf-attachment-bad-mime.eml", "<20100213$2b62e942$9cc2b$sxm@61-186.reverse.ukhost4u.com>", "jennifer - billing department billing@limitedsoftwareworld.com billing limitedsoftwareworld com ", "limitedsoftwareworld.com", "", "", "100000 100000@aaa.fu 100000 aaa fu ", "aaa.fu ", "", "Billing Summary for 100000, Processed on 2010-02-13 17:01:03", 1}, |       {"19-pdf-attachment-bad-mime.eml", "<20100213$2b62e942$9cc2b$sxm@61-186.reverse.ukhost4u.com>", "jennifer - billing department billing@limitedsoftwareworld.com billing limitedsoftwareworld com ", "limitedsoftwareworld.com", "", "", "100000 100000@aaa.fu 100000 aaa fu ", "aaa.fu ", "", "Billing Summary for 100000, Processed on 2010-02-13 17:01:03", 1}, | ||||||
|       {"20-pdf-attachment-bad-mime.eml", "<20100213$2b62e942$9cc2b$sxm@61-187.reverse.ukhost4u.com>", "jennifer - billing department billing@limitedsoftwareworld.com billing limitedsoftwareworld com ", "limitedsoftwareworld.com", "", "", "100000 100000@aaa.fu 100000 aaa fu ", "aaa.fu ", "", "Billing Summary for 100000, Processed on 2010-02-13 17:01:03", 1}, |       {"20-pdf-attachment-bad-mime.eml", "<20100213$2b62e942$9cc2b$sxm@61-187.reverse.ukhost4u.com>", "jennifer - billing department billing@limitedsoftwareworld.com billing limitedsoftwareworld com ", "limitedsoftwareworld.com", "", "", "100000 100000@aaa.fu 100000 aaa fu ", "aaa.fu ", "", "Billing Summary for 100000, Processed on 2010-02-13 17:01:03", 1}, | ||||||
|       {"21-register-tricky-urls.eml", "<E1IBifn-0001un-MD@admin4.theregister.co.uk>", "the register update-49363-08f0f768@list.theregister.co.uk update 49363 08f0f768 list theregister co uk ", "list.theregister.co.uk", "", "", "hello@mail.aaa.fu hello mail aaa fu ", "mail.aaa.fu ", "", "[sp@m] Reg Headlines Friday July 20", 0}, |       {"21-register-tricky-urls.eml", "<E1IBifn-0001un-MD@admin4.theregister.co.uk>", "the register update-49363-08f0f768@list.theregister.co.uk 30cbee0b0f411fcf170416fb9f996c6f update 49363 08f0f768 list theregister co uk ", "list.theregister.co.uk", "", "", "hello@mail.aaa.fu hello mail aaa fu ", "mail.aaa.fu ", "", "[sp@m] Reg Headlines Friday July 20", 0}, | ||||||
|       {"30-subject.eml", "<3660278814815884@pongr-fabd8067e>", "aaapsi.hu info@aaapsi.hu info aaapsi hu ", "aaapsi.hu", "", "", "hello@acts.hu hello acts hu ", "acts.hu ", "", "RE: hxx-ajajajaja.com_ Aaagágyi és kia ttt_webstat hiba", 0}, |       {"30-subject.eml", "<3660278814815884@pongr-fabd8067e>", "aaapsi.hu info@aaapsi.hu info aaapsi hu ", "aaapsi.hu", "", "", "hello@acts.hu hello acts hu ", "acts.hu ", "", "RE: hxx-ajajajaja.com_ Aaagágyi és kia ttt_webstat hiba", 0}, | ||||||
|       {"31-subject.eml", "<3660278814815884@pongr-fabd8067e>", "aaapsi.hu info@aaapsi.hu info aaapsi hu ", "aaapsi.hu", "", "", "hello@acts.hu hello acts hu ", "acts.hu ", "", "Re: stanhu \"domain not found\"-dal eldobja a @fohu-ra küldött leveleket...", 0}, |       {"31-subject.eml", "<3660278814815884@pongr-fabd8067e>", "aaapsi.hu info@aaapsi.hu info aaapsi hu ", "aaapsi.hu", "", "", "hello@acts.hu hello acts hu ", "acts.hu ", "", "Re: stanhu \"domain not found\"-dal eldobja a @fohu-ra küldött leveleket...", 0}, | ||||||
|       {"32-subject.eml", "<3660278814815884@pongr-fabd8067e>", "aaapsi.hu info@aaapsi.hu info aaapsi hu ", "aaapsi.hu", "", "", "hello@acts.hu hello acts hu ", "acts.hu ", "", "<GD-XXXX/1-2015> www.ujsag.hu new virtual host reg. --> Aaaaaaaaa", 0}, |       {"32-subject.eml", "<3660278814815884@pongr-fabd8067e>", "aaapsi.hu info@aaapsi.hu info aaapsi hu ", "aaapsi.hu", "", "", "hello@acts.hu hello acts hu ", "acts.hu ", "", "<GD-XXXX/1-2015> www.ujsag.hu new virtual host reg. --> Aaaaaaaaa", 0}, | ||||||
|   | |||||||
| @@ -9,9 +9,9 @@ create table if not exists `sph_counter` ( | |||||||
| create table if not exists `sph_index` ( | create table if not exists `sph_index` ( | ||||||
|   `id` bigint not null, |   `id` bigint not null, | ||||||
|   `from` tinyblob default null, |   `from` tinyblob default null, | ||||||
|   `to` text(8192) default null, |   `to` blob(8192) default null, | ||||||
|   `fromdomain` char(255) default null, |   `fromdomain` tinyblob default null, | ||||||
|   `todomain` text(512) default null, |   `todomain` blob(512) default null, | ||||||
|   `subject` blob(512) default null, |   `subject` blob(512) default null, | ||||||
|   `arrived` int unsigned not null, |   `arrived` int unsigned not null, | ||||||
|   `sent` int unsigned not null, |   `sent` int unsigned not null, | ||||||
| @@ -73,7 +73,7 @@ create index `rcpt_idx3` on `rcpt`(`todomain`); | |||||||
|  |  | ||||||
|  |  | ||||||
| drop view if exists `v_messages`; | drop view if exists `v_messages`; | ||||||
| create view `v_messages` AS select `metadata`.`id` AS `id`,`metadata`.`piler_id` AS `piler_id`,`metadata`.`from` AS `from`,`metadata`.`fromdomain` AS `fromdomain`,`rcpt`.`to` AS `to`,`rcpt`.`todomain` AS `todomain`,`metadata`.`subject` AS `subject`, `metadata`.`size` AS `size`, `metadata`.`direction` AS `direction`, `metadata`.`sent` AS `sent`, `metadata`.`retained` AS `retained`, `metadata`.`arrived` AS `arrived`, `metadata`.`digest` AS `digest`, `metadata`.`bodydigest` AS `bodydigest`, `metadata`.`deleted` AS `deleted` from (`metadata` join `rcpt`) where (`metadata`.`id` = `rcpt`.`id`); | create view `v_messages` AS select `metadata`.`id` AS `id`,`metadata`.`piler_id` AS `piler_id`,`metadata`.`from` AS `from`,`metadata`.`fromdomain` AS `fromdomain`,`rcpt`.`to` AS `to`,`rcpt`.`todomain` AS `todomain`,`metadata`.`subject` AS `subject`, `metadata`.`size` AS `size`, `metadata`.`direction` AS `direction`, `metadata`.`sent` AS `sent`, `metadata`.`retained` AS `retained`, `metadata`.`arrived` AS `arrived`, `metadata`.`digest` AS `digest`, `metadata`.`bodydigest` AS `bodydigest`, `metadata`.`deleted` AS `deleted`, `metadata`.`attachments` AS `attachments` from (`metadata` join `rcpt`) where (`metadata`.`id` = `rcpt`.`id`); | ||||||
|  |  | ||||||
|  |  | ||||||
| create table if not exists `attachment` ( | create table if not exists `attachment` ( | ||||||
| @@ -463,7 +463,7 @@ create table if not exists `timestamp` ( | |||||||
|   `id` bigint unsigned not null auto_increment, |   `id` bigint unsigned not null auto_increment, | ||||||
|   `start_id` bigint default 0, |   `start_id` bigint default 0, | ||||||
|   `stop_id` bigint default 0, |   `stop_id` bigint default 0, | ||||||
|   `hash_value` char(40), |   `hash_value` varchar(128), | ||||||
|   `count` int default 0, |   `count` int default 0, | ||||||
|   `response_time` bigint default 0, |   `response_time` bigint default 0, | ||||||
|   `response_string` blob not null, |   `response_string` blob not null, | ||||||
|   | |||||||
							
								
								
									
										8
									
								
								util/db-upgrade.sql
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								util/db-upgrade.sql
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,8 @@ | |||||||
|  | alter table timestamp change column hash_value hash_value varchar(128) default null; | ||||||
|  |  | ||||||
|  | alter table sph_index change column `to` `to` blob(8192) default null; | ||||||
|  | alter table sph_index change column fromdomain fromdomain tinyblob default null; | ||||||
|  | alter table sph_index change column todomain todomain blob(512) default null; | ||||||
|  |  | ||||||
|  |  | ||||||
|  | alter table metadata change column subject `subject` blob(512) default null; | ||||||
| @@ -103,7 +103,7 @@ function saveMessages($storage, $folder = '', $num = 0) { | |||||||
|  |  | ||||||
|    $messages = $storage->piler_batch_fetch(1, $num); |    $messages = $storage->piler_batch_fetch(1, $num); | ||||||
|  |  | ||||||
|    while(list($k, $v) = each($messages)) { |    foreach($messages as $k => $v) { | ||||||
|       $uuid = $storage->getUniqueId($k); |       $uuid = $storage->getUniqueId($k); | ||||||
|  |  | ||||||
|       $tmpname = "piler-" . $username . "-" . $folder . "-" . $k . "-" . $uuid . ".eml"; |       $tmpname = "piler-" . $username . "-" . $folder . "-" . $k . "-" . $uuid . ".eml"; | ||||||
|   | |||||||
| @@ -90,6 +90,7 @@ def main(): | |||||||
|                         default="/etc/piler/piler.conf") |                         default="/etc/piler/piler.conf") | ||||||
|     parser.add_argument("-s", "--server", type=str, help="imap server") |     parser.add_argument("-s", "--server", type=str, help="imap server") | ||||||
|     parser.add_argument("-P", "--port", type=int, help="port number", default=143) |     parser.add_argument("-P", "--port", type=int, help="port number", default=143) | ||||||
|  |     parser.add_argument("--no_ssl", help="Do not use ssl/tls", action='store_true') | ||||||
|     parser.add_argument("-u", "--user", type=str, help="imap user") |     parser.add_argument("-u", "--user", type=str, help="imap user") | ||||||
|     parser.add_argument("-p", "--password", type=str, help="imap password") |     parser.add_argument("-p", "--password", type=str, help="imap password") | ||||||
|     parser.add_argument("-x", "--skip-list", type=str, help="IMAP folders to skip", |     parser.add_argument("-x", "--skip-list", type=str, help="IMAP folders to skip", | ||||||
| @@ -116,12 +117,16 @@ def main(): | |||||||
|     opts['verbose'] = args.verbose |     opts['verbose'] = args.verbose | ||||||
|     opts['search'] = 'ALL' |     opts['search'] = 'ALL' | ||||||
|     opts['counter'] = 0 |     opts['counter'] = 0 | ||||||
|  |     opts['use_ssl'] = True | ||||||
|     opts['db'] = None |     opts['db'] = None | ||||||
|     opts['id'] = 0 |     opts['id'] = 0 | ||||||
|  |  | ||||||
|     if args.date: |     if args.date: | ||||||
|         opts['search'] = args.date |         opts['search'] = args.date | ||||||
|  |  | ||||||
|  |     if args.no_ssl: | ||||||
|  |         opts['use_ssl'] = False | ||||||
|  |  | ||||||
|     server = '' |     server = '' | ||||||
|     user = '' |     user = '' | ||||||
|     password = '' |     password = '' | ||||||
| @@ -152,7 +157,7 @@ def main(): | |||||||
|     if opts['verbose']: |     if opts['verbose']: | ||||||
|         print("Skipped folder list: {}".format(opts['skip_folders'])) |         print("Skipped folder list: {}".format(opts['skip_folders'])) | ||||||
|  |  | ||||||
|     if args.port == 993: |     if opts['use_ssl']: | ||||||
|         conn = imaplib.IMAP4_SSL(server) |         conn = imaplib.IMAP4_SSL(server) | ||||||
|     else: |     else: | ||||||
|         conn = imaplib.IMAP4(server) |         conn = imaplib.IMAP4(server) | ||||||
|   | |||||||
| @@ -54,12 +54,26 @@ def purge_m_files(ids=[], opts={}): | |||||||
|         remove_m_files(ids, opts) |         remove_m_files(ids, opts) | ||||||
|  |  | ||||||
|         # Set deleted=1 for aged metadata entries |         # Set deleted=1 for aged metadata entries | ||||||
|  |         # as well as clean other tables | ||||||
|  |  | ||||||
|         if opts['dry_run'] is False: |         if opts['dry_run'] is False: | ||||||
|             cursor = opts['db'].cursor() |             cursor = opts['db'].cursor() | ||||||
|             format = ", ".join(['%s'] * len(ids)) |             format = ", ".join(['%s'] * len(ids)) | ||||||
|             cursor.execute("UPDATE metadata SET deleted=1 WHERE piler_id IN " + |             cursor.execute("UPDATE metadata SET deleted=1, subject=NULL, `from`=''," + | ||||||
|  |                            "fromdomain='', message_id='' WHERE piler_id IN " + | ||||||
|                            "(%s)" % (format), ids) |                            "(%s)" % (format), ids) | ||||||
|  |  | ||||||
|  |             cursor.execute("DELETE FROM rcpt WHERE id IN (SELECT id FROM metadata " + | ||||||
|  |                            "WHERE piler_id IN (%s))" % (format), ids) | ||||||
|  |             cursor.execute("DELETE FROM note WHERE id IN (SELECT id FROM metadata " + | ||||||
|  |                            "WHERE piler_id IN (%s))" % (format), ids) | ||||||
|  |             cursor.execute("DELETE FROM tag WHERE id IN (SELECT id FROM metadata " + | ||||||
|  |                            "WHERE piler_id IN (%s))" % (format), ids) | ||||||
|  |             cursor.execute("DELETE FROM private WHERE id IN (SELECT id FROM metadata" + | ||||||
|  |                            "WHERE piler_id IN (%s))" % (format), ids) | ||||||
|  |             cursor.execute("DELETE FROM folder_message WHERE id IN (SELECT id FROM " + | ||||||
|  |                            "metadata WHERE piler_id IN (%s))" % (format), ids) | ||||||
|  |  | ||||||
|             opts['db'].commit() |             opts['db'].commit() | ||||||
|  |  | ||||||
|  |  | ||||||
| @@ -85,7 +99,7 @@ def purge_attachments_by_attachment_id(opts={}): | |||||||
|     cursor = opts['db'].cursor() |     cursor = opts['db'].cursor() | ||||||
|  |  | ||||||
|     cursor.execute("SELECT i, piler_id, attachment_id, refcount FROM " + |     cursor.execute("SELECT i, piler_id, attachment_id, refcount FROM " + | ||||||
|                    "v_attachment WHERE i IN (%s)" % |                    "v_attachment WHERE refcount=0 AND i IN (%s)" % | ||||||
|                    (format), opts['referenced_attachments']) |                    (format), opts['referenced_attachments']) | ||||||
|  |  | ||||||
|     while True: |     while True: | ||||||
| @@ -160,12 +174,12 @@ def unlink(filename="", opts={}): | |||||||
|  |  | ||||||
|  |  | ||||||
| def get_m_file_path(id='', opts={}): | def get_m_file_path(id='', opts={}): | ||||||
|     return "/".join([opts['storedir'], opts['server_id'], id[8:11], id[32:34], |     return "/".join([opts['storedir'], id[24:26], id[8:11], id[32:34], | ||||||
|                     id[34:36], id + ".m"]) |                     id[34:36], id + ".m"]) | ||||||
|  |  | ||||||
|  |  | ||||||
| def get_attachment_file_path(piler_id='', attachment_id=0, opts={}): | def get_attachment_file_path(piler_id='', attachment_id=0, opts={}): | ||||||
|     return "/".join([opts['storedir'], opts['server_id'], piler_id[8:11], |     return "/".join([opts['storedir'], piler_id[24:26], piler_id[8:11], | ||||||
|                     piler_id[32:34], piler_id[34:36], piler_id + ".a" + |                     piler_id[32:34], piler_id[34:36], piler_id + ".a" + | ||||||
|                     str(attachment_id)]) |                     str(attachment_id)]) | ||||||
|  |  | ||||||
|   | |||||||
| @@ -286,6 +286,7 @@ make_cron_entries() { | |||||||
|       echo "30   6 * * * /usr/bin/php ${LIBEXECDIR}/piler/generate_stats.php --webui ${DOCROOT} >/dev/null"; |       echo "30   6 * * * /usr/bin/php ${LIBEXECDIR}/piler/generate_stats.php --webui ${DOCROOT} >/dev/null"; | ||||||
|       echo "*/5 * * * * /usr/bin/find ${LOCALSTATEDIR}/piler/error -type f|wc -l > ${LOCALSTATEDIR}/piler/stat/error"; |       echo "*/5 * * * * /usr/bin/find ${LOCALSTATEDIR}/piler/error -type f|wc -l > ${LOCALSTATEDIR}/piler/stat/error"; | ||||||
|       echo "*/5 * * * * /usr/bin/find ${DOCROOT}/tmp -type f -name i.\* -exec rm -f {} \;"; |       echo "*/5 * * * * /usr/bin/find ${DOCROOT}/tmp -type f -name i.\* -exec rm -f {} \;"; | ||||||
|  |       echo "#*/5 * * * * ${LIBEXECDIR}/piler/import.sh"; | ||||||
|       echo "### PILEREND"; |       echo "### PILEREND"; | ||||||
|    } >> "$CRON_TMP" |    } >> "$CRON_TMP" | ||||||
| } | } | ||||||
|   | |||||||
							
								
								
									
										23
									
								
								util/reindex.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										23
									
								
								util/reindex.sh
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,23 @@ | |||||||
|  | #!/bin/bash | ||||||
|  |  | ||||||
|  | set -o nounset | ||||||
|  | set -o errexit | ||||||
|  | set -o pipefail | ||||||
|  |  | ||||||
|  | INSTALL_PREFIX=/usr/local | ||||||
|  | THRESHOLD=100000000 | ||||||
|  |  | ||||||
|  | start_id=1 | ||||||
|  | stop_id=5000000 | ||||||
|  |  | ||||||
|  | while [[ $start_id -lt $stop_id ]]; do | ||||||
|  |    y=$(( start_id + 9999 )) | ||||||
|  |    echo $start_id $y | ||||||
|  |    "${INSTALL_PREFIX}/bin/reindex" -f $start_id -t $y -p | ||||||
|  |    "${INSTALL_PREFIX}/libexec/piler/indexer.delta.sh" | ||||||
|  |    start_id=$(( start_id + 10000 )) | ||||||
|  |  | ||||||
|  |    if [[ "$(stat -c %s /var/piler/sphinx/dailydelta1.spp)" -gt "$THRESHOLD" ]]; then | ||||||
|  |       "${INSTALL_PREFIX}/libexec/piler/indexer.main.sh" | ||||||
|  |    fi | ||||||
|  | done | ||||||
| @@ -12,11 +12,13 @@ ini_set("session.save_path", "/tmp"); | |||||||
| $webuidir = ""; | $webuidir = ""; | ||||||
| $verbose = 0; | $verbose = 0; | ||||||
| $mode = "unit"; | $mode = "unit"; | ||||||
|  | $algo = "sha256"; | ||||||
|  |  | ||||||
| $opts = 'h::v'; | $opts = 'h::v'; | ||||||
| $lopts = array( | $lopts = array( | ||||||
|     'webui:', |     'webui:', | ||||||
|     'mode:', |     'mode:', | ||||||
|  |     'algo:', | ||||||
|     'verbose' |     'verbose' | ||||||
|     ); |     ); | ||||||
|  |  | ||||||
| @@ -37,6 +39,10 @@ if ( $options = getopt( $opts, $lopts ) ) | |||||||
|        $mode = $options['mode']; |        $mode = $options['mode']; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     if ( isset($options['algo']) ) { | ||||||
|  |        $algo = $options['algo']; | ||||||
|  |     } | ||||||
|  |  | ||||||
|     if ( isset($options['h']) ) |     if ( isset($options['h']) ) | ||||||
|     { |     { | ||||||
|         display_help(); |         display_help(); | ||||||
| @@ -66,6 +72,7 @@ Registry::set('db', $db); | |||||||
| Registry::set('DB_DRIVER', DB_DRIVER); | Registry::set('DB_DRIVER', DB_DRIVER); | ||||||
|  |  | ||||||
| define('MODE', $mode); | define('MODE', $mode); | ||||||
|  | define('ALGO', $algo); | ||||||
|  |  | ||||||
|  |  | ||||||
| $data = get_hash_values(); | $data = get_hash_values(); | ||||||
| @@ -121,29 +128,29 @@ function get_hash_values() { | |||||||
|  |  | ||||||
|    if($last_id == 0) { |    if($last_id == 0) { | ||||||
|       $start_id = TSA_START_ID; |       $start_id = TSA_START_ID; | ||||||
|       if(MODE == 'unit') { $stop_id = $start_id + TSA_STAMP_REQUEST_UNIT_SIZE - 1; } |    } else { | ||||||
|       else { $stop_id = 1000000000; } |  | ||||||
|    } |  | ||||||
|    else { |  | ||||||
|       $start_id = $last_id + 1; |       $start_id = $last_id + 1; | ||||||
|       if(MODE == 'unit') { $stop_id = $start_id + TSA_STAMP_REQUEST_UNIT_SIZE - 1; } |  | ||||||
|       else { $stop_id = 1000000000; } |  | ||||||
|    } |    } | ||||||
|  |  | ||||||
|    $query = $db->query("SELECT id, digest FROM " . TABLE_META . " WHERE id >= ? AND id <= ?", array($start_id, $stop_id)); |    if(MODE == 'unit') { | ||||||
|  |       $limit = TSA_STAMP_REQUEST_UNIT_SIZE; | ||||||
|  |    } else { | ||||||
|  |       $limit = 100000; // stay well below default PHP memory_limit | ||||||
|  |    } | ||||||
|  |  | ||||||
|  |    $query = $db->query("SELECT id, digest FROM " . TABLE_META . " WHERE id >= ? ORDER BY id LIMIT $limit", array($start_id)); | ||||||
|  |  | ||||||
|    foreach($query->rows as $q) { |    foreach($query->rows as $q) { | ||||||
|       $count++; |       $count++; | ||||||
|  |       $last_id = $q['id']; | ||||||
|       $s .= $q['digest']; |       $s .= $q['digest']; | ||||||
|    } |    } | ||||||
|  |  | ||||||
|    if(MODE == 'time') { $stop_id = $start_id + $count - 1; } |  | ||||||
|  |  | ||||||
|    return [ |    return [ | ||||||
|       START_ID => $start_id, |       START_ID => $start_id, | ||||||
|       STOP_ID => $stop_id, |       STOP_ID => $last_id, | ||||||
|       COUNT => $count, |       COUNT => $count, | ||||||
|       HASH_VALUE => sha1($s) |       HASH_VALUE => hash(ALGO, $s) | ||||||
|    ]; |    ]; | ||||||
|  |  | ||||||
| } | } | ||||||
|   | |||||||
| @@ -410,7 +410,7 @@ class Zend_Mail_Protocol_Imap | |||||||
|  |  | ||||||
|        $a = $this->requestAndResponse("LIST", array('""', '"*"')); |        $a = $this->requestAndResponse("LIST", array('""', '"*"')); | ||||||
|  |  | ||||||
|        while(list($k, $v) = each($a)) { |        foreach ($a as $k => $v) { | ||||||
|           if($v[1][0] == '\HasNoChildren') { |           if($v[1][0] == '\HasNoChildren') { | ||||||
|              array_push($folders, $v[3]); |              array_push($folders, $v[3]); | ||||||
|           } |           } | ||||||
|   | |||||||
| @@ -99,7 +99,7 @@ class ControllerAuditHelper extends Controller { | |||||||
|       $s = preg_replace("/\s{1,}/", " ", $s); |       $s = preg_replace("/\s{1,}/", " ", $s); | ||||||
|       $b = explode(" ", $s); |       $b = explode(" ", $s); | ||||||
|  |  | ||||||
|       while(list($k, $v) = each($b)) { |       foreach ($b as $k => $v) { | ||||||
|          if($v == '') { continue; } |          if($v == '') { continue; } | ||||||
|  |  | ||||||
|          if(preg_match("/(login|loginfailed|logout|view|download|search|restore|journal)$/", $v) && isset($actions[$v])) { $this->a['action'] .= "\t" . $actions[$v]; } |          if(preg_match("/(login|loginfailed|logout|view|download|search|restore|journal)$/", $v) && isset($actions[$v])) { $this->a['action'] .= "\t" . $actions[$v]; } | ||||||
|   | |||||||
| @@ -140,7 +140,7 @@ class ControllerSearchHelper extends Controller { | |||||||
|       $s = preg_replace("/OR/", "|", $data['search']); |       $s = preg_replace("/OR/", "|", $data['search']); | ||||||
|       $b = preg_split("/\s/", $s); |       $b = preg_split("/\s/", $s); | ||||||
|  |  | ||||||
|       while(list($k, $v) = each($b)) { |       foreach ($b as $k => $v) { | ||||||
|          if($v == '') { continue; } |          if($v == '') { continue; } | ||||||
|  |  | ||||||
|          if(preg_match("/\d{4}\-\d{1,2}\-\d{1,2}/", $v) || preg_match("/\d{1,2}\/\d{1,2}\/\d{4}/", $v)) { |          if(preg_match("/\d{4}\-\d{1,2}\-\d{1,2}/", $v) || preg_match("/\d{1,2}\/\d{1,2}\/\d{4}/", $v)) { | ||||||
|   | |||||||
| @@ -79,7 +79,7 @@ class ControllerUserEdit extends Controller { | |||||||
|  |  | ||||||
|             $this->data['emails'] = $this->model_user_user->get_emails($this->data['user']['username']); |             $this->data['emails'] = $this->model_user_user->get_emails($this->data['user']['username']); | ||||||
|  |  | ||||||
|             $this->data['user']['group'] = $this->model_group_group->get_groups_by_email(array($this->data['emails'])); |             $this->data['user']['group'] = $this->model_group_group->get_groups_by_email(explode("\n", $this->data['emails'])); | ||||||
|          //} |          //} | ||||||
|       } |       } | ||||||
|       else { |       else { | ||||||
|   | |||||||
| @@ -55,7 +55,7 @@ class apiUtils { | |||||||
|     $strlenVar = strlen($str); |     $strlenVar = strlen($str); | ||||||
|     $d = $ret = 0; |     $d = $ret = 0; | ||||||
|     for ($count = 0; $count < $strlenVar; ++ $count) { |     for ($count = 0; $count < $strlenVar; ++ $count) { | ||||||
|       $ordinalValue = ord($str{$ret}); |       $ordinalValue = ord($str[$ret]); | ||||||
|       switch (true) { |       switch (true) { | ||||||
|         case (($ordinalValue >= 0x20) && ($ordinalValue <= 0x7F)): |         case (($ordinalValue >= 0x20) && ($ordinalValue <= 0x7F)): | ||||||
|           // characters U-00000000 - U-0000007F (same as ASCII) |           // characters U-00000000 - U-0000007F (same as ASCII) | ||||||
| @@ -114,4 +114,4 @@ class apiUtils { | |||||||
|     } |     } | ||||||
|     return $normalized; |     return $normalized; | ||||||
|   } |   } | ||||||
| } | } | ||||||
|   | |||||||
							
								
								
									
										497
									
								
								webui/language/cn/messages.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										497
									
								
								webui/language/cn/messages.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,497 @@ | |||||||
|  | <?php | ||||||
|  |  | ||||||
|  | $_['text_60_minutes'] = "60 分钟"; | ||||||
|  |  | ||||||
|  | $_['text_action'] = "动作"; | ||||||
|  | $_['text_active_incoming_queue'] = "活动 + 传入队列"; | ||||||
|  | $_['text_active_incoming_queue_sender'] = "活动 + 传入队列与发件人"; | ||||||
|  | $_['text_ad_sync_status'] = "AD 同步状态"; | ||||||
|  | $_['text_add'] = "新增"; | ||||||
|  | $_['text_add_new_email_address'] = "新增邮件地址"; | ||||||
|  | $_['text_add_new_domain'] = "新增域名"; | ||||||
|  | $_['text_add_new_entry'] = "新增条目"; | ||||||
|  | $_['text_add_new_group'] = "新增组"; | ||||||
|  | $_['text_add_new_rule'] = "新增规则"; | ||||||
|  | $_['text_add_new_user_alias'] = "新增用户"; | ||||||
|  | $_['text_add_policy'] = "新增策略"; | ||||||
|  | $_['text_administration'] = "管理"; | ||||||
|  | $_['text_admin_user'] = "管理员"; | ||||||
|  | $_['text_advanced'] = "高级"; | ||||||
|  | $_['text_advanced_search'] = "高级搜索"; | ||||||
|  | $_['text_all'] = "所有"; | ||||||
|  | $_['text_any'] = "任一"; | ||||||
|  | $_['text_applied'] = "已套用"; | ||||||
|  | $_['text_apply_changes'] = "套用变更"; | ||||||
|  | $_['text_archive_size'] = "归档大小"; | ||||||
|  | $_['text_archive_size_before_compression'] = "Archive size before compression"; | ||||||
|  | $_['text_archived_messages'] = "已归档邮件"; | ||||||
|  | $_['text_archiving_rules'] = "归档规则"; | ||||||
|  | $_['text_assigned_email_addresses'] = "已指派邮件地址"; | ||||||
|  | $_['text_attachment'] = "附件"; | ||||||
|  | $_['text_attachment_name'] = "附件名称"; | ||||||
|  | $_['text_attachment_size'] = "附件大小"; | ||||||
|  | $_['text_attachment_type'] = "附件类型"; | ||||||
|  | $_['text_audit'] = "审计"; | ||||||
|  | $_['text_automated_search'] = "自动搜索"; | ||||||
|  |  | ||||||
|  | $_['text_back'] = "返回"; | ||||||
|  | $_['text_background_colour'] = "背景颜色"; | ||||||
|  | $_['text_body'] = "内文"; | ||||||
|  | $_['text_branding_logo'] = "品牌标志"; | ||||||
|  | $_['text_branding_text'] = "品牌文字"; | ||||||
|  | $_['text_branding_url'] = "品牌网址"; | ||||||
|  | $_['text_bulk_edit_selected_uids'] = "批次修改已选取的 uid"; | ||||||
|  | $_['text_bulk_restore_selected_emails'] = "批次还原已选取的項目"; | ||||||
|  | $_['text_bulk_update_selected_uids'] = "批次更新已选择的 uid"; | ||||||
|  |  | ||||||
|  | $_['text_cancel'] = "取消"; | ||||||
|  | $_['text_change_user_settings'] = "变更用户设定"; | ||||||
|  | $_['text_clienthost'] = "Client host"; | ||||||
|  | $_['text_close'] = "关闭"; | ||||||
|  | $_['text_colour'] = "颜色"; | ||||||
|  | $_['text_compressed'] = "已压缩"; | ||||||
|  | $_['text_confirm_to_reset_counters'] = "确认要重置计数器"; | ||||||
|  | $_['text_connection_failed'] = "连接失败"; | ||||||
|  | $_['text_connection_ok'] = "连接成功"; | ||||||
|  | $_['text_contact_support'] = "联系支持"; | ||||||
|  | $_['text_content_filter'] = "内容过滤器"; | ||||||
|  | $_['text_conversation_available'] = "可使用对话查看"; | ||||||
|  | $_['text_copied'] = "Copied"; | ||||||
|  | $_['text_counters'] = "计数器"; | ||||||
|  | $_['text_cpu_load'] = "CPU 负载"; | ||||||
|  | $_['text_cpu_usage'] = "CPU 使用率"; | ||||||
|  | $_['text_create_new_secret'] = "建立新的密钥"; | ||||||
|  | $_['text_create_note'] = "创建注释"; | ||||||
|  | $_['text_cumulative_counts'] = "累积计数"; | ||||||
|  | $_['text_customers'] = "Customers"; | ||||||
|  |  | ||||||
|  | $_['text_daily_quarantine_report'] = "每日隔离报表"; | ||||||
|  | $_['text_daily_quarantine_report_status'] = "每日隔离报表状态"; | ||||||
|  | $_['text_daily_report'] = "每日报表"; | ||||||
|  | $_['text_daily_piler_report'] = "每日 Piler 报表"; | ||||||
|  | $_['text_database_emails'] = "在 piler 资料库的邮件地址"; | ||||||
|  | $_['text_date'] = "日期"; | ||||||
|  | $_['text_date_from'] = "起始日期"; | ||||||
|  | $_['text_date_to'] = "结束日期"; | ||||||
|  | $_['text_days'] = "天"; | ||||||
|  | $_['text_days2'] = "天"; | ||||||
|  | $_['text_days_to_retain'] = "保留天数"; | ||||||
|  | $_['text_deferred_queue'] = "延迟队列"; | ||||||
|  | $_['text_deferred_queue_sender'] = "延迟队列与发件人"; | ||||||
|  | $_['text_delay'] = "延迟"; | ||||||
|  | $_['text_delete_confirm_message'] = "您是否要删除"; | ||||||
|  | $_['text_delete_reason'] = "移除原因"; | ||||||
|  | $_['text_deleted'] = "已删除"; | ||||||
|  | $_['text_deleted_users'] = "已删除"; | ||||||
|  | $_['text_deliver'] = "传递"; | ||||||
|  | $_['text_delivered'] = "已传递"; | ||||||
|  | $_['text_deliver_and_train_selected_messages'] = "Deliver and train selected messages"; | ||||||
|  | $_['text_deliver_and_train_selected_messages_as_ham'] = "Deliver and train selected messages AS HAM"; | ||||||
|  | $_['text_deliver_selected_messages'] = "传递已选择的邮件"; | ||||||
|  | $_['text_description'] = "描述"; | ||||||
|  | $_['text_direction'] = "Direction"; | ||||||
|  | $_['text_disk_usage'] = "磁盘使用率"; | ||||||
|  | $_['text_disable'] = "停用"; | ||||||
|  | $_['text_disabled'] = "停用"; | ||||||
|  | $_['text_dn_asterisk_means_skip_sync'] = "万用字元 (*) 表示这个用户项目将不会包含在 AD 同步当中"; | ||||||
|  | $_['text_domain'] = "域"; | ||||||
|  | $_['text_domains'] = "域"; | ||||||
|  | $_['text_domainname'] = "域名称"; | ||||||
|  | $_['text_download_all_hits_as_eml'] = "全部下载 (EML)"; | ||||||
|  | $_['text_download_selected_hits_as_pdf'] = "下载已选取项目 (PDF)"; | ||||||
|  | $_['text_download_attachment2'] = "下载附件"; | ||||||
|  | $_['text_download_message'] = "下載 (EML)"; | ||||||
|  | $_['text_download_message2'] = "下载邮件"; | ||||||
|  |  | ||||||
|  | $_['text_edit'] = "编辑"; | ||||||
|  | $_['text_edit_entry'] = "编辑条目"; | ||||||
|  | $_['text_edit_group'] = "编辑组"; | ||||||
|  | $_['text_edit_user'] = "编辑用户"; | ||||||
|  | $_['text_edit_or_view'] = "编辑/查看"; | ||||||
|  | $_['text_email'] = "邮件地址"; | ||||||
|  | $_['text_email_addresses'] = "邮件地址"; | ||||||
|  | $_['text_email_aliases'] = "邮件别名"; | ||||||
|  | $_['text_email_in_unknown_domain'] = "邮件地址在未知的域"; | ||||||
|  | $_['text_empty_search_criteria'] = "'Empty criteria'"; | ||||||
|  | $_['text_empty_search_result'] = "没有搜寻结果。请尝试加入万用字元 (*) 在关键字后方 (最小 " . MIN_PREFIX_LEN . " 个字元),例如 duplic* 以搜索到 \"duplicate\", \"duplicated\", 之类的结果。"; | ||||||
|  | $_['text_enable'] = "启用"; | ||||||
|  | $_['text_enabled'] = "启用"; | ||||||
|  | $_['text_enter_google_authenticator_code'] = "输入 Google Authenticator 验证码"; | ||||||
|  | $_['text_enter_one_email_address_per_line'] = "每一行输入一个邮件地址"; | ||||||
|  | $_['text_enter_one_group_per_line'] = "每一行输入一个群组"; | ||||||
|  | $_['text_enter_search_terms'] = "输入您要搜索的字词"; | ||||||
|  | $_['text_error'] = "错误"; | ||||||
|  | $_['text_exact_domain_name_or_email_address'] = "确认您的域名或邮件地址"; | ||||||
|  | $_['text_exclude'] = "排除"; | ||||||
|  | $_['text_existing'] = "现有"; | ||||||
|  | $_['text_existing_domains'] = "现有域"; | ||||||
|  | $_['text_existing_email'] = "现有邮件"; | ||||||
|  | $_['text_existing_folders'] = "现有资料夹"; | ||||||
|  | $_['text_existing_groups'] = "现有组"; | ||||||
|  | $_['text_existing_policies'] = "现有策略"; | ||||||
|  | $_['text_existing_entries'] = "现有条目"; | ||||||
|  | $_['text_existing_rules'] = "现有规则"; | ||||||
|  | $_['text_existing_user'] = "现有用户"; | ||||||
|  | $_['text_existing_users'] = "现有用户"; | ||||||
|  | $_['text_expert'] = "专家"; | ||||||
|  | $_['text_expert_search'] = "专家搜索"; | ||||||
|  |  | ||||||
|  | $_['text_failed'] = "失败"; | ||||||
|  | $_['text_failed_to_add'] = "新增失败"; | ||||||
|  | $_['text_failed_to_change_password'] = "变更密码失败"; | ||||||
|  | $_['text_failed_to_deliver'] = "传递失败"; | ||||||
|  | $_['text_failed_to_mark_for_removal'] = "标记移除失败"; | ||||||
|  | $_['text_failed_to_modify'] = "修改失败"; | ||||||
|  | $_['text_failed_to_remove'] = "移除失败"; | ||||||
|  | $_['text_failed_to_restore'] = "还原失败"; | ||||||
|  | $_['text_failed_to_update'] = "更新失败"; | ||||||
|  | $_['text_first'] = "First"; | ||||||
|  | $_['text_folder'] = "文件夹"; | ||||||
|  | $_['text_folder_rules'] = "文件夹规则"; | ||||||
|  | $_['text_folders'] = "文件夹"; | ||||||
|  | $_['text_forward_selected_emails_to'] = "转寄已选择邮件至"; | ||||||
|  | $_['text_from'] = "发件人"; | ||||||
|  | $_['text_from_domain'] = "发件人域"; | ||||||
|  |  | ||||||
|  | $_['text_google_authenticator_code'] = "Google Authenticator 验证码"; | ||||||
|  | $_['text_google_authenticator_settings'] = "Google Authenticator 设定"; | ||||||
|  | $_['text_group_id'] = "组 id"; | ||||||
|  | $_['text_groupname'] = "组名称"; | ||||||
|  | $_['text_groups'] = "组"; | ||||||
|  | $_['text_group_management'] = "组管理"; | ||||||
|  | $_['text_group_membership'] = "组成员"; | ||||||
|  |  | ||||||
|  | $_['text_health'] = "健康状况"; | ||||||
|  | $_['text_health_monitor'] = "健康状况监视器"; | ||||||
|  | $_['text_help'] = "帮助"; | ||||||
|  | $_['text_history'] = "历史"; | ||||||
|  | $_['text_home'] = "首页"; | ||||||
|  |  | ||||||
|  | $_['text_image'] = "image"; | ||||||
|  | $_['text_import'] = "汇入"; | ||||||
|  | $_['text_import_job_delete_confirm_message'] = "您是否要删除汇入作业"; | ||||||
|  | $_['text_import_users'] = "汇入用户"; | ||||||
|  | $_['text_import_users_from_LDAP'] = "从 LDAP 汇入用户"; | ||||||
|  | $_['text_inbound'] = "inbound"; | ||||||
|  | $_['text_indexer_job'] = "索引器作业"; | ||||||
|  | $_['text_install_sudo_apply'] = "加入以下内容到 /etc/sudoers: 'www-data ALL=NOPASSWD: /etc/init.d/rc.piler reload'"; | ||||||
|  | $_['text_internal'] = "internal"; | ||||||
|  | $_['text_invalid_data'] = "无效的资料"; | ||||||
|  | $_['text_invalid_email'] = "无效的邮件"; | ||||||
|  | $_['text_invalid_email_or_password'] = "无效的邮件或密码"; | ||||||
|  | $_['text_invalid_gid'] = "无效的 gid"; | ||||||
|  | $_['text_invalid_password'] = "无效的密码"; | ||||||
|  | $_['text_invalid_pin_code'] = "无效的 Pin 码"; | ||||||
|  | $_['text_invalid_policy_group'] = "无效的策略组"; | ||||||
|  | $_['text_invalid_policy_name'] = "无效的策略名称"; | ||||||
|  | $_['text_invalid_policy_setting'] = "无效的策略设定"; | ||||||
|  | $_['text_invalid_uid'] = "无效的 uid"; | ||||||
|  | $_['text_invalid_username'] = "无效的用户名称"; | ||||||
|  | $_['text_ipaddr'] = "IP 位址"; | ||||||
|  |  | ||||||
|  | $_['text_language'] = "语言"; | ||||||
|  | $_['text_last'] = "Last"; | ||||||
|  | $_['text_last_activity'] = "最后活动"; | ||||||
|  | $_['text_last_update'] = "最后更新"; | ||||||
|  | $_['text_latest_emails'] = "最新邮件"; | ||||||
|  | $_['text_ldap'] = "LDAP"; | ||||||
|  | $_['text_ldap_auditor_member_dn'] = "审计成员 DN"; | ||||||
|  | $_['text_ldap_base_dn'] = "LDAP 基础 DN"; | ||||||
|  | $_['text_ldap_bind_dn'] = "LDAP 绑定 DN"; | ||||||
|  | $_['text_ldap_bind_pw'] = "LDAP 绑定 密码"; | ||||||
|  | $_['text_ldap_host'] = "LDAP 主机"; | ||||||
|  | $_['text_ldap_type'] = "LDAP 类型"; | ||||||
|  | $_['text_legal_hold'] = "法务保存措施"; | ||||||
|  | $_['text_load'] = "载入"; | ||||||
|  | $_['text_loading'] = "载入中"; | ||||||
|  | $_['text_logged_in'] = "已登入"; | ||||||
|  | $_['text_logged_out'] = "您已登出"; | ||||||
|  | $_['text_login'] = "登入"; | ||||||
|  | $_['text_login2'] = "登入"; | ||||||
|  | $_['text_login_failed'] = "登入失败"; | ||||||
|  | $_['text_login_via_google'] = "经由 Google 账户登入"; | ||||||
|  | $_['text_logout'] = "登出"; | ||||||
|  | $_['text_logout2'] = "登出"; | ||||||
|  |  | ||||||
|  | $_['text_maillog_status'] = "邮件记录收集器状态"; | ||||||
|  | $_['text_main_title'] = "clapf web UI"; | ||||||
|  | $_['text_mapped_domain'] = "对应域"; | ||||||
|  | $_['text_mark_private'] = "隐私"; | ||||||
|  | $_['text_marked_for_removal'] = "邮件标示为移除"; | ||||||
|  | $_['text_memory_usage'] = "内存使用率"; | ||||||
|  | $_['text_message'] = "邮件"; | ||||||
|  | $_['text_messages'] = "邮件"; | ||||||
|  | $_['text_message_disposition'] = "邮件处理结果计数"; | ||||||
|  | $_['text_message_text'] = "邮件文字"; | ||||||
|  | $_['text_min_2_chars'] = "最小 2 个字元"; | ||||||
|  | $_['text_missing_data'] = "遗失资料"; | ||||||
|  | $_['text_missing_password'] = "遗失密码"; | ||||||
|  | $_['text_modify'] = "修改"; | ||||||
|  | $_['text_monitor'] = "监视器"; | ||||||
|  | $_['text_months'] = "月"; | ||||||
|  | $_['text_monthly_report'] = "每月报表"; | ||||||
|  |  | ||||||
|  | $_['text_need_to_approve_removal'] = "移除需要批准"; | ||||||
|  | $_['text_new'] = "新增"; | ||||||
|  | $_['text_new_users'] = "新增"; | ||||||
|  | $_['text_next'] = "Next"; | ||||||
|  | $_['text_no_domain_found'] = '没有找到域'; | ||||||
|  | $_['text_no_email_found'] = '没有找到邮件'; | ||||||
|  | $_['text_no_message_in_the_quarantine'] = "隔离区内没有符合搜索结果的邮件"; | ||||||
|  | $_['text_no_records'] = "没有记录"; | ||||||
|  | $_['text_no_selected_message'] = "没有选择邮件"; | ||||||
|  | $_['text_no_sender'] = "没有发件人"; | ||||||
|  | $_['text_no_spam_message_in_the_quarantine_yet'] = "隔离区中没有垃圾邮件"; | ||||||
|  | $_['text_no_subject'] = "没有主旨"; | ||||||
|  | $_['text_no_such_policy'] = "没有策略"; | ||||||
|  | $_['text_non_existent_queue_directory'] = "您指定的队列不存在"; | ||||||
|  | $_['text_non_existing_user'] = "无现有的用户"; | ||||||
|  | $_['text_notes'] = "注释"; | ||||||
|  | $_['text_not_found'] = "没有找到"; | ||||||
|  | $_['text_not_running'] = "未在执行中"; | ||||||
|  | $_['text_not_spam'] = "不是垃圾邮件"; | ||||||
|  | $_['title_not_found'] = "Page not found"; | ||||||
|  | $_['text_number_of_messages_in_quarantine'] = "隔离区内符合搜索结果的邮件数量"; | ||||||
|  | $_['text_number_of_spam_messages_in_quarantine'] = "隔离区内符合搜索结果的垃圾邮件数量"; | ||||||
|  |  | ||||||
|  | $_['text_off'] = "关闭"; | ||||||
|  | $_['text_on'] = "启用"; | ||||||
|  | $_['text_online_users'] = "线上用户"; | ||||||
|  | $_['text_other'] = "其他"; | ||||||
|  | $_['text_outbound'] = "outbound"; | ||||||
|  |  | ||||||
|  | $_['text_password'] = "密码"; | ||||||
|  | $_['text_password_again'] = "再一次密码"; | ||||||
|  | $_['text_password_changed'] = "密码已变更"; | ||||||
|  | $_['text_password_mismatch'] = "密码不符"; | ||||||
|  | $_['text_page_length'] = "每页结果"; | ||||||
|  | $_['text_periodic_purge'] = "定期清理"; | ||||||
|  | $_['text_policy'] = "策略"; | ||||||
|  | $_['text_policy_group'] = "策略组"; | ||||||
|  | $_['text_policy_name'] = "策略名称"; | ||||||
|  | $_['text_previous'] = "Previous"; | ||||||
|  | $_['text_print_message'] = "打印"; | ||||||
|  | $_['text_private'] = "隐私"; | ||||||
|  | $_['text_processed_emails'] = "已处理邮件"; | ||||||
|  | $_['text_progress'] = "处理进度"; | ||||||
|  | $_['text_purge_all_messages_from_quarantine'] = "从隔离区清除您的所有邮件"; | ||||||
|  | $_['text_purge_selected_messages'] = "清除已选择邮件"; | ||||||
|  | $_['text_purged'] = "清除"; | ||||||
|  |  | ||||||
|  | $_['text_qr_code'] = "QR code"; | ||||||
|  | $_['text_queue_status'] = "队列状态"; | ||||||
|  | $_['text_quick_search'] = "快速搜索"; | ||||||
|  |  | ||||||
|  | $_['text_realname'] = "人员姓名"; | ||||||
|  | $_['text_recipient'] = "收件人"; | ||||||
|  | $_['text_ref'] = "参照"; | ||||||
|  | $_['text_refresh_period'] = "刷新周期"; | ||||||
|  | $_['text_refresh_qr_code'] = "刷新 QR code"; | ||||||
|  | $_['text_reject'] = "拒绝"; | ||||||
|  | $_['text_rejected_removal'] = "rejected removal"; | ||||||
|  | $_['text_reason_of_rejection'] = "拒绝原因"; | ||||||
|  | $_['text_relay_details'] = "转送内容"; | ||||||
|  | $_['text_relay_status'] = "转送状态"; | ||||||
|  | $_['text_remove'] = "移除"; | ||||||
|  | $_['text_remove_domain'] = "移除域"; | ||||||
|  | $_['text_remove_message'] = "移除邮件"; | ||||||
|  | $_['text_remove_message2'] = "移除邮件"; | ||||||
|  | $_['text_remove_request'] = "移除要求"; | ||||||
|  | $_['text_remove_selected_uids'] = "移除已选择 uids"; | ||||||
|  | $_['text_remove_policy'] = "移除策略"; | ||||||
|  | $_['text_remove_rule'] = "移除规则"; | ||||||
|  | $_['text_remove_this_policy'] = "移除此策略"; | ||||||
|  | $_['text_remove_this_group'] = "移除此组"; | ||||||
|  | $_['text_remove_this_user'] = "移除此用户"; | ||||||
|  | $_['text_removed'] = "已移除"; | ||||||
|  | $_['text_reset_counters'] = "重置计数器"; | ||||||
|  | $_['text_restore'] = "还原"; | ||||||
|  | $_['text_restored'] = "已还原"; | ||||||
|  | $_['text_restore_message'] = "还原邮件"; | ||||||
|  | $_['text_restore_to_mailbox'] = "还原邮件至邮箱"; | ||||||
|  | $_['text_result'] = "结果"; | ||||||
|  | $_['text_retention_days'] = "保留天数"; | ||||||
|  | $_['text_retention_rules'] = "保留规则"; | ||||||
|  | $_['text_role'] = "用户类型"; | ||||||
|  | $_['text_running'] = "执行中"; | ||||||
|  |  | ||||||
|  | $_['text_save'] = "存储"; | ||||||
|  | $_['text_saved'] = "已存储"; | ||||||
|  | $_['text_save_search'] = "存储搜索"; | ||||||
|  | $_['text_save_search_terms'] = "搜索字词"; | ||||||
|  | $_['text_saved_search_terms'] = "搜索字词已存储"; | ||||||
|  | $_['text_search'] = "搜索"; | ||||||
|  | $_['text_search2'] = "搜索"; | ||||||
|  | $_['text_search_emails'] = "搜索邮件地址"; | ||||||
|  | $_['text_search_email_to_add'] = "搜索邮件以加入"; | ||||||
|  | $_['text_search_expression'] = "搜索语法"; | ||||||
|  | $_['text_search_folders'] = "搜索文件夹"; | ||||||
|  | $_['text_search_folder_to_add'] = "搜索文件夹以加入"; | ||||||
|  | $_['text_search_groups'] = "搜索组"; | ||||||
|  | $_['text_search_group_to_add'] = "搜索组以加入"; | ||||||
|  | $_['text_search_terms'] = "搜索字词"; | ||||||
|  | $_['text_select_action'] = "选择动作"; | ||||||
|  | $_['text_select_all'] = "全部选择"; | ||||||
|  | $_['text_select_image'] = "Select image"; | ||||||
|  | $_['text_select_recipients'] = "选择收件人"; | ||||||
|  | $_['text_sender'] = "发件人"; | ||||||
|  | $_['text_sending_domains'] = "发件人域"; | ||||||
|  | $_['text_server_name'] = "服务器名称"; | ||||||
|  | $_['text_server_operating_system'] = "操作系统"; | ||||||
|  | $_['text_set'] = "设定"; | ||||||
|  | $_['text_settings'] = "设定"; | ||||||
|  | $_['text_simple'] = "简单"; | ||||||
|  | $_['text_simple_search'] = "简单搜索"; | ||||||
|  | $_['text_size'] = "大小"; | ||||||
|  | $_['text_smtp_status'] = "SMTP 状态"; | ||||||
|  | $_['text_spam'] = "垃圾邮件"; | ||||||
|  | $_['text_spam2'] = "垃圾邮件"; | ||||||
|  | $_['text_statistics'] = "使用统计"; | ||||||
|  | $_['text_status'] = "状态"; | ||||||
|  | $_['text_storage'] = "存储"; | ||||||
|  | $_['text_subject'] = "主旨"; | ||||||
|  | $_['text_submit'] = "送出"; | ||||||
|  | $_['text_successful'] = "成功"; | ||||||
|  | $_['text_successfully_added'] = "新增成功"; | ||||||
|  | $_['text_successfully_delivered'] = "传递成功"; | ||||||
|  | $_['text_successfully_modified'] = "修改成功"; | ||||||
|  | $_['text_successfully_removed'] = "移除成功"; | ||||||
|  | $_['text_successfully_trained'] = "Successfully trained"; | ||||||
|  | $_['text_successfully_updated'] = "更新成功"; | ||||||
|  | $_['text_support_link'] = "支持链接"; | ||||||
|  | $_['text_swap_usage'] = "Swap 使用率"; | ||||||
|  |  | ||||||
|  | $_['text_tag_selected_messages'] = "标签已选择邮件"; | ||||||
|  | $_['text_tagged'] = "标记的"; | ||||||
|  | $_['text_tags'] = "标签"; | ||||||
|  | $_['text_test_connection'] = "测试连接"; | ||||||
|  | $_['text_text'] = "文字"; | ||||||
|  | $_['text_text_colour'] = "文字颜色"; | ||||||
|  | $_['text_text2'] = "文字"; | ||||||
|  | $_['text_theme'] = "背景主题"; | ||||||
|  | $_['text_time'] = "时间"; | ||||||
|  | $_['text_to'] = "收件人"; | ||||||
|  | $_['text_to_domain'] = "收件人域"; | ||||||
|  | $_['text_too_short_password'] = "密码太短"; | ||||||
|  | $_['text_total'] = "总计"; | ||||||
|  | $_['text_total_ratio'] = "总比例"; | ||||||
|  | $_['text_total_query_time'] = "总计 SQL 查询时间"; | ||||||
|  | $_['text_total_users'] = "总计"; | ||||||
|  | $_['text_type'] = "类型"; | ||||||
|  |  | ||||||
|  | $_['text_uids'] = "uids"; | ||||||
|  | $_['text_unauthorized_domain'] = "未授权域"; | ||||||
|  | $_['text_unauthorized_download_attachment'] = "未授权下载附件"; | ||||||
|  | $_['text_unauthorized_remove_message'] = "未授权移除邮件"; | ||||||
|  | $_['text_unauthorized_view_message'] = "未授权查看邮件"; | ||||||
|  | $_['text_unknown'] = "未知"; | ||||||
|  | $_['text_update_retention_within_this_domain'] = "此域内的更新保留数值"; | ||||||
|  | $_['text_update_selected_uids'] = "更新所选的 uid"; | ||||||
|  | $_['text_updated_records'] = "已更新记录"; | ||||||
|  | $_['text_uptime'] = "运行时间"; | ||||||
|  | $_['text_user'] = "用户"; | ||||||
|  | $_['text_users'] = "用户"; | ||||||
|  | $_['text_user_id'] = "用户 id"; | ||||||
|  | $_['text_user_auditor'] = "审计员"; | ||||||
|  | $_['text_user_data_officer'] = "资料管理员"; | ||||||
|  | $_['text_user_domainadmin'] = "域管理员"; | ||||||
|  | $_['text_user_management'] = "用户管理"; | ||||||
|  | $_['text_user_masteradmin'] = "主要管理员"; | ||||||
|  | $_['text_user_read_only_admin'] = "唯读管理员"; | ||||||
|  | $_['text_user_regular'] = "普通用户"; | ||||||
|  | $_['text_userlist'] = "用户清单"; | ||||||
|  | $_['text_username'] = "用户名称"; | ||||||
|  | $_['text_users_quarantine'] = "用户的隔离区"; | ||||||
|  |  | ||||||
|  | $_['text_view_formatted_email'] = "查看格式化邮件"; | ||||||
|  | $_['text_view_header'] = "查看邮件头"; | ||||||
|  | $_['text_view_headers'] = "查看邮件头"; | ||||||
|  | $_['text_view_journal'] = "日志"; | ||||||
|  | $_['text_view_journal_envelope'] = "查看信封"; | ||||||
|  | $_['text_view_message'] = "查看邮件"; | ||||||
|  | $_['text_view_message2'] = "查看邮件"; | ||||||
|  | $_['text_view_progress'] = "查看进度"; | ||||||
|  | $_['text_view_raw_email'] = "查看原始邮件"; | ||||||
|  | $_['text_view_user_quarantine'] = "查看用户的隔离区"; | ||||||
|  |  | ||||||
|  | $_['text_warning_about_default_policy'] = "预设策略可以在 clapf.conf 中设定"; | ||||||
|  | $_['text_wildcard_domains'] = "通用域"; | ||||||
|  | $_['text_whitelist'] = "白名单"; | ||||||
|  | $_['text_whitelist_settings'] = "白名单设定"; | ||||||
|  | $_['text_with_attachment'] = "含附件"; | ||||||
|  | $_['text_without_attachment'] = "不含附件"; | ||||||
|  |  | ||||||
|  | $_['text_years'] = "年"; | ||||||
|  | $_['text_you_are'] = "您是"; | ||||||
|  | $_['text_you_are_not_admin'] = "您不是管理员"; | ||||||
|  |  | ||||||
|  |  | ||||||
|  | $_['rcvd'] = "接收邮件"; | ||||||
|  | $_['virus'] = "病毒邮件"; | ||||||
|  | $_['duplicate'] = "重复邮件"; | ||||||
|  | $_['ignore'] = "忽略邮件"; | ||||||
|  | $_['counters_last_update'] = "计数器更新"; | ||||||
|  |  | ||||||
|  | $_['text_24_hours'] = "24 小时"; | ||||||
|  | $_['text_1_week'] = "1 周"; | ||||||
|  | $_['text_30_days'] = "30 天"; | ||||||
|  |  | ||||||
|  | $_['text_access_settings'] = '存取设定'; | ||||||
|  | $_['text_access_setting_explanation'] = "您可以存取自己的电子邮件。对于指定组或域的审计员存取,请您与管理员联系。"; | ||||||
|  | $_['text_display_settings'] = '显示设定'; | ||||||
|  | $_['text_change_password'] = "变更密码"; | ||||||
|  | $_['text_none_found'] = "没有找到"; | ||||||
|  | $_['text_primary_domain'] = "主要域"; | ||||||
|  | $_['text_search_domains'] = "搜索域"; | ||||||
|  | $_['text_search_domain_to_add'] = "搜索域以加入"; | ||||||
|  |  | ||||||
|  | $_['text_space_projection'] = '空间保护'; | ||||||
|  | $_['text_average_messages_day'] = '每天平均邮件'; | ||||||
|  | $_['text_average_message_size'] = '平均邮件 + 中继邮件 + 索引大小'; | ||||||
|  | $_['text_average_size_day'] = '每天平均大小'; | ||||||
|  | $_['text_partition_full'] = '分区预计用完于'; | ||||||
|  | $_['text_usage_trend'] = '使用趋势'; | ||||||
|  | $_['text_usage_increasing'] = '上升'; | ||||||
|  | $_['text_usage_decreasing'] = '下降'; | ||||||
|  | $_['text_usage_neutral'] = '持平'; | ||||||
|  | $_['text_accounting'] = '归档审计'; | ||||||
|  | $_['text_accounting_email'] = '依邮件审计'; | ||||||
|  | $_['text_accounting_domain'] = '依域名审计'; | ||||||
|  |  | ||||||
|  | $_['text_options'] = '选项'; | ||||||
|  | $_['text_spam_flag'] = '邮件已标注为 SPAM'; | ||||||
|  | $_['text_attachment_flag'] = '邮件有附件'; | ||||||
|  | $_['text_notes_flag'] = '邮件有备注'; | ||||||
|  | $_['text_tag_flag'] = '邮件已标记'; | ||||||
|  | $_['text_verified_flag'] = '邮件以验证'; | ||||||
|  | $_['text_unverified_flag'] = '邮件验证失败'; | ||||||
|  | $_['text_bulk_download'] = '批次下载已选择邮件'; | ||||||
|  | $_['text_clear'] = '清除'; | ||||||
|  | $_['text_select_letter'] = '以开头字母选择'; | ||||||
|  | $_['text_working'] = '作业中...'; | ||||||
|  |  | ||||||
|  | $_['text_use_browser_settings'] = '使用浏览器设定'; | ||||||
|  |  | ||||||
|  | $_['text_sent'] = '寄送'; | ||||||
|  | $_['text_received'] = '已接收'; | ||||||
|  | $_['text_oldest_record'] = '最旧记录'; | ||||||
|  | $_['text_newest_record'] = '最新纪录'; | ||||||
|  | $_['text_items'] = '项目'; | ||||||
|  | $_['text_average_size'] = '平均大小'; | ||||||
|  |  | ||||||
|  | $_['text_return_to'] = '回到'; | ||||||
|  | $_['text_error_message'] = '请更正以下错误后重新送出。'; | ||||||
|  | $_['text_field_required'] = '此为必填栏位。'; | ||||||
|  | $_['text_field_length'] = '这个栏位必须大于 ? 个字元。'; | ||||||
|  | $_['text_field_domain'] = '这个栏位必须填入域 (例如 - domain.com)。'; | ||||||
|  | $_['text_field_colour'] = '这个栏位必须填入色码 (例如 - #fcfcfc)。'; | ||||||
|  | $_['text_delete'] = '删除'; | ||||||
|  | $_['text_confirm'] = '确认'; | ||||||
|  | $_['text_user_delete_confirm_message'] = '您要删除用户吗'; | ||||||
|  | $_['text_domain_delete_confirm_message'] = '您要删除域吗'; | ||||||
|  | $_['text_group_delete_confirm_message'] = '您要删除组吗'; | ||||||
|  | $_['text_ldap_delete_confirm_message'] = '您要删除 LDAP 项目吗'; | ||||||
|  | $_['text_customer_delete_confirm_message'] = '您要删除客户吗'; | ||||||
|  | $_['text_with_selected'] = '选择项目'; | ||||||
|  |  | ||||||
|  | $_['text_compliance_warning'] = '删除功能已启用,因此这个归档不符合规定!'; | ||||||
							
								
								
									
										497
									
								
								webui/language/it/messages.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										497
									
								
								webui/language/it/messages.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,497 @@ | |||||||
|  | <?php | ||||||
|  |  | ||||||
|  | $_['text_60_minutes'] = "60 min."; | ||||||
|  |  | ||||||
|  | $_['text_action'] = "Azione"; | ||||||
|  | $_['text_active_incoming_queue'] = "coda attiva e in entrata"; | ||||||
|  | $_['text_active_incoming_queue_sender'] = "active + incoming queue vs. sender"; | ||||||
|  | $_['text_ad_sync_status'] = "Stato di sincronizzazione con AD"; | ||||||
|  | $_['text_add'] = "Aggiungi"; | ||||||
|  | $_['text_add_new_email_address'] = "Nuovo indirizzo email"; | ||||||
|  | $_['text_add_new_domain'] = "Nuovo Dominio"; | ||||||
|  | $_['text_add_new_entry'] = "Nuovo inserimento"; | ||||||
|  | $_['text_add_new_group'] = "Aggiungi gruppo"; | ||||||
|  | $_['text_add_new_rule'] = "Aggiungi regola"; | ||||||
|  | $_['text_add_new_user_alias'] = "Nuovo utente"; | ||||||
|  | $_['text_add_policy'] = "Aggiungi una nuova policy"; | ||||||
|  | $_['text_administration'] = "Amministrazione"; | ||||||
|  | $_['text_admin_user'] = "Utente amministratore"; | ||||||
|  | $_['text_advanced'] = "Avanzate"; | ||||||
|  | $_['text_advanced_search'] = "Ricerca avanzata"; | ||||||
|  | $_['text_all'] = "Tutti"; | ||||||
|  | $_['text_any'] = "Qualunque"; | ||||||
|  | $_['text_applied'] = "Applicata"; | ||||||
|  | $_['text_apply_changes'] = "Applica modifiche"; | ||||||
|  | $_['text_archive_size'] = "Dimensione archivio"; | ||||||
|  | $_['text_archive_size_before_compression'] = "Dimensione archivio pruima della compressione"; | ||||||
|  | $_['text_archived_messages'] = "Messaggi archiviati"; | ||||||
|  | $_['text_archiving_rules'] = "Regole di archiviazione"; | ||||||
|  | $_['text_assigned_email_addresses'] = "Indirizzi email assegnati"; | ||||||
|  | $_['text_attachment'] = "Allegato"; | ||||||
|  | $_['text_attachment_name'] = "Nome dell'allegato"; | ||||||
|  | $_['text_attachment_size'] = "Dimensione dell'allegato"; | ||||||
|  | $_['text_attachment_type'] = "Tipo di allegato"; | ||||||
|  | $_['text_audit'] = "Audit"; | ||||||
|  | $_['text_automated_search'] = "Ricerca automatica"; | ||||||
|  |  | ||||||
|  | $_['text_back'] = "Indietro"; | ||||||
|  | $_['text_background_colour'] = "Colore di sfondo"; | ||||||
|  | $_['text_body'] = "Corpo"; | ||||||
|  | $_['text_branding_logo'] = "Branding logo"; | ||||||
|  | $_['text_branding_text'] = "Branding text"; | ||||||
|  | $_['text_branding_url'] = "Branding URL"; | ||||||
|  | $_['text_bulk_edit_selected_uids'] = "MOdifica tutti gli ID selezionati"; | ||||||
|  | $_['text_bulk_restore_selected_emails'] = "Ripristina tutti gli ID selezionati"; | ||||||
|  | $_['text_bulk_update_selected_uids'] = "Aggiorna tutti gli ID selezionati"; | ||||||
|  |  | ||||||
|  | $_['text_cancel'] = "Cancella"; | ||||||
|  | $_['text_change_user_settings'] = "modifica impostazioni utente"; | ||||||
|  | $_['text_clienthost'] = "Client host"; | ||||||
|  | $_['text_close'] = "Chiudi"; | ||||||
|  | $_['text_colour'] = "Colore"; | ||||||
|  | $_['text_compressed'] = "compresso"; | ||||||
|  | $_['text_confirm_to_reset_counters'] = "Conferma l'azzeramento dei contatori"; | ||||||
|  | $_['text_connection_failed'] = "Connessione fallita"; | ||||||
|  | $_['text_connection_ok'] = "Connessione OK"; | ||||||
|  | $_['text_contact_support'] = "Contatta il supporto"; | ||||||
|  | $_['text_content_filter'] = "Filtro contenuti"; | ||||||
|  | $_['text_conversation_available'] = "Conversazione disponibile"; | ||||||
|  | $_['text_copied'] = "Copiato"; | ||||||
|  | $_['text_counters'] = "Contatori"; | ||||||
|  | $_['text_cpu_load'] = "Carico sulla CPU"; | ||||||
|  | $_['text_cpu_usage'] = "Utilizzo CPU"; | ||||||
|  | $_['text_create_new_secret'] = "Crea un "; | ||||||
|  | $_['text_create_note'] = "Crea una nota"; | ||||||
|  | $_['text_cumulative_counts'] = "Conteggi cumulativi"; | ||||||
|  | $_['text_customers'] = "Clienti"; | ||||||
|  |  | ||||||
|  | $_['text_daily_quarantine_report'] = "Rapporto quotidiano della quarantena"; | ||||||
|  | $_['text_daily_quarantine_report_status'] = "Stato del rapporto quotidiano della quarantena"; | ||||||
|  | $_['text_daily_report'] = "Rapporto quotidiano"; | ||||||
|  | $_['text_daily_piler_report'] = "Rappporto quotidiano di piler"; | ||||||
|  | $_['text_database_emails'] = "indirizzi email nel database di piler"; | ||||||
|  | $_['text_date'] = "Data"; | ||||||
|  | $_['text_date_from'] = "Dalla data"; | ||||||
|  | $_['text_date_to'] = "Alla data"; | ||||||
|  | $_['text_days'] = "Giorni"; | ||||||
|  | $_['text_days2'] = "giorni"; | ||||||
|  | $_['text_days_to_retain'] = "Giorni da conservare"; | ||||||
|  | $_['text_deferred_queue'] = "coda differita"; | ||||||
|  | $_['text_deferred_queue_sender'] = "coda differita verso il mittente"; | ||||||
|  | $_['text_delay'] = "Ritardo"; | ||||||
|  | $_['text_delete_confirm_message'] = "Vuoi cancellare"; | ||||||
|  | $_['text_delete_reason'] = "Motivo della rimozione"; | ||||||
|  | $_['text_deleted'] = "Cancellato"; | ||||||
|  | $_['text_deleted_users'] = "Cancellato"; | ||||||
|  | $_['text_deliver'] = "Consegna"; | ||||||
|  | $_['text_delivered'] = "Consegnato"; | ||||||
|  | $_['text_deliver_and_train_selected_messages'] = "Consegna i messaggi selezionati e indicizzali come"; | ||||||
|  | $_['text_deliver_and_train_selected_messages_as_ham'] = "Consegna i messaggi selezionati e indicizzali come HAM"; | ||||||
|  | $_['text_deliver_selected_messages'] = "Consegna i messaggi selezionati"; | ||||||
|  | $_['text_description'] = "Descrizione"; | ||||||
|  | $_['text_direction'] = "Direzione"; | ||||||
|  | $_['text_disk_usage'] = "Utilizzo disco"; | ||||||
|  | $_['text_disable'] = "Disabilita"; | ||||||
|  | $_['text_disabled'] = "disabilitata"; | ||||||
|  | $_['text_dn_asterisk_means_skip_sync'] = "L'Asterisco (*) significa che questo utente non avrà parte nella sincronizzazione di AD"; | ||||||
|  | $_['text_domain'] = "Dominio"; | ||||||
|  | $_['text_domains'] = "Domini(o)"; | ||||||
|  | $_['text_domainname'] = "Nome dominio"; | ||||||
|  | $_['text_download_all_hits_as_eml'] = "Scarica tutto (EML)"; | ||||||
|  | $_['text_download_selected_hits_as_pdf'] = "Scarica la selezione (PDF)"; | ||||||
|  | $_['text_download_attachment2'] = "scarica l'allegato"; | ||||||
|  | $_['text_download_message'] = "Scarica (EML)"; | ||||||
|  | $_['text_download_message2'] = "scarica il messaggio"; | ||||||
|  |  | ||||||
|  | $_['text_edit'] = "Modifica"; | ||||||
|  | $_['text_edit_entry'] = "Modifica voce"; | ||||||
|  | $_['text_edit_group'] = "Modifica gruppo"; | ||||||
|  | $_['text_edit_user'] = "Modifica utente"; | ||||||
|  | $_['text_edit_or_view'] = "Modifica/vedi"; | ||||||
|  | $_['text_email'] = "Indirizzo email"; | ||||||
|  | $_['text_email_addresses'] = "Indirizzi email"; | ||||||
|  | $_['text_email_aliases'] = "Alias email"; | ||||||
|  | $_['text_email_in_unknown_domain'] = "l'indirizzo email è di un dominio sconosciuto"; | ||||||
|  | $_['text_empty_search_criteria'] = "'Nessun criterio di ricerca'"; | ||||||
|  | $_['text_empty_search_result'] = "Nessun risultato. Prova ad aggiungere il carattere jolly(*) dopo una parola abbreviata (min. " . MIN_PREFIX_LEN . " lettere), es. duplic* per trovare \"duplicate\", \"duplicati\", etc."; | ||||||
|  | $_['text_enable'] = "Abilita"; | ||||||
|  | $_['text_enabled'] = "abilitata"; | ||||||
|  | $_['text_enter_google_authenticator_code'] = "Usa Google Authenticator"; | ||||||
|  | $_['text_enter_one_email_address_per_line'] = "Inserisci un indirizzo email per riga"; | ||||||
|  | $_['text_enter_one_group_per_line'] = "Inserisci un gruppo per riga"; | ||||||
|  | $_['text_enter_search_terms'] = "Inserisci i termini di ricerca"; | ||||||
|  | $_['text_error'] = "Errore"; | ||||||
|  | $_['text_exact_domain_name_or_email_address'] = "esatto nome a domino o indirizzo email"; | ||||||
|  | $_['text_exclude'] = "Escludi"; | ||||||
|  | $_['text_existing'] = "Esistente"; | ||||||
|  | $_['text_existing_domains'] = "Dominio esistente"; | ||||||
|  | $_['text_existing_email'] = "Email esistente"; | ||||||
|  | $_['text_existing_folders'] = "Cartelle esistenti"; | ||||||
|  | $_['text_existing_groups'] = "Gruppi esistenti"; | ||||||
|  | $_['text_existing_policies'] = "Policies esistenti"; | ||||||
|  | $_['text_existing_entries'] = "Voci esistenti"; | ||||||
|  | $_['text_existing_rules'] = "Regole esistenti"; | ||||||
|  | $_['text_existing_user'] = "Utente esistente"; | ||||||
|  | $_['text_existing_users'] = "Utenti esistenti"; | ||||||
|  | $_['text_expert'] = "Esperto"; | ||||||
|  | $_['text_expert_search'] = "Ricerca esperta"; | ||||||
|  |  | ||||||
|  | $_['text_failed'] = "fallito"; | ||||||
|  | $_['text_failed_to_add'] = "Aggiunta fallita"; | ||||||
|  | $_['text_failed_to_change_password'] = "Cambio password fallito"; | ||||||
|  | $_['text_failed_to_deliver'] = "Consegna fallita"; | ||||||
|  | $_['text_failed_to_mark_for_removal'] = "Contrassegno di rimozione fallito"; | ||||||
|  | $_['text_failed_to_modify'] = "Modifica fallita"; | ||||||
|  | $_['text_failed_to_remove'] = "Rimozione fallita"; | ||||||
|  | $_['text_failed_to_restore'] = "Ripristino fallito"; | ||||||
|  | $_['text_failed_to_update'] = "Aggiornamento fallito"; | ||||||
|  | $_['text_first'] = "Primo"; | ||||||
|  | $_['text_folder'] = "Cartella"; | ||||||
|  | $_['text_folder_rules'] = "Regole delle cartelle"; | ||||||
|  | $_['text_folders'] = "Cartelle"; | ||||||
|  | $_['text_forward_selected_emails_to'] = "Inoltra i messaggi selezionati a"; | ||||||
|  | $_['text_from'] = "Da"; | ||||||
|  | $_['text_from_domain'] = "Dal dominio"; | ||||||
|  |  | ||||||
|  | $_['text_google_authenticator_code'] = "Google Authenticator code"; | ||||||
|  | $_['text_google_authenticator_settings'] = "Impostazioni di Google Authenticator"; | ||||||
|  | $_['text_group_id'] = "Id gruppo"; | ||||||
|  | $_['text_groupname'] = "Nome gruppo"; | ||||||
|  | $_['text_groups'] = "Gruppi"; | ||||||
|  | $_['text_group_management'] = "Gestione gruppo"; | ||||||
|  | $_['text_group_membership'] = "Appartenenza al gruppo"; | ||||||
|  |  | ||||||
|  | $_['text_health'] = "Health"; | ||||||
|  | $_['text_health_monitor'] = "Health monitor"; | ||||||
|  | $_['text_help'] = "Aiuto"; | ||||||
|  | $_['text_history'] = "Cronologia"; | ||||||
|  | $_['text_home'] = "Home"; | ||||||
|  |  | ||||||
|  | $_['text_image'] = "immagine"; | ||||||
|  | $_['text_import'] = "Importa"; | ||||||
|  | $_['text_import_job_delete_confirm_message'] = "Vuoi terminare l'importazione"; | ||||||
|  | $_['text_import_users'] = "Importa utenti"; | ||||||
|  | $_['text_import_users_from_LDAP'] = "Importa utenti da LDAP"; | ||||||
|  | $_['text_inbound'] = "In entrata"; | ||||||
|  | $_['text_indexer_job'] = "Indicizzazione"; | ||||||
|  | $_['text_install_sudo_apply'] = "Aggiungi la riga seguente a /etc/sudoers: 'www-data ALL=NOPASSWD: /etc/init.d/rc.piler reload'"; | ||||||
|  | $_['text_internal'] = "interno"; | ||||||
|  | $_['text_invalid_data'] = "Dati non validi"; | ||||||
|  | $_['text_invalid_email'] = "Email non valida"; | ||||||
|  | $_['text_invalid_email_or_password'] = "email o password non valide"; | ||||||
|  | $_['text_invalid_gid'] = "GID non valido"; | ||||||
|  | $_['text_invalid_password'] = "Password non valida"; | ||||||
|  | $_['text_invalid_pin_code'] = "Pin non valido"; | ||||||
|  | $_['text_invalid_policy_group'] = "Regola di gruppo non valida"; | ||||||
|  | $_['text_invalid_policy_name'] = "Nome regola non valido"; | ||||||
|  | $_['text_invalid_policy_setting'] = "Impostazioni policy non valide"; | ||||||
|  | $_['text_invalid_uid'] = "UID non valido"; | ||||||
|  | $_['text_invalid_username'] = "Nome utente non valido"; | ||||||
|  | $_['text_ipaddr'] = "Indirizzo IP"; | ||||||
|  |  | ||||||
|  | $_['text_language'] = "Lingua"; | ||||||
|  | $_['text_last'] = "Ultimo"; | ||||||
|  | $_['text_last_activity'] = "Ultima attività"; | ||||||
|  | $_['text_last_update'] = "Ultimo aggiornamento"; | ||||||
|  | $_['text_latest_emails'] = "Ultime email"; | ||||||
|  | $_['text_ldap'] = "LDAP"; | ||||||
|  | $_['text_ldap_auditor_member_dn'] = "Auditor member DN"; | ||||||
|  | $_['text_ldap_base_dn'] = "LDAP base DN"; | ||||||
|  | $_['text_ldap_bind_dn'] = "LDAP bind DN"; | ||||||
|  | $_['text_ldap_bind_pw'] = "LDAP bind password"; | ||||||
|  | $_['text_ldap_host'] = "LDAP host"; | ||||||
|  | $_['text_ldap_type'] = "LDAP type"; | ||||||
|  | $_['text_legal_hold'] = "Conservazione legale"; | ||||||
|  | $_['text_load'] = "Carico"; | ||||||
|  | $_['text_loading'] = "caricamento"; | ||||||
|  | $_['text_logged_in'] = "connesso"; | ||||||
|  | $_['text_logged_out'] = "Ti sei disconnesso"; | ||||||
|  | $_['text_login'] = "Login"; | ||||||
|  | $_['text_login2'] = "login"; | ||||||
|  | $_['text_login_failed'] = "login fallito"; | ||||||
|  | $_['text_login_via_google'] = "Login via Google account"; | ||||||
|  | $_['text_logout'] = "Disconnetti"; | ||||||
|  | $_['text_logout2'] = "disconnetti"; | ||||||
|  |  | ||||||
|  | $_['text_maillog_status'] = "status del collettore dei log delle email"; | ||||||
|  | $_['text_main_title'] = "interfaccia web di clapf"; | ||||||
|  | $_['text_mapped_domain'] = "Dominio associato"; | ||||||
|  | $_['text_mark_private'] = "privato"; | ||||||
|  | $_['text_marked_for_removal'] = "Messaggio contrassegnato per la rimozione"; | ||||||
|  | $_['text_memory_usage'] = "Utilizzo memoria"; | ||||||
|  | $_['text_message'] = "messaggio"; | ||||||
|  | $_['text_messages'] = "messaggi"; | ||||||
|  | $_['text_message_disposition'] = "Disposizione Messaggi"; | ||||||
|  | $_['text_message_text'] = "Testo del messaggio"; | ||||||
|  | $_['text_min_2_chars'] = "Min. 2 caratteri"; | ||||||
|  | $_['text_missing_data'] = "Dati mancanti"; | ||||||
|  | $_['text_missing_password'] = "Password mancante"; | ||||||
|  | $_['text_modify'] = "Modifica"; | ||||||
|  | $_['text_monitor'] = "Monitor"; | ||||||
|  | $_['text_months'] = "mesi"; | ||||||
|  | $_['text_monthly_report'] = "Rapporto mensile"; | ||||||
|  |  | ||||||
|  | $_['text_need_to_approve_removal'] = "devi approvare la rimozione"; | ||||||
|  | $_['text_new'] = "nuovo"; | ||||||
|  | $_['text_new_users'] = "nuovo"; | ||||||
|  | $_['text_next'] = "Prossimo"; | ||||||
|  | $_['text_no_domain_found'] = 'Nessun dominio trovato'; | ||||||
|  | $_['text_no_email_found'] = 'Nessuna email trovata'; | ||||||
|  | $_['text_no_message_in_the_quarantine'] = "Nessun messaggio in quarantena soddisfa i requisiti di ricerca"; | ||||||
|  | $_['text_no_records'] = "Nessun record"; | ||||||
|  | $_['text_no_selected_message'] = "nessun messaggio selezionato"; | ||||||
|  | $_['text_no_sender'] = "nessun mittente"; | ||||||
|  | $_['text_no_spam_message_in_the_quarantine_yet'] = "Nessun messaggio spam in quarantena ora"; | ||||||
|  | $_['text_no_subject'] = "nessun oggetto"; | ||||||
|  | $_['text_no_such_policy'] = "Nessuna policy di questo tipo"; | ||||||
|  | $_['text_non_existent_queue_directory'] = "Cartella della coda specificata inesistente"; | ||||||
|  | $_['text_non_existing_user'] = "Utente inesistente"; | ||||||
|  | $_['text_notes'] = "Note"; | ||||||
|  | $_['text_not_found'] = "Non trovato"; | ||||||
|  | $_['text_not_running'] = "non in funzione"; | ||||||
|  | $_['text_not_spam'] = "non SPAM"; | ||||||
|  | $_['title_not_found'] = "Pagina non trovata"; | ||||||
|  | $_['text_number_of_messages_in_quarantine'] = "Numero di messaggi in quarantena che soddisfano i tuoi criteri di ricerca"; | ||||||
|  | $_['text_number_of_spam_messages_in_quarantine'] = "Numero di messaggi spam in quarantena che soddisfano i tuoi criteri di ricerca"; | ||||||
|  |  | ||||||
|  | $_['text_off'] = "off"; | ||||||
|  | $_['text_on'] = "on"; | ||||||
|  | $_['text_online_users'] = "Utenti online"; | ||||||
|  | $_['text_other'] = "altro"; | ||||||
|  | $_['text_outbound'] = "in uscita"; | ||||||
|  |  | ||||||
|  | $_['text_password'] = "Password"; | ||||||
|  | $_['text_password_again'] = "Ripeti password"; | ||||||
|  | $_['text_password_changed'] = "Password modificata"; | ||||||
|  | $_['text_password_mismatch'] = "Le password non corrispondono"; | ||||||
|  | $_['text_page_length'] = "Risultati per pagina"; | ||||||
|  | $_['text_periodic_purge'] = "Pulizia periodica"; | ||||||
|  | $_['text_policy'] = "Policy"; | ||||||
|  | $_['text_policy_group'] = "Policy group"; | ||||||
|  | $_['text_policy_name'] = "Nome policy"; | ||||||
|  | $_['text_previous'] = "Precedente"; | ||||||
|  | $_['text_print_message'] = "Stampa"; | ||||||
|  | $_['text_private'] = "Privato"; | ||||||
|  | $_['text_processed_emails'] = "email processate"; | ||||||
|  | $_['text_progress'] = "Progresso"; | ||||||
|  | $_['text_purge_all_messages_from_quarantine'] = "Elimina tutti i tuoi messaggi dalla quarantena"; | ||||||
|  | $_['text_purge_selected_messages'] = "Elimina i messaggi selezionati"; | ||||||
|  | $_['text_purged'] = "Eliminati"; | ||||||
|  |  | ||||||
|  | $_['text_qr_code'] = "QR"; | ||||||
|  | $_['text_queue_status'] = "Stato della coda"; | ||||||
|  | $_['text_quick_search'] = "Ricerca veloca"; | ||||||
|  |  | ||||||
|  | $_['text_realname'] = "Nome reale"; | ||||||
|  | $_['text_recipient'] = "Destinatario"; | ||||||
|  | $_['text_ref'] = "Riferimento"; | ||||||
|  | $_['text_refresh_period'] = "Periodo di aggiornamento"; | ||||||
|  | $_['text_refresh_qr_code'] = "Aggiorna il QR code"; | ||||||
|  | $_['text_reject'] = "Scarta"; | ||||||
|  | $_['text_rejected_removal'] = "rimozione scartata"; | ||||||
|  | $_['text_reason_of_rejection'] = "Motivo dello scarto"; | ||||||
|  | $_['text_relay_details'] = "Dettagli di inoltro"; | ||||||
|  | $_['text_relay_status'] = "Stato dell'inoltro"; | ||||||
|  | $_['text_remove'] = "Rimuovi"; | ||||||
|  | $_['text_remove_domain'] = "Rimuovi dominio"; | ||||||
|  | $_['text_remove_message'] = "Rimuovi il messaggio"; | ||||||
|  | $_['text_remove_message2'] = "rimuovi il messaggio"; | ||||||
|  | $_['text_remove_request'] = "remove request"; | ||||||
|  | $_['text_remove_selected_uids'] = "Rimuovi gli uid selezionati"; | ||||||
|  | $_['text_remove_policy'] = "Rimuovi policy"; | ||||||
|  | $_['text_remove_rule'] = "Rimuovi regola"; | ||||||
|  | $_['text_remove_this_policy'] = "Rimuovi questa policy"; | ||||||
|  | $_['text_remove_this_group'] = "Rimuovi questo gruppo"; | ||||||
|  | $_['text_remove_this_user'] = "Rimuovio questo utente"; | ||||||
|  | $_['text_removed'] = "Rimosso"; | ||||||
|  | $_['text_reset_counters'] = "Azzera i contatori"; | ||||||
|  | $_['text_restore'] = "Ripristina"; | ||||||
|  | $_['text_restored'] = "Ripristinato"; | ||||||
|  | $_['text_restore_message'] = "ripriatina messaggio"; | ||||||
|  | $_['text_restore_to_mailbox'] = "Ripristina nella cassetta postale"; | ||||||
|  | $_['text_result'] = "Risultato"; | ||||||
|  | $_['text_retention_days'] = "Giorni di conservazione"; | ||||||
|  | $_['text_retention_rules'] = "Regole di conservazione"; | ||||||
|  | $_['text_role'] = "Regola"; | ||||||
|  | $_['text_running'] = "in corso"; | ||||||
|  |  | ||||||
|  | $_['text_save'] = "Salva"; | ||||||
|  | $_['text_saved'] = "Salvato"; | ||||||
|  | $_['text_save_search'] = "salva la ricerca"; | ||||||
|  | $_['text_save_search_terms'] = "Salva i termini della ricerca"; | ||||||
|  | $_['text_saved_search_terms'] = "Termini di ricerca salvati"; | ||||||
|  | $_['text_search'] = "Cerca"; | ||||||
|  | $_['text_search2'] = "cerca"; | ||||||
|  | $_['text_search_emails'] = "Cerca indirizzi email"; | ||||||
|  | $_['text_search_email_to_add'] = "Cerca email da aggiungere"; | ||||||
|  | $_['text_search_expression'] = "Espressione di ricerca"; | ||||||
|  | $_['text_search_folders'] = "Cartelle di ricerca"; | ||||||
|  | $_['text_search_folder_to_add'] = "Cerca le cartelle  da aggiungere"; | ||||||
|  | $_['text_search_groups'] = "Cerca gruppi"; | ||||||
|  | $_['text_search_group_to_add'] = "Cerca un gruppo da aggiungere"; | ||||||
|  | $_['text_search_terms'] = "Termini di ricerca"; | ||||||
|  | $_['text_select_action'] = "Seleziona azione"; | ||||||
|  | $_['text_select_all'] = "Seleziona tutto"; | ||||||
|  | $_['text_select_image'] = "Seleziona immagine"; | ||||||
|  | $_['text_select_recipients'] = "Selezione destinatari"; | ||||||
|  | $_['text_sender'] = "Mittente"; | ||||||
|  | $_['text_sending_domains'] = "domini mittenti"; | ||||||
|  | $_['text_server_name'] = "Nome server"; | ||||||
|  | $_['text_server_operating_system'] = "Sistema operativo"; | ||||||
|  | $_['text_set'] = "Imposta"; | ||||||
|  | $_['text_settings'] = "Impostazioni"; | ||||||
|  | $_['text_simple'] = "Semplice"; | ||||||
|  | $_['text_simple_search'] = "Ricera semplice"; | ||||||
|  | $_['text_size'] = "Dimensioni"; | ||||||
|  | $_['text_smtp_status'] = "Stato SMTP"; | ||||||
|  | $_['text_spam'] = "Spam"; | ||||||
|  | $_['text_spam2'] = "spam"; | ||||||
|  | $_['text_statistics'] = "Statistiche"; | ||||||
|  | $_['text_status'] = "Status"; | ||||||
|  | $_['text_storage'] = "Archiviazione"; | ||||||
|  | $_['text_subject'] = "Oggetto"; | ||||||
|  | $_['text_submit'] = "Invia"; | ||||||
|  | $_['text_successful'] = "Con successo"; | ||||||
|  | $_['text_successfully_added'] = "Aggiunto con successo"; | ||||||
|  | $_['text_successfully_delivered'] = "Consegnato con successo"; | ||||||
|  | $_['text_successfully_modified'] = "Modificato con successo"; | ||||||
|  | $_['text_successfully_removed'] = "Rimosso con successo"; | ||||||
|  | $_['text_successfully_trained'] = "Allenato con successo"; | ||||||
|  | $_['text_successfully_updated'] = "Aggiornato con successo"; | ||||||
|  | $_['text_support_link'] = "Collegamento di supporto"; | ||||||
|  | $_['text_swap_usage'] = "Utilizzo dello swap"; | ||||||
|  |  | ||||||
|  | $_['text_tag_selected_messages'] = "Marca i messaggi selezionati"; | ||||||
|  | $_['text_tagged'] = "Etichettato"; | ||||||
|  | $_['text_tags'] = "Etichette"; | ||||||
|  | $_['text_test_connection'] = "Test della connessione"; | ||||||
|  | $_['text_text'] = "Testo"; | ||||||
|  | $_['text_text_colour'] = "Colore testo"; | ||||||
|  | $_['text_text2'] = "testo"; | ||||||
|  | $_['text_theme'] = "Tema"; | ||||||
|  | $_['text_time'] = "Ora"; | ||||||
|  | $_['text_to'] = "A"; | ||||||
|  | $_['text_to_domain'] = "Al dominio"; | ||||||
|  | $_['text_too_short_password'] = "Password troppo corta"; | ||||||
|  | $_['text_total'] = "totale"; | ||||||
|  | $_['text_total_ratio'] = "rateo totale"; | ||||||
|  | $_['text_total_query_time'] = "Tempo totale della query SQL"; | ||||||
|  | $_['text_total_users'] = "totale"; | ||||||
|  | $_['text_type'] = "Tipo"; | ||||||
|  |  | ||||||
|  | $_['text_uids'] = "uids"; | ||||||
|  | $_['text_unauthorized_domain'] = "Dominio non autorizzato"; | ||||||
|  | $_['text_unauthorized_download_attachment'] = "download dell'allegato non autorizzato"; | ||||||
|  | $_['text_unauthorized_remove_message'] = "Rimozione del messaggio non autorizzata"; | ||||||
|  | $_['text_unauthorized_view_message'] = "Visualizzazione del messaggio non autorizzata"; | ||||||
|  | $_['text_unknown'] = "sconosciuto"; | ||||||
|  | $_['text_update_retention_within_this_domain'] = "Aggiorna i valori di conservazione all'interno di questo dominio"; | ||||||
|  | $_['text_update_selected_uids'] = "Aggiorna gli UID selezionati"; | ||||||
|  | $_['text_updated_records'] = "Record aggiornato"; | ||||||
|  | $_['text_uptime'] = "Uptime"; | ||||||
|  | $_['text_user'] = "Utente"; | ||||||
|  | $_['text_users'] = "Utenti"; | ||||||
|  | $_['text_user_id'] = "Id Utente"; | ||||||
|  | $_['text_user_auditor'] = "Auditor"; | ||||||
|  | $_['text_user_data_officer'] = "Data officer"; | ||||||
|  | $_['text_user_domainadmin'] = "Amministratore del dominio"; | ||||||
|  | $_['text_user_management'] = "Gestione utente"; | ||||||
|  | $_['text_user_masteradmin'] = "Master admin"; | ||||||
|  | $_['text_user_read_only_admin'] = "Read-only admin"; | ||||||
|  | $_['text_user_regular'] = "Normale utente"; | ||||||
|  | $_['text_userlist'] = "Lista degli utenti"; | ||||||
|  | $_['text_username'] = "Nome utente"; | ||||||
|  | $_['text_users_quarantine'] = "Quarantena degli utenti"; | ||||||
|  |  | ||||||
|  | $_['text_view_formatted_email'] = "Visualizza email formattata"; | ||||||
|  | $_['text_view_header'] = "visualizza intestazioni"; | ||||||
|  | $_['text_view_headers'] = "Visualizza intestazioni"; | ||||||
|  | $_['text_view_journal'] = "journal"; | ||||||
|  | $_['text_view_journal_envelope'] = "Visualizza la busta"; | ||||||
|  | $_['text_view_message'] = "Visualizza il messaggio"; | ||||||
|  | $_['text_view_message2'] = "visualizza il messaggio"; | ||||||
|  | $_['text_view_progress'] = "visualizza il progresso"; | ||||||
|  | $_['text_view_raw_email'] = "Visualizza sorgenti"; | ||||||
|  | $_['text_view_user_quarantine'] = "Visualizza la quarantena dell'utente"; | ||||||
|  |  | ||||||
|  | $_['text_warning_about_default_policy'] = "La policy predefinita può essere configurata in clapf.conf"; | ||||||
|  | $_['text_wildcard_domains'] = "Wildcard domini"; | ||||||
|  | $_['text_whitelist'] = "Lista bianca"; | ||||||
|  | $_['text_whitelist_settings'] = "Impostazioni della lista bianca"; | ||||||
|  | $_['text_with_attachment'] = "con allegato(i)"; | ||||||
|  | $_['text_without_attachment'] = "senza allegato"; | ||||||
|  |  | ||||||
|  | $_['text_years'] = "anni"; | ||||||
|  | $_['text_you_are'] = "Tu sei"; | ||||||
|  | $_['text_you_are_not_admin'] = "Tu non sei un utente amministratore"; | ||||||
|  |  | ||||||
|  |  | ||||||
|  | $_['rcvd'] = "messaggi ricevuti"; | ||||||
|  | $_['virus'] = "messaggi infetti"; | ||||||
|  | $_['duplicate'] = "messaggi duplicati"; | ||||||
|  | $_['ignore'] = "messaggi ignorati"; | ||||||
|  | $_['counters_last_update'] = "contatori aggiornati"; | ||||||
|  |  | ||||||
|  | $_['text_24_hours'] = "24 ore"; | ||||||
|  | $_['text_1_week'] = "1 settimana"; | ||||||
|  | $_['text_30_days'] = "30 giorni"; | ||||||
|  |  | ||||||
|  | $_['text_access_settings'] = 'Impostazioni di accesso'; | ||||||
|  | $_['text_access_setting_explanation'] = "Hai sempre accesso ai tuoi indirizzi email.  Contatta l'amministratore per un accesso da auditor a specifici gruppi o domini."; | ||||||
|  | $_['text_display_settings'] = 'Visualizza le impostazioni'; | ||||||
|  | $_['text_change_password'] = "Cambia Password"; | ||||||
|  | $_['text_none_found'] = "Nessuno trovato"; | ||||||
|  | $_['text_primary_domain'] = "Dominio Principale"; | ||||||
|  | $_['text_search_domains'] = "Domini di ricerca"; | ||||||
|  | $_['text_search_domain_to_add'] = "Cerca un dominio da aggiungere"; | ||||||
|  |  | ||||||
|  | $_['text_space_projection'] = 'Previsione Spazio'; | ||||||
|  | $_['text_average_messages_day'] = 'Media dei messaggi per giorno'; | ||||||
|  | $_['text_average_message_size'] = 'Media dei Messaggi + Metadati + Dimensione Indice'; | ||||||
|  | $_['text_average_size_day'] = 'Media Dimensioni per Giorno'; | ||||||
|  | $_['text_partition_full'] = 'Lo spazio finirà tra'; | ||||||
|  | $_['text_usage_trend'] = 'Trend di Utilizzo'; | ||||||
|  | $_['text_usage_increasing'] = 'Crescente'; | ||||||
|  | $_['text_usage_decreasing'] = 'Decrescente'; | ||||||
|  | $_['text_usage_neutral'] = 'Neutrale'; | ||||||
|  | $_['text_accounting'] = 'Resoconto Archivio'; | ||||||
|  | $_['text_accounting_email'] = 'Resoconto email'; | ||||||
|  | $_['text_accounting_domain'] = 'Resoconto Domini'; | ||||||
|  |  | ||||||
|  | $_['text_options'] = 'Opzioni'; | ||||||
|  | $_['text_spam_flag'] = 'Messaggio categorizzato come SPAM'; | ||||||
|  | $_['text_attachment_flag'] = 'Il Messaggio ha degli allegati'; | ||||||
|  | $_['text_notes_flag'] = 'Il Messaggio ha delle Note'; | ||||||
|  | $_['text_tag_flag'] = 'Il Messaggio è Etichettato'; | ||||||
|  | $_['text_verified_flag'] = 'Il Messaggio è verificato'; | ||||||
|  | $_['text_unverified_flag'] = 'Verifica fallita sul messaggio'; | ||||||
|  | $_['text_bulk_download'] = 'Scarica le email selezionate'; | ||||||
|  | $_['text_clear'] = 'Cancella'; | ||||||
|  | $_['text_select_letter'] = 'Seleziona indirizzo da Lettera iniziale'; | ||||||
|  | $_['text_working'] = 'Working...'; | ||||||
|  |  | ||||||
|  | $_['text_use_browser_settings'] = 'Usa le impostazioni del browser'; | ||||||
|  |  | ||||||
|  | $_['text_sent'] = 'Inviato'; | ||||||
|  | $_['text_received'] = 'Ricevuto'; | ||||||
|  | $_['text_oldest_record'] = 'Record più vecchio'; | ||||||
|  | $_['text_newest_record'] = 'Record più nuovo'; | ||||||
|  | $_['text_items'] = 'Items'; | ||||||
|  | $_['text_average_size'] = 'Dimensioni medie'; | ||||||
|  |  | ||||||
|  | $_['text_return_to'] = 'Rispondi a'; | ||||||
|  | $_['text_error_message'] = 'Correggi i seguenti errori e reinvia.'; | ||||||
|  | $_['text_field_required'] = 'Campo richiesto.'; | ||||||
|  | $_['text_field_length'] = 'Questo campo deve essere piu lungo di ? caratteri.'; | ||||||
|  | $_['text_field_domain'] = 'Questo campo deve avere un dominio valido (es. - domain.com).'; | ||||||
|  | $_['text_field_colour'] = 'Questo campo deve avere un valido codice colore (es. - #fcfcfc).'; | ||||||
|  | $_['text_delete'] = 'Elimina'; | ||||||
|  | $_['text_confirm'] = 'Conferma'; | ||||||
|  | $_['text_user_delete_confirm_message'] = 'Vuoi eliminare questo utente?'; | ||||||
|  | $_['text_domain_delete_confirm_message'] = 'Vuoi eliminare il dominio?'; | ||||||
|  | $_['text_group_delete_confirm_message'] = 'Vuoi eliminare il gruppo?'; | ||||||
|  | $_['text_ldap_delete_confirm_message'] = 'Vuoi eliminare il LDAP?'; | ||||||
|  | $_['text_customer_delete_confirm_message'] = 'Vuoi eliminare il cliente?'; | ||||||
|  | $_['text_with_selected'] = 'Con i selezionati'; | ||||||
|  |  | ||||||
|  | $_['text_compliance_warning'] = 'È abilitata la cancellazione dei messaggi per cui il tuo archivio non soddisfa i requisiti di legge!'; | ||||||
							
								
								
									
										497
									
								
								webui/language/tw/messages.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										497
									
								
								webui/language/tw/messages.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,497 @@ | |||||||
|  | <?php | ||||||
|  |  | ||||||
|  | $_['text_60_minutes'] = "60 分鐘"; | ||||||
|  |  | ||||||
|  | $_['text_action'] = "動作"; | ||||||
|  | $_['text_active_incoming_queue'] = "活動 + 傳入佇列"; | ||||||
|  | $_['text_active_incoming_queue_sender'] = "活動 + 傳入佇列與寄件者"; | ||||||
|  | $_['text_ad_sync_status'] = "AD 同步狀態"; | ||||||
|  | $_['text_add'] = "新增"; | ||||||
|  | $_['text_add_new_email_address'] = "新增郵件位址"; | ||||||
|  | $_['text_add_new_domain'] = "新增網域"; | ||||||
|  | $_['text_add_new_entry'] = "新增項目"; | ||||||
|  | $_['text_add_new_group'] = "新增群組"; | ||||||
|  | $_['text_add_new_rule'] = "新增規則"; | ||||||
|  | $_['text_add_new_user_alias'] = "新增使用者"; | ||||||
|  | $_['text_add_policy'] = "新增政策"; | ||||||
|  | $_['text_administration'] = "管理"; | ||||||
|  | $_['text_admin_user'] = "管理者"; | ||||||
|  | $_['text_advanced'] = "進階"; | ||||||
|  | $_['text_advanced_search'] = "進階搜尋"; | ||||||
|  | $_['text_all'] = "所有"; | ||||||
|  | $_['text_any'] = "任一"; | ||||||
|  | $_['text_applied'] = "已套用"; | ||||||
|  | $_['text_apply_changes'] = "套用變更"; | ||||||
|  | $_['text_archive_size'] = "歸檔大小"; | ||||||
|  | $_['text_archive_size_before_compression'] = "Archive size before compression"; | ||||||
|  | $_['text_archived_messages'] = "已歸檔郵件"; | ||||||
|  | $_['text_archiving_rules'] = "歸檔規則"; | ||||||
|  | $_['text_assigned_email_addresses'] = "已指派郵件位址"; | ||||||
|  | $_['text_attachment'] = "附件"; | ||||||
|  | $_['text_attachment_name'] = "附件名稱"; | ||||||
|  | $_['text_attachment_size'] = "附件大小"; | ||||||
|  | $_['text_attachment_type'] = "附件類型"; | ||||||
|  | $_['text_audit'] = "稽核"; | ||||||
|  | $_['text_automated_search'] = "自動搜尋"; | ||||||
|  |  | ||||||
|  | $_['text_back'] = "返回"; | ||||||
|  | $_['text_background_colour'] = "背景顏色"; | ||||||
|  | $_['text_body'] = "內文"; | ||||||
|  | $_['text_branding_logo'] = "商標圖片"; | ||||||
|  | $_['text_branding_text'] = "商標文字"; | ||||||
|  | $_['text_branding_url'] = "商標網址"; | ||||||
|  | $_['text_bulk_edit_selected_uids'] = "批次修改已選取的 uid"; | ||||||
|  | $_['text_bulk_restore_selected_emails'] = "批次還原已選取的項目"; | ||||||
|  | $_['text_bulk_update_selected_uids'] = "批次更新已選擇的 uid"; | ||||||
|  |  | ||||||
|  | $_['text_cancel'] = "取消"; | ||||||
|  | $_['text_change_user_settings'] = "變更使用者設定"; | ||||||
|  | $_['text_clienthost'] = "Client host"; | ||||||
|  | $_['text_close'] = "關閉"; | ||||||
|  | $_['text_colour'] = "顏色"; | ||||||
|  | $_['text_compressed'] = "已壓縮"; | ||||||
|  | $_['text_confirm_to_reset_counters'] = "確認要重置計數器"; | ||||||
|  | $_['text_connection_failed'] = "連線失敗"; | ||||||
|  | $_['text_connection_ok'] = "連線成功"; | ||||||
|  | $_['text_contact_support'] = "連繫支援"; | ||||||
|  | $_['text_content_filter'] = "內容篩選器"; | ||||||
|  | $_['text_conversation_available'] = "可使用對話檢視"; | ||||||
|  | $_['text_copied'] = "Copied"; | ||||||
|  | $_['text_counters'] = "計數器"; | ||||||
|  | $_['text_cpu_load'] = "CPU 負載"; | ||||||
|  | $_['text_cpu_usage'] = "CPU 使用率"; | ||||||
|  | $_['text_create_new_secret'] = "建立新的密鑰"; | ||||||
|  | $_['text_create_note'] = "建立備註"; | ||||||
|  | $_['text_cumulative_counts'] = "累積計數"; | ||||||
|  | $_['text_customers'] = "Customers"; | ||||||
|  |  | ||||||
|  | $_['text_daily_quarantine_report'] = "每日隔離報表"; | ||||||
|  | $_['text_daily_quarantine_report_status'] = "每日隔離報表狀態"; | ||||||
|  | $_['text_daily_report'] = "每日報表"; | ||||||
|  | $_['text_daily_piler_report'] = "每日 Piler 報表"; | ||||||
|  | $_['text_database_emails'] = "在 piler 資料庫的郵件位址"; | ||||||
|  | $_['text_date'] = "日期"; | ||||||
|  | $_['text_date_from'] = "起始日期"; | ||||||
|  | $_['text_date_to'] = "結束日期"; | ||||||
|  | $_['text_days'] = "天"; | ||||||
|  | $_['text_days2'] = "天"; | ||||||
|  | $_['text_days_to_retain'] = "保留天數"; | ||||||
|  | $_['text_deferred_queue'] = "延遲佇列"; | ||||||
|  | $_['text_deferred_queue_sender'] = "延遲佇列與寄件者"; | ||||||
|  | $_['text_delay'] = "延遲"; | ||||||
|  | $_['text_delete_confirm_message'] = "您是否要刪除"; | ||||||
|  | $_['text_delete_reason'] = "移除原因"; | ||||||
|  | $_['text_deleted'] = "已刪除"; | ||||||
|  | $_['text_deleted_users'] = "已刪除"; | ||||||
|  | $_['text_deliver'] = "傳遞"; | ||||||
|  | $_['text_delivered'] = "已傳遞"; | ||||||
|  | $_['text_deliver_and_train_selected_messages'] = "Deliver and train selected messages"; | ||||||
|  | $_['text_deliver_and_train_selected_messages_as_ham'] = "Deliver and train selected messages AS HAM"; | ||||||
|  | $_['text_deliver_selected_messages'] = "傳遞已選擇的郵件"; | ||||||
|  | $_['text_description'] = "描述"; | ||||||
|  | $_['text_direction'] = "Direction"; | ||||||
|  | $_['text_disk_usage'] = "磁碟使用率"; | ||||||
|  | $_['text_disable'] = "停用"; | ||||||
|  | $_['text_disabled'] = "停用"; | ||||||
|  | $_['text_dn_asterisk_means_skip_sync'] = "萬用字元 (*) 表示這個使用者項目將不會包含在 AD 同步當中"; | ||||||
|  | $_['text_domain'] = "網域"; | ||||||
|  | $_['text_domains'] = "網域"; | ||||||
|  | $_['text_domainname'] = "網域名稱"; | ||||||
|  | $_['text_download_all_hits_as_eml'] = "全部下載 (EML)"; | ||||||
|  | $_['text_download_selected_hits_as_pdf'] = "下載已選取項目 (PDF)"; | ||||||
|  | $_['text_download_attachment2'] = "下載附件"; | ||||||
|  | $_['text_download_message'] = "下載 (EML)"; | ||||||
|  | $_['text_download_message2'] = "下載郵件"; | ||||||
|  |  | ||||||
|  | $_['text_edit'] = "編輯"; | ||||||
|  | $_['text_edit_entry'] = "編輯項目"; | ||||||
|  | $_['text_edit_group'] = "編輯群組"; | ||||||
|  | $_['text_edit_user'] = "編輯使用者"; | ||||||
|  | $_['text_edit_or_view'] = "編輯/檢視"; | ||||||
|  | $_['text_email'] = "郵件位址"; | ||||||
|  | $_['text_email_addresses'] = "郵件位址"; | ||||||
|  | $_['text_email_aliases'] = "郵件別名"; | ||||||
|  | $_['text_email_in_unknown_domain'] = "郵件位址在未知的網域"; | ||||||
|  | $_['text_empty_search_criteria'] = "'Empty criteria'"; | ||||||
|  | $_['text_empty_search_result'] = "沒有搜尋結果。請試著加入萬用字元 (*) 在關鍵字後方 (最小 " . MIN_PREFIX_LEN . " 個字元),例如 duplic* 以搜尋到 \"duplicate\", \"duplicated\", 之類的結果。"; | ||||||
|  | $_['text_enable'] = "啟用"; | ||||||
|  | $_['text_enabled'] = "啟用"; | ||||||
|  | $_['text_enter_google_authenticator_code'] = "輸入 Google Authenticator 驗證碼"; | ||||||
|  | $_['text_enter_one_email_address_per_line'] = "每一行輸入一個郵件位址"; | ||||||
|  | $_['text_enter_one_group_per_line'] = "每一行輸入一個群組"; | ||||||
|  | $_['text_enter_search_terms'] = "輸入您要搜尋的字詞"; | ||||||
|  | $_['text_error'] = "錯誤"; | ||||||
|  | $_['text_exact_domain_name_or_email_address'] = "確認您的網域名稱或郵件位址"; | ||||||
|  | $_['text_exclude'] = "排除"; | ||||||
|  | $_['text_existing'] = "現有"; | ||||||
|  | $_['text_existing_domains'] = "現有網域"; | ||||||
|  | $_['text_existing_email'] = "現有郵件"; | ||||||
|  | $_['text_existing_folders'] = "現有資料夾"; | ||||||
|  | $_['text_existing_groups'] = "現有群組"; | ||||||
|  | $_['text_existing_policies'] = "現有政策"; | ||||||
|  | $_['text_existing_entries'] = "現有項目"; | ||||||
|  | $_['text_existing_rules'] = "現有規則"; | ||||||
|  | $_['text_existing_user'] = "現有使用者"; | ||||||
|  | $_['text_existing_users'] = "現有使用者"; | ||||||
|  | $_['text_expert'] = "專家"; | ||||||
|  | $_['text_expert_search'] = "專家搜尋"; | ||||||
|  |  | ||||||
|  | $_['text_failed'] = "失敗"; | ||||||
|  | $_['text_failed_to_add'] = "新增失敗"; | ||||||
|  | $_['text_failed_to_change_password'] = "變更密碼失敗"; | ||||||
|  | $_['text_failed_to_deliver'] = "傳遞失敗"; | ||||||
|  | $_['text_failed_to_mark_for_removal'] = "標記移除失敗"; | ||||||
|  | $_['text_failed_to_modify'] = "修改失敗"; | ||||||
|  | $_['text_failed_to_remove'] = "移除失敗"; | ||||||
|  | $_['text_failed_to_restore'] = "還原失敗"; | ||||||
|  | $_['text_failed_to_update'] = "更新失敗"; | ||||||
|  | $_['text_first'] = "First"; | ||||||
|  | $_['text_folder'] = "資料夾"; | ||||||
|  | $_['text_folder_rules'] = "資料夾規則"; | ||||||
|  | $_['text_folders'] = "資料夾"; | ||||||
|  | $_['text_forward_selected_emails_to'] = "轉寄已選擇郵件至"; | ||||||
|  | $_['text_from'] = "寄件者"; | ||||||
|  | $_['text_from_domain'] = "寄件者網域"; | ||||||
|  |  | ||||||
|  | $_['text_google_authenticator_code'] = "Google Authenticator 驗證碼"; | ||||||
|  | $_['text_google_authenticator_settings'] = "Google Authenticator 設定"; | ||||||
|  | $_['text_group_id'] = "群組 id"; | ||||||
|  | $_['text_groupname'] = "群組名稱"; | ||||||
|  | $_['text_groups'] = "群組"; | ||||||
|  | $_['text_group_management'] = "群組管理"; | ||||||
|  | $_['text_group_membership'] = "群組成員"; | ||||||
|  |  | ||||||
|  | $_['text_health'] = "健康狀況"; | ||||||
|  | $_['text_health_monitor'] = "健康狀況監視器"; | ||||||
|  | $_['text_help'] = "說明"; | ||||||
|  | $_['text_history'] = "歷程"; | ||||||
|  | $_['text_home'] = "首頁"; | ||||||
|  |  | ||||||
|  | $_['text_image'] = "image"; | ||||||
|  | $_['text_import'] = "匯入"; | ||||||
|  | $_['text_import_job_delete_confirm_message'] = "您是否要刪除匯入作業"; | ||||||
|  | $_['text_import_users'] = "匯入使用者"; | ||||||
|  | $_['text_import_users_from_LDAP'] = "從 LDAP 匯入使用者"; | ||||||
|  | $_['text_inbound'] = "inbound"; | ||||||
|  | $_['text_indexer_job'] = "索引器作業"; | ||||||
|  | $_['text_install_sudo_apply'] = "加入下列內容到 /etc/sudoers: 'www-data ALL=NOPASSWD: /etc/init.d/rc.piler reload'"; | ||||||
|  | $_['text_internal'] = "internal"; | ||||||
|  | $_['text_invalid_data'] = "無效的資料"; | ||||||
|  | $_['text_invalid_email'] = "無效的郵件"; | ||||||
|  | $_['text_invalid_email_or_password'] = "無效的郵件或密碼"; | ||||||
|  | $_['text_invalid_gid'] = "無效的 gid"; | ||||||
|  | $_['text_invalid_password'] = "無效的密乸"; | ||||||
|  | $_['text_invalid_pin_code'] = "無效的 Pin 碼"; | ||||||
|  | $_['text_invalid_policy_group'] = "無效的政策群組"; | ||||||
|  | $_['text_invalid_policy_name'] = "無效的政策名稱"; | ||||||
|  | $_['text_invalid_policy_setting'] = "無效的政策設定"; | ||||||
|  | $_['text_invalid_uid'] = "無效的 uid"; | ||||||
|  | $_['text_invalid_username'] = "無效的使用者名稱"; | ||||||
|  | $_['text_ipaddr'] = "IP 位址"; | ||||||
|  |  | ||||||
|  | $_['text_language'] = "語言"; | ||||||
|  | $_['text_last'] = "Last"; | ||||||
|  | $_['text_last_activity'] = "最後活動"; | ||||||
|  | $_['text_last_update'] = "最後更新"; | ||||||
|  | $_['text_latest_emails'] = "最新郵件"; | ||||||
|  | $_['text_ldap'] = "LDAP"; | ||||||
|  | $_['text_ldap_auditor_member_dn'] = "稽核者成員 DN"; | ||||||
|  | $_['text_ldap_base_dn'] = "LDAP 基礎 DN"; | ||||||
|  | $_['text_ldap_bind_dn'] = "LDAP 繫結 DN"; | ||||||
|  | $_['text_ldap_bind_pw'] = "LDAP 繫結密碼"; | ||||||
|  | $_['text_ldap_host'] = "LDAP 主機"; | ||||||
|  | $_['text_ldap_type'] = "LDAP 類型"; | ||||||
|  | $_['text_legal_hold'] = "法務保存措施"; | ||||||
|  | $_['text_load'] = "載入"; | ||||||
|  | $_['text_loading'] = "載入中"; | ||||||
|  | $_['text_logged_in'] = "已登入"; | ||||||
|  | $_['text_logged_out'] = "您已登出"; | ||||||
|  | $_['text_login'] = "登入"; | ||||||
|  | $_['text_login2'] = "登入"; | ||||||
|  | $_['text_login_failed'] = "登入失敗"; | ||||||
|  | $_['text_login_via_google'] = "經由 Google 帳戶登入"; | ||||||
|  | $_['text_logout'] = "登出"; | ||||||
|  | $_['text_logout2'] = "登出"; | ||||||
|  |  | ||||||
|  | $_['text_maillog_status'] = "郵件記錄收集器狀態"; | ||||||
|  | $_['text_main_title'] = "clapf web UI"; | ||||||
|  | $_['text_mapped_domain'] = "對應網域"; | ||||||
|  | $_['text_mark_private'] = "隱私"; | ||||||
|  | $_['text_marked_for_removal'] = "郵件標示為移除"; | ||||||
|  | $_['text_memory_usage'] = "記憶體使用率"; | ||||||
|  | $_['text_message'] = "郵件"; | ||||||
|  | $_['text_messages'] = "郵件"; | ||||||
|  | $_['text_message_disposition'] = "郵件處理"; | ||||||
|  | $_['text_message_text'] = "郵件文字"; | ||||||
|  | $_['text_min_2_chars'] = "最小 2 個字元"; | ||||||
|  | $_['text_missing_data'] = "遺漏資料"; | ||||||
|  | $_['text_missing_password'] = "遺漏密碼"; | ||||||
|  | $_['text_modify'] = "修改"; | ||||||
|  | $_['text_monitor'] = "監視器"; | ||||||
|  | $_['text_months'] = "月"; | ||||||
|  | $_['text_monthly_report'] = "每月報表"; | ||||||
|  |  | ||||||
|  | $_['text_need_to_approve_removal'] = "移除需要核准"; | ||||||
|  | $_['text_new'] = "新增"; | ||||||
|  | $_['text_new_users'] = "新增"; | ||||||
|  | $_['text_next'] = "Next"; | ||||||
|  | $_['text_no_domain_found'] = '沒有找到網域'; | ||||||
|  | $_['text_no_email_found'] = '沒有找到郵件'; | ||||||
|  | $_['text_no_message_in_the_quarantine'] = "隔離區內沒有符合搜尋結果的郵件"; | ||||||
|  | $_['text_no_records'] = "沒有記錄"; | ||||||
|  | $_['text_no_selected_message'] = "沒有選擇郵件"; | ||||||
|  | $_['text_no_sender'] = "沒有寄件者"; | ||||||
|  | $_['text_no_spam_message_in_the_quarantine_yet'] = "隔離區中沒有垃圾郵件"; | ||||||
|  | $_['text_no_subject'] = "沒有主旨"; | ||||||
|  | $_['text_no_such_policy'] = "沒有政策"; | ||||||
|  | $_['text_non_existent_queue_directory'] = "您指定的佇列不存在"; | ||||||
|  | $_['text_non_existing_user'] = "無現有的使用者"; | ||||||
|  | $_['text_notes'] = "備註"; | ||||||
|  | $_['text_not_found'] = "沒有找到"; | ||||||
|  | $_['text_not_running'] = "未在執行中"; | ||||||
|  | $_['text_not_spam'] = "不是垃圾郵件"; | ||||||
|  | $_['title_not_found'] = "Page not found"; | ||||||
|  | $_['text_number_of_messages_in_quarantine'] = "隔離區內符合搜尋結果的郵件數量"; | ||||||
|  | $_['text_number_of_spam_messages_in_quarantine'] = "隔離區內符合搜尋結果的垃圾郵件數量"; | ||||||
|  |  | ||||||
|  | $_['text_off'] = "關閉"; | ||||||
|  | $_['text_on'] = "啟用"; | ||||||
|  | $_['text_online_users'] = "線上使用者"; | ||||||
|  | $_['text_other'] = "其它"; | ||||||
|  | $_['text_outbound'] = "outbound"; | ||||||
|  |  | ||||||
|  | $_['text_password'] = "密碼"; | ||||||
|  | $_['text_password_again'] = "再一次密碼"; | ||||||
|  | $_['text_password_changed'] = "密碼已變更"; | ||||||
|  | $_['text_password_mismatch'] = "密碼不符"; | ||||||
|  | $_['text_page_length'] = "每頁結果"; | ||||||
|  | $_['text_periodic_purge'] = "定期清理"; | ||||||
|  | $_['text_policy'] = "政策"; | ||||||
|  | $_['text_policy_group'] = "政策群組"; | ||||||
|  | $_['text_policy_name'] = "政策名稱"; | ||||||
|  | $_['text_previous'] = "Previous"; | ||||||
|  | $_['text_print_message'] = "列印"; | ||||||
|  | $_['text_private'] = "隱私"; | ||||||
|  | $_['text_processed_emails'] = "已處理郵件"; | ||||||
|  | $_['text_progress'] = "處理進度"; | ||||||
|  | $_['text_purge_all_messages_from_quarantine'] = "從隔離區清理您的所有郵件"; | ||||||
|  | $_['text_purge_selected_messages'] = "清理已選擇郵件"; | ||||||
|  | $_['text_purged'] = "清理"; | ||||||
|  |  | ||||||
|  | $_['text_qr_code'] = "QR code"; | ||||||
|  | $_['text_queue_status'] = "佇列狀態"; | ||||||
|  | $_['text_quick_search'] = "快速搜尋"; | ||||||
|  |  | ||||||
|  | $_['text_realname'] = "人員姓名"; | ||||||
|  | $_['text_recipient'] = "收件者"; | ||||||
|  | $_['text_ref'] = "參照"; | ||||||
|  | $_['text_refresh_period'] = "重新整理週期"; | ||||||
|  | $_['text_refresh_qr_code'] = "重新整理 QR code"; | ||||||
|  | $_['text_reject'] = "拒絕"; | ||||||
|  | $_['text_rejected_removal'] = "rejected removal"; | ||||||
|  | $_['text_reason_of_rejection'] = "拒絕原因"; | ||||||
|  | $_['text_relay_details'] = "轉送細節"; | ||||||
|  | $_['text_relay_status'] = "轉送狀態"; | ||||||
|  | $_['text_remove'] = "移除"; | ||||||
|  | $_['text_remove_domain'] = "移除網域"; | ||||||
|  | $_['text_remove_message'] = "移除郵件"; | ||||||
|  | $_['text_remove_message2'] = "移除郵件"; | ||||||
|  | $_['text_remove_request'] = "移除要求"; | ||||||
|  | $_['text_remove_selected_uids'] = "移除已選擇 uids"; | ||||||
|  | $_['text_remove_policy'] = "移除政策"; | ||||||
|  | $_['text_remove_rule'] = "移除規則"; | ||||||
|  | $_['text_remove_this_policy'] = "移除此政策"; | ||||||
|  | $_['text_remove_this_group'] = "移除此群組"; | ||||||
|  | $_['text_remove_this_user'] = "移除此使用者"; | ||||||
|  | $_['text_removed'] = "已移除"; | ||||||
|  | $_['text_reset_counters'] = "重置計數器"; | ||||||
|  | $_['text_restore'] = "還原"; | ||||||
|  | $_['text_restored'] = "已還原"; | ||||||
|  | $_['text_restore_message'] = "還原郵件"; | ||||||
|  | $_['text_restore_to_mailbox'] = "還原郵件至郵箱"; | ||||||
|  | $_['text_result'] = "結果"; | ||||||
|  | $_['text_retention_days'] = "保留天數"; | ||||||
|  | $_['text_retention_rules'] = "保留規則"; | ||||||
|  | $_['text_role'] = "角色"; | ||||||
|  | $_['text_running'] = "執行中"; | ||||||
|  |  | ||||||
|  | $_['text_save'] = "儲存"; | ||||||
|  | $_['text_saved'] = "已儲存"; | ||||||
|  | $_['text_save_search'] = "儲存搜尋"; | ||||||
|  | $_['text_save_search_terms'] = "搜尋字詞"; | ||||||
|  | $_['text_saved_search_terms'] = "搜尋字詞已儲存"; | ||||||
|  | $_['text_search'] = "搜尋"; | ||||||
|  | $_['text_search2'] = "搜尋"; | ||||||
|  | $_['text_search_emails'] = "搜尋郵件位址"; | ||||||
|  | $_['text_search_email_to_add'] = "搜尋郵件以加入"; | ||||||
|  | $_['text_search_expression'] = "搜尋語法"; | ||||||
|  | $_['text_search_folders'] = "搜尋資料夾"; | ||||||
|  | $_['text_search_folder_to_add'] = "搜尋資料夾以加入"; | ||||||
|  | $_['text_search_groups'] = "搜尋群組"; | ||||||
|  | $_['text_search_group_to_add'] = "搜尋群組以加入"; | ||||||
|  | $_['text_search_terms'] = "搜尋字詞"; | ||||||
|  | $_['text_select_action'] = "選擇動作"; | ||||||
|  | $_['text_select_all'] = "全部選擇"; | ||||||
|  | $_['text_select_image'] = "Select image"; | ||||||
|  | $_['text_select_recipients'] = "選擇收件者"; | ||||||
|  | $_['text_sender'] = "寄件者"; | ||||||
|  | $_['text_sending_domains'] = "寄件者網域"; | ||||||
|  | $_['text_server_name'] = "伺服器名稱"; | ||||||
|  | $_['text_server_operating_system'] = "作業系統"; | ||||||
|  | $_['text_set'] = "設定"; | ||||||
|  | $_['text_settings'] = "設定"; | ||||||
|  | $_['text_simple'] = "簡易"; | ||||||
|  | $_['text_simple_search'] = "簡易搜尋"; | ||||||
|  | $_['text_size'] = "大小"; | ||||||
|  | $_['text_smtp_status'] = "SMTP 狀態"; | ||||||
|  | $_['text_spam'] = "垃圾郵件"; | ||||||
|  | $_['text_spam2'] = "垃圾郵件"; | ||||||
|  | $_['text_statistics'] = "使用統計"; | ||||||
|  | $_['text_status'] = "狀態"; | ||||||
|  | $_['text_storage'] = "儲存"; | ||||||
|  | $_['text_subject'] = "主旨"; | ||||||
|  | $_['text_submit'] = "送出"; | ||||||
|  | $_['text_successful'] = "成功"; | ||||||
|  | $_['text_successfully_added'] = "新增成功"; | ||||||
|  | $_['text_successfully_delivered'] = "傳遞成功"; | ||||||
|  | $_['text_successfully_modified'] = "修改成功"; | ||||||
|  | $_['text_successfully_removed'] = "移除成功"; | ||||||
|  | $_['text_successfully_trained'] = "Successfully trained"; | ||||||
|  | $_['text_successfully_updated'] = "修改成功"; | ||||||
|  | $_['text_support_link'] = "支援連結"; | ||||||
|  | $_['text_swap_usage'] = "Swap 使用率"; | ||||||
|  |  | ||||||
|  | $_['text_tag_selected_messages'] = "標籤已選擇郵件"; | ||||||
|  | $_['text_tagged'] = "標籤"; | ||||||
|  | $_['text_tags'] = "標籤"; | ||||||
|  | $_['text_test_connection'] = "測試連線"; | ||||||
|  | $_['text_text'] = "文字"; | ||||||
|  | $_['text_text_colour'] = "文字顏色"; | ||||||
|  | $_['text_text2'] = "文字"; | ||||||
|  | $_['text_theme'] = "佈景主題"; | ||||||
|  | $_['text_time'] = "時間"; | ||||||
|  | $_['text_to'] = "收件者"; | ||||||
|  | $_['text_to_domain'] = "收件者網域"; | ||||||
|  | $_['text_too_short_password'] = "密碼太短"; | ||||||
|  | $_['text_total'] = "總計"; | ||||||
|  | $_['text_total_ratio'] = "總比例"; | ||||||
|  | $_['text_total_query_time'] = "總計 SQL 查詢時間"; | ||||||
|  | $_['text_total_users'] = "總計"; | ||||||
|  | $_['text_type'] = "類型"; | ||||||
|  |  | ||||||
|  | $_['text_uids'] = "uids"; | ||||||
|  | $_['text_unauthorized_domain'] = "未授權網域"; | ||||||
|  | $_['text_unauthorized_download_attachment'] = "未授權下載附件"; | ||||||
|  | $_['text_unauthorized_remove_message'] = "未授權移除郵件"; | ||||||
|  | $_['text_unauthorized_view_message'] = "未授權檢視郵件"; | ||||||
|  | $_['text_unknown'] = "未知"; | ||||||
|  | $_['text_update_retention_within_this_domain'] = "此網域內的更新保留數值"; | ||||||
|  | $_['text_update_selected_uids'] = "更新所選的 uid"; | ||||||
|  | $_['text_updated_records'] = "已更新記錄"; | ||||||
|  | $_['text_uptime'] = "開機時間"; | ||||||
|  | $_['text_user'] = "使用者"; | ||||||
|  | $_['text_users'] = "使用者"; | ||||||
|  | $_['text_user_id'] = "使用者 id"; | ||||||
|  | $_['text_user_auditor'] = "稽核者"; | ||||||
|  | $_['text_user_data_officer'] = "資料管理者"; | ||||||
|  | $_['text_user_domainadmin'] = "網域管理者"; | ||||||
|  | $_['text_user_management'] = "使用者管理"; | ||||||
|  | $_['text_user_masteradmin'] = "主要管理者"; | ||||||
|  | $_['text_user_read_only_admin'] = "唯讀管理者"; | ||||||
|  | $_['text_user_regular'] = "一般使用者"; | ||||||
|  | $_['text_userlist'] = "使用者清單"; | ||||||
|  | $_['text_username'] = "使用者名稱"; | ||||||
|  | $_['text_users_quarantine'] = "使用者的隔離區"; | ||||||
|  |  | ||||||
|  | $_['text_view_formatted_email'] = "檢視格式化郵件"; | ||||||
|  | $_['text_view_header'] = "檢視標頭"; | ||||||
|  | $_['text_view_headers'] = "檢視標頭"; | ||||||
|  | $_['text_view_journal'] = "日誌"; | ||||||
|  | $_['text_view_journal_envelope'] = "檢視信封"; | ||||||
|  | $_['text_view_message'] = "檢視郵件"; | ||||||
|  | $_['text_view_message2'] = "檢視郵件"; | ||||||
|  | $_['text_view_progress'] = "檢視進度"; | ||||||
|  | $_['text_view_raw_email'] = "檢視原始郵件"; | ||||||
|  | $_['text_view_user_quarantine'] = "檢視使用者的隔離區"; | ||||||
|  |  | ||||||
|  | $_['text_warning_about_default_policy'] = "預設政測可以在 clapf.conf 中設定"; | ||||||
|  | $_['text_wildcard_domains'] = "通用網域"; | ||||||
|  | $_['text_whitelist'] = "允許清單"; | ||||||
|  | $_['text_whitelist_settings'] = "允許清單設定"; | ||||||
|  | $_['text_with_attachment'] = "含附件"; | ||||||
|  | $_['text_without_attachment'] = "不含附件"; | ||||||
|  |  | ||||||
|  | $_['text_years'] = "年"; | ||||||
|  | $_['text_you_are'] = "您是"; | ||||||
|  | $_['text_you_are_not_admin'] = "您不是管理者"; | ||||||
|  |  | ||||||
|  |  | ||||||
|  | $_['rcvd'] = "接收郵件"; | ||||||
|  | $_['virus'] = "感染郵件"; | ||||||
|  | $_['duplicate'] = "重複郵件"; | ||||||
|  | $_['ignore'] = "忽略郵件"; | ||||||
|  | $_['counters_last_update'] = "計數器更新"; | ||||||
|  |  | ||||||
|  | $_['text_24_hours'] = "24 小時"; | ||||||
|  | $_['text_1_week'] = "1 週"; | ||||||
|  | $_['text_30_days'] = "30 天"; | ||||||
|  |  | ||||||
|  | $_['text_access_settings'] = '存取設定'; | ||||||
|  | $_['text_access_setting_explanation'] = "您可以存取自己的電子郵件。對於指定群組或網域的稽核者存取,請您與管理者連繫。"; | ||||||
|  | $_['text_display_settings'] = '顯示設定'; | ||||||
|  | $_['text_change_password'] = "變更密碼"; | ||||||
|  | $_['text_none_found'] = "沒有找到"; | ||||||
|  | $_['text_primary_domain'] = "主要網域"; | ||||||
|  | $_['text_search_domains'] = "搜尋網域"; | ||||||
|  | $_['text_search_domain_to_add'] = "搜尋網域以加入"; | ||||||
|  |  | ||||||
|  | $_['text_space_projection'] = '空間保護'; | ||||||
|  | $_['text_average_messages_day'] = '每天平均郵件'; | ||||||
|  | $_['text_average_message_size'] = '平均郵件 + 中繼資料 + 索引大小'; | ||||||
|  | $_['text_average_size_day'] = '每天平均大小'; | ||||||
|  | $_['text_partition_full'] = '磁區預計用完於'; | ||||||
|  | $_['text_usage_trend'] = '使用趨勢'; | ||||||
|  | $_['text_usage_increasing'] = '上升'; | ||||||
|  | $_['text_usage_decreasing'] = '下降'; | ||||||
|  | $_['text_usage_neutral'] = '持平'; | ||||||
|  | $_['text_accounting'] = '歸檔稽核'; | ||||||
|  | $_['text_accounting_email'] = '依郵件稽核'; | ||||||
|  | $_['text_accounting_domain'] = '依網域稽核'; | ||||||
|  |  | ||||||
|  | $_['text_options'] = '選項'; | ||||||
|  | $_['text_spam_flag'] = '郵件已標記為 SPAM'; | ||||||
|  | $_['text_attachment_flag'] = '郵件有附件'; | ||||||
|  | $_['text_notes_flag'] = '郵件有備註'; | ||||||
|  | $_['text_tag_flag'] = '郵件已標記'; | ||||||
|  | $_['text_verified_flag'] = '郵件已驗證'; | ||||||
|  | $_['text_unverified_flag'] = '郵件驗證失敗'; | ||||||
|  | $_['text_bulk_download'] = '批次下載已選擇郵件'; | ||||||
|  | $_['text_clear'] = '清除'; | ||||||
|  | $_['text_select_letter'] = '以開頭字母選擇'; | ||||||
|  | $_['text_working'] = '作業中...'; | ||||||
|  |  | ||||||
|  | $_['text_use_browser_settings'] = '使用瀏覽器設定'; | ||||||
|  |  | ||||||
|  | $_['text_sent'] = '寄送'; | ||||||
|  | $_['text_received'] = '已接收'; | ||||||
|  | $_['text_oldest_record'] = '最舊記錄'; | ||||||
|  | $_['text_newest_record'] = '最新記錄'; | ||||||
|  | $_['text_items'] = '項目'; | ||||||
|  | $_['text_average_size'] = '平均大小'; | ||||||
|  |  | ||||||
|  | $_['text_return_to'] = '回到'; | ||||||
|  | $_['text_error_message'] = '請更正以下錯誤後重新送出。'; | ||||||
|  | $_['text_field_required'] = '此為必填欄位。'; | ||||||
|  | $_['text_field_length'] = '這個欄位必須大於 ? 個字元。'; | ||||||
|  | $_['text_field_domain'] = '這個欄位必須填入網域 (例如 - domain.com)。'; | ||||||
|  | $_['text_field_colour'] = '這個欄位必須填入色碼 (例如 - #fcfcfc)。'; | ||||||
|  | $_['text_delete'] = '刪除'; | ||||||
|  | $_['text_confirm'] = '確認'; | ||||||
|  | $_['text_user_delete_confirm_message'] = '您要刪除使用者嗎'; | ||||||
|  | $_['text_domain_delete_confirm_message'] = '您要刪除網域嗎'; | ||||||
|  | $_['text_group_delete_confirm_message'] = '您要刪除群組嗎'; | ||||||
|  | $_['text_ldap_delete_confirm_message'] = '您要刪除 LDAP 項目嗎'; | ||||||
|  | $_['text_customer_delete_confirm_message'] = '您要刪除客戶嗎'; | ||||||
|  | $_['text_with_selected'] = '選擇項目'; | ||||||
|  |  | ||||||
|  | $_['text_compliance_warning'] = '刪除功能已啟用,因此這個歸檔不符合規定!'; | ||||||
| @@ -36,7 +36,7 @@ class ModelAccountingAccounting extends Model { | |||||||
|  |  | ||||||
|       // emails sent to users |       // emails sent to users | ||||||
|  |  | ||||||
|       $tousers = $this->db->query("SELECT `$column`-(`$column` % 86400) AS `day`, `to`, COUNT(*) AS `count`, SUM(`size`) AS `size` FROM " . VIEW_MESSAGES . " WHERE `$column` >= ? AND `$column` < ? GROUP BY FROM_UNIXTIME(`day`, '%Y.%m.%d.'), `to`", array($start, $stop)); |       $tousers = $this->db->query("SELECT `$column`-(`$column` % 86400) AS `day`, `to`, COUNT(*) AS `count`, SUM(`size`) AS `size` FROM " . VIEW_MESSAGES . " WHERE deleted=0 AND `$column` >= ? AND `$column` < ? GROUP BY FROM_UNIXTIME(`day`, '%Y.%m.%d.'), `to`", array($start, $stop)); | ||||||
|  |  | ||||||
|       foreach($tousers->rows as $row) { |       foreach($tousers->rows as $row) { | ||||||
|          $counter[$row['day']][$row['to']]['recd'] = $row['count']; |          $counter[$row['day']][$row['to']]['recd'] = $row['count']; | ||||||
| @@ -46,7 +46,7 @@ class ModelAccountingAccounting extends Model { | |||||||
|  |  | ||||||
|       // emails sent from users |       // emails sent from users | ||||||
|  |  | ||||||
|       $fromusers = $this->db->query("SELECT `$column`-(`$column` % 86400) AS `day`, `from`, COUNT(*) AS `count`, SUM(`size`) AS `size` FROM " . VIEW_MESSAGES . " WHERE `$column` >= ? AND `$column` < ? GROUP BY FROM_UNIXTIME(`day`, '%Y.%m.%d.'), `from`", array($start, $stop)); |       $fromusers = $this->db->query("SELECT `$column`-(`$column` % 86400) AS `day`, `from`, COUNT(*) AS `count`, SUM(`size`) AS `size` FROM " . VIEW_MESSAGES . " WHERE deleted=0 AND `$column` >= ? AND `$column` < ? GROUP BY FROM_UNIXTIME(`day`, '%Y.%m.%d.'), `from`", array($start, $stop)); | ||||||
|  |  | ||||||
|       foreach($fromusers->rows as $row) { |       foreach($fromusers->rows as $row) { | ||||||
|          $counter[$row['day']][$row['from']]['sent'] = $row['count']; |          $counter[$row['day']][$row['from']]['sent'] = $row['count']; | ||||||
| @@ -144,10 +144,6 @@ class ModelAccountingAccounting extends Model { | |||||||
|  |  | ||||||
|       $search = preg_replace("/\s{1,}/", "", $search); |       $search = preg_replace("/\s{1,}/", "", $search); | ||||||
|  |  | ||||||
|       if($search) { |  | ||||||
|          $search_cond .= " AND ( `email` LIKE '%".$search."%' OR `domain` LIKE '%".$search."%' )"; |  | ||||||
|       } |  | ||||||
|  |  | ||||||
|       $query = "SELECT `email` AS `item`, MIN(`date`) AS `oldest`, MAX(`date`) AS `newest`, SUM(`sent`) AS `sent`, SUM(`recd`) AS `recd`, SUM(`sentsize`) AS `sentsize`, SUM(`recdsize`) AS `recdsize` FROM " . TABLE_STAT_COUNTER; |       $query = "SELECT `email` AS `item`, MIN(`date`) AS `oldest`, MAX(`date`) AS `newest`, SUM(`sent`) AS `sent`, SUM(`recd`) AS `recd`, SUM(`sentsize`) AS `sentsize`, SUM(`recdsize`) AS `recdsize` FROM " . TABLE_STAT_COUNTER; | ||||||
|  |  | ||||||
|       if($item == 'email') { |       if($item == 'email') { | ||||||
|   | |||||||
| @@ -43,7 +43,7 @@ class ModelAuditAudit extends Model { | |||||||
|       if(Registry::get('admin_user') == 0 && RESTRICTED_AUDITOR == 1) { |       if(Registry::get('admin_user') == 0 && RESTRICTED_AUDITOR == 1) { | ||||||
|          $auditdomains = $session->get("auditdomains"); |          $auditdomains = $session->get("auditdomains"); | ||||||
|  |  | ||||||
|          while(list($k, $v) = each($auditdomains)) { |          foreach($auditdomains as $k => $v) { | ||||||
|             if($q) { $q .= ","; } |             if($q) { $q .= ","; } | ||||||
|             $q .= "?"; |             $q .= "?"; | ||||||
|             array_push($arr, $v); |             array_push($arr, $v); | ||||||
|   | |||||||
| @@ -76,7 +76,7 @@ class ModelGoogleGoogle extends Model { | |||||||
|  |  | ||||||
|          $messages = $storage->piler_batch_fetch($from, $to); |          $messages = $storage->piler_batch_fetch($from, $to); | ||||||
|  |  | ||||||
|          while(list($k, $v) = each($messages)) { |          foreach($messages as $k => $v) { | ||||||
|             $uuid = $storage->getUniqueId($k); |             $uuid = $storage->getUniqueId($k); | ||||||
|  |  | ||||||
|             $tmpname = "piler-" . $email . "-" . $k . "-" . $uuid . ".eml"; |             $tmpname = "piler-" . $email . "-" . $k . "-" . $uuid . ".eml"; | ||||||
| @@ -98,7 +98,7 @@ class ModelGoogleGoogle extends Model { | |||||||
|       } |       } | ||||||
|  |  | ||||||
|  |  | ||||||
|       syslog(LOG_INFO, "downloaded $count messages for $email");    |       syslog(LOG_INFO, "downloaded $count messages for $email"); | ||||||
|  |  | ||||||
|       return $count; |       return $count; | ||||||
|    } |    } | ||||||
| @@ -174,5 +174,3 @@ class ModelGoogleGoogle extends Model { | |||||||
|  |  | ||||||
|  |  | ||||||
| } | } | ||||||
|  |  | ||||||
| ?> |  | ||||||
|   | |||||||
| @@ -199,7 +199,7 @@ class ModelHealthHealth extends Model { | |||||||
|    public function meminfo() { |    public function meminfo() { | ||||||
|       $m = explode("\n", file_get_contents("/proc/meminfo")); |       $m = explode("\n", file_get_contents("/proc/meminfo")); | ||||||
|  |  | ||||||
|       while(list($k, $v) = each($m)) { |       foreach($m as $k => $v) { | ||||||
|          $a = preg_split("/\ {1,}/", $v); |          $a = preg_split("/\ {1,}/", $v); | ||||||
|          if(isset($a[0]) && $a[0]) { $_m[$a[0]] = $a[1]; } |          if(isset($a[0]) && $a[0]) { $_m[$a[0]] = $a[1]; } | ||||||
|       } |       } | ||||||
| @@ -219,7 +219,7 @@ class ModelHealthHealth extends Model { | |||||||
|  |  | ||||||
|       $partitions = Registry::get('partitions_to_monitor'); |       $partitions = Registry::get('partitions_to_monitor'); | ||||||
|  |  | ||||||
|       while(list($k, $v) = each($output)) { |       foreach($output as $k => $v) { | ||||||
|          if($k > 0) { |          if($k > 0) { | ||||||
|             $p = preg_split("/\ {1,}/", $v); |             $p = preg_split("/\ {1,}/", $v); | ||||||
|             if(isset($p[5]) && in_array($p[5], $partitions) && !isset($a[$p[5]])) { |             if(isset($p[5]) && in_array($p[5], $partitions) && !isset($a[$p[5]])) { | ||||||
|   | |||||||
| @@ -26,7 +26,7 @@ class ModelMailMail extends Model { | |||||||
|       fputs($r, "MAIL FROM: <$from>\r\n"); |       fputs($r, "MAIL FROM: <$from>\r\n"); | ||||||
|       $l = fgets($r, 4096); |       $l = fgets($r, 4096); | ||||||
|  |  | ||||||
|       while(list($k, $v) = each($to)) { |       foreach($to as $k => $v) { | ||||||
|          fputs($r, "RCPT TO: <$v>\r\n"); |          fputs($r, "RCPT TO: <$v>\r\n"); | ||||||
|          $l = fgets($r, 4096); |          $l = fgets($r, 4096); | ||||||
|       } |       } | ||||||
|   | |||||||
| @@ -213,7 +213,7 @@ class ModelSearchMessage extends Model { | |||||||
|       $a = explode(" ", $terms); |       $a = explode(" ", $terms); | ||||||
|       $terms = array(); |       $terms = array(); | ||||||
|  |  | ||||||
|       while(list($k, $v) = each($a)) { |       foreach($a as $k => $v) { | ||||||
|          if(strlen($v) >= 3 && !in_array($v, $fields)) { |          if(strlen($v) >= 3 && !in_array($v, $fields)) { | ||||||
|             $v = preg_replace("/\*/", "", $v); |             $v = preg_replace("/\*/", "", $v); | ||||||
|             if($v) { array_push($terms, $v); } |             if($v) { array_push($terms, $v); } | ||||||
| @@ -223,7 +223,7 @@ class ModelSearchMessage extends Model { | |||||||
|       if(count($terms) <= 0) { return $s; } |       if(count($terms) <= 0) { return $s; } | ||||||
|  |  | ||||||
|       if($html == 0) { |       if($html == 0) { | ||||||
|          while(list($k, $v) = each($terms)) { |          foreach($terms as $k => $v) { | ||||||
|             $s = preg_replace("/$v/i", "<span class=\"mssghglght\">$v</span>", $s); |             $s = preg_replace("/$v/i", "<span class=\"mssghglght\">$v</span>", $s); | ||||||
|          } |          } | ||||||
|  |  | ||||||
| @@ -233,7 +233,7 @@ class ModelSearchMessage extends Model { | |||||||
|       $tokens = preg_split("/\</", $s); |       $tokens = preg_split("/\</", $s); | ||||||
|       $s = ''; |       $s = ''; | ||||||
|  |  | ||||||
|       while(list($k, $token) = each($tokens)) { |       foreach($tokens as $k => $token) { | ||||||
|  |  | ||||||
|          $pos = strpos($token, ">"); |          $pos = strpos($token, ">"); | ||||||
|          if($pos > 0) { |          if($pos > 0) { | ||||||
| @@ -245,7 +245,7 @@ class ModelSearchMessage extends Model { | |||||||
|                $str = substr($token, $pos+1, $len); |                $str = substr($token, $pos+1, $len); | ||||||
|  |  | ||||||
|                reset($terms); |                reset($terms); | ||||||
|                while(list($k, $v) = each($terms)) { |                foreach($terms as $k => $v) { | ||||||
|                   $str = preg_replace("/$v/i", "<span class=\"mssghglght\">$v</span>", $str); |                   $str = preg_replace("/$v/i", "<span class=\"mssghglght\">$v</span>", $str); | ||||||
|                } |                } | ||||||
|  |  | ||||||
| @@ -365,13 +365,20 @@ class ModelSearchMessage extends Model { | |||||||
|  |  | ||||||
|          if($computed_hash == '') { |          if($computed_hash == '') { | ||||||
|  |  | ||||||
|             $query2 = $this->db->query("SELECT digest FROM " . TABLE_META . " WHERE id >= ? AND id <= ?", array($query->row['start_id'], $query->row['stop_id'])); |             $query2 = $this->db->query("SELECT digest FROM " . TABLE_META . " WHERE id >= ? AND id <= ? ORDER BY id", array($query->row['start_id'], $query->row['stop_id'])); | ||||||
|  |  | ||||||
|             foreach($query2->rows as $q) { |             foreach($query2->rows as $q) { | ||||||
|                $s .= $q['digest']; |                $s .= $q['digest']; | ||||||
|             } |             } | ||||||
|  |  | ||||||
|             $computed_hash = sha1($s); |             $len = strlen($query->row['hash_value']); | ||||||
|  |             if($len == 64) | ||||||
|  |                $algo='sha256'; | ||||||
|  |             elseif($len == 128) | ||||||
|  |                $algo='sha512'; | ||||||
|  |             else | ||||||
|  |                $algo='sha1'; | ||||||
|  |             $computed_hash = hash($algo, $s); | ||||||
|  |  | ||||||
|             if(MEMCACHED_ENABLED) { |             if(MEMCACHED_ENABLED) { | ||||||
|                $memcache->add($cache_key, $computed_hash, 0, MEMCACHED_TTL); |                $memcache->add($cache_key, $computed_hash, 0, MEMCACHED_TTL); | ||||||
|   | |||||||
| @@ -16,7 +16,7 @@ class ModelSearchSearch extends Model { | |||||||
|  |  | ||||||
|       $session = Registry::get('session'); |       $session = Registry::get('session'); | ||||||
|  |  | ||||||
|       while(list($k,$v) = each($data)) { |       foreach($data as $k => $v) { | ||||||
|          if($v) { if(is_array($v)) { $v = implode(" ", $v); } $s .= '&' . $k . '=' . $v; } |          if($v) { if(is_array($v)) { $v = implode(" ", $v); } $s .= '&' . $k . '=' . $v; } | ||||||
|       } |       } | ||||||
|  |  | ||||||
| @@ -113,11 +113,10 @@ class ModelSearchSearch extends Model { | |||||||
|       $session = Registry::get('session'); |       $session = Registry::get('session'); | ||||||
|  |  | ||||||
|       $i = 0; |       $i = 0; | ||||||
|       while(list($k, $v) = each($data['match'])) { |       foreach($data['match'] as $k => $v) { | ||||||
|          if($v == "@attachment_types") { |          if($v == "@attachment_types") { | ||||||
|             list($k, $v) = each($data['match']); |  | ||||||
|             $i++; |             $i++; | ||||||
|             if($v == "any") { |             if($data['match'][$i] == "any") { | ||||||
|                $data['match'][$i-1] = ""; |                $data['match'][$i-1] = ""; | ||||||
|                $data['match'][$i] = ""; |                $data['match'][$i] = ""; | ||||||
|             } |             } | ||||||
| @@ -199,7 +198,7 @@ class ModelSearchSearch extends Model { | |||||||
|  |  | ||||||
|       if(ENABLE_FOLDER_RESTRICTIONS == 1) { |       if(ENABLE_FOLDER_RESTRICTIONS == 1) { | ||||||
|          $s = explode(" ", $data['folders']); |          $s = explode(" ", $data['folders']); | ||||||
|          while(list($k,$v) = each($s)) { |          foreach($s as $k => $v) { | ||||||
|             if(in_array($v, $session->get("folders"))) { |             if(in_array($v, $session->get("folders"))) { | ||||||
|                array_push($__folders, $v); |                array_push($__folders, $v); | ||||||
|             } |             } | ||||||
| @@ -347,7 +346,7 @@ class ModelSearchSearch extends Model { | |||||||
|       $s = preg_replace("/httpX/", "http:", $s); |       $s = preg_replace("/httpX/", "http:", $s); | ||||||
|       $b = explode(" ", $s); |       $b = explode(" ", $s); | ||||||
|  |  | ||||||
|       while(list($k, $v) = each($b)) { |       foreach($b as $k => $v) { | ||||||
|          if($v == '') { continue; } |          if($v == '') { continue; } | ||||||
|  |  | ||||||
|          if($v == 'from:') { $token = 'match'; $a['match'][] = FROM_TOKEN; continue; } |          if($v == 'from:') { $token = 'match'; $a['match'][] = FROM_TOKEN; continue; } | ||||||
| @@ -441,7 +440,7 @@ class ModelSearchSearch extends Model { | |||||||
|       $offset = $page * $pagelen; |       $offset = $page * $pagelen; | ||||||
|  |  | ||||||
|       $s = explode(" ", $extra_folders); |       $s = explode(" ", $extra_folders); | ||||||
|       while(list($k,$v) = each($s)) { |       foreach($s as $k => $v) { | ||||||
|          if(in_array($v, $session->get("extra_folders")) && is_numeric($v)) { |          if(in_array($v, $session->get("extra_folders")) && is_numeric($v)) { | ||||||
|             array_push($__folders, $v); |             array_push($__folders, $v); | ||||||
|             if($q) { $q .= ",?"; } |             if($q) { $q .= ",?"; } | ||||||
| @@ -647,7 +646,9 @@ class ModelSearchSearch extends Model { | |||||||
|  |  | ||||||
|       $emails = $session->get($session_var); |       $emails = $session->get($session_var); | ||||||
|  |  | ||||||
|       while(list($k, $v) = each($emails)) { |       if(!$emails) { return $s; } | ||||||
|  |  | ||||||
|  |       foreach($emails as $k => $v) { | ||||||
|          if($s) { $s .= '| ' .  $this->fix_email_address_for_sphinx($v); } |          if($s) { $s .= '| ' .  $this->fix_email_address_for_sphinx($v); } | ||||||
|          else { $s = $this->fix_email_address_for_sphinx($v); } |          else { $s = $this->fix_email_address_for_sphinx($v); } | ||||||
|       } |       } | ||||||
| @@ -681,6 +682,13 @@ class ModelSearchSearch extends Model { | |||||||
|  |  | ||||||
|       if($id == '') { return 0; } |       if($id == '') { return 0; } | ||||||
|  |  | ||||||
|  |       if(Registry::get('data_officer') == 1) { | ||||||
|  |          $query = $this->db->query("SELECT id FROM " . TABLE_DELETED . " WHERE deleted=-1 AND id=?", array($id)); | ||||||
|  |          if(!isset($query->row['id'])) { | ||||||
|  |             return 0; | ||||||
|  |          } | ||||||
|  |       } | ||||||
|  |  | ||||||
|       if((Registry::get('auditor_user') == 1 || Registry::get('data_officer') == 1) && RESTRICTED_AUDITOR == 0) { return 1; } |       if((Registry::get('auditor_user') == 1 || Registry::get('data_officer') == 1) && RESTRICTED_AUDITOR == 0) { return 1; } | ||||||
|  |  | ||||||
|       $session = Registry::get('session'); |       $session = Registry::get('session'); | ||||||
| @@ -695,7 +703,7 @@ class ModelSearchSearch extends Model { | |||||||
|  |  | ||||||
|          $auditdomains = $session->get("auditdomains"); |          $auditdomains = $session->get("auditdomains"); | ||||||
|  |  | ||||||
|          while(list($k, $v) = each($auditdomains)) { |          foreach($auditdomains as $k => $v) { | ||||||
|             if(validdomain($v) == 1 && !in_array($v, $a)) { |             if(validdomain($v) == 1 && !in_array($v, $a)) { | ||||||
|                $q .= ",?"; |                $q .= ",?"; | ||||||
|                array_push($a, $v); |                array_push($a, $v); | ||||||
| @@ -711,7 +719,7 @@ class ModelSearchSearch extends Model { | |||||||
|  |  | ||||||
|          $emails = $session->get("emails"); |          $emails = $session->get("emails"); | ||||||
|  |  | ||||||
|          while(list($k, $v) = each($emails)) { |          foreach($emails as $k => $v) { | ||||||
|             if(validemail($v) == 1) { |             if(validemail($v) == 1) { | ||||||
|                $q .= ",?"; |                $q .= ",?"; | ||||||
|                array_push($a, $v); |                array_push($a, $v); | ||||||
| @@ -767,7 +775,7 @@ class ModelSearchSearch extends Model { | |||||||
|  |  | ||||||
|          $auditdomains = $session->get("auditdomains"); |          $auditdomains = $session->get("auditdomains"); | ||||||
|  |  | ||||||
|          while(list($k, $v) = each($auditdomains)) { |          foreach($auditdomains as $k => $v) { | ||||||
|             if(validdomain($v) == 1 && !in_array($v, $a)) { |             if(validdomain($v) == 1 && !in_array($v, $a)) { | ||||||
|                $q .= ",?"; |                $q .= ",?"; | ||||||
|                array_push($a, $v); |                array_push($a, $v); | ||||||
| @@ -778,7 +786,7 @@ class ModelSearchSearch extends Model { | |||||||
|          if(Registry::get('auditor_user') == 0) { |          if(Registry::get('auditor_user') == 0) { | ||||||
|             $emails = $session->get("emails"); |             $emails = $session->get("emails"); | ||||||
|  |  | ||||||
|             while(list($k, $v) = each($emails)) { |             foreach($emails as $k => $v) { | ||||||
|                if(validemail($v) == 1) { |                if(validemail($v) == 1) { | ||||||
|                   $q .= ",?"; |                   $q .= ",?"; | ||||||
|                   array_push($a, $v); |                   array_push($a, $v); | ||||||
| @@ -835,6 +843,10 @@ class ModelSearchSearch extends Model { | |||||||
|  |  | ||||||
|  |  | ||||||
|    public function fix_email_address_for_sphinx($email = '') { |    public function fix_email_address_for_sphinx($email = '') { | ||||||
|  |       if(strlen($email) > MAX_EMAIL_LEN) { | ||||||
|  |          return md5($email . ' '); | ||||||
|  |       } | ||||||
|  |  | ||||||
|       $email = preg_replace("/\|@/", "|", $email); |       $email = preg_replace("/\|@/", "|", $email); | ||||||
|       return preg_replace("/[\@\.\+\-\_]/", "X", $email); |       return preg_replace("/[\@\.\+\-\_]/", "X", $email); | ||||||
|    } |    } | ||||||
| @@ -906,7 +918,7 @@ class ModelSearchSearch extends Model { | |||||||
|       $a = explode(" ", $s); |       $a = explode(" ", $s); | ||||||
|       $s = ''; |       $s = ''; | ||||||
|  |  | ||||||
|       while(list($k, $v) = each($a)) { |       foreach($a as $k => $v) { | ||||||
|  |  | ||||||
|          if(substr($v, 0, 4) == 'http') { |          if(substr($v, 0, 4) == 'http') { | ||||||
|             $v = preg_replace("/http(s){0,1}\:\/\//", "__URL__", $v); |             $v = preg_replace("/http(s){0,1}\:\/\//", "__URL__", $v); | ||||||
|   | |||||||
| @@ -69,7 +69,7 @@ class ModelStatChart extends Model { | |||||||
|  |  | ||||||
|       if($query->num_rows >= 15) { |       if($query->num_rows >= 15) { | ||||||
|          $i = 0; |          $i = 0; | ||||||
|          while(list($k, $v) = each($dates)) { |          foreach($dates as $k => $v) { | ||||||
|             $i++; |             $i++; | ||||||
|             if($i % 3) { $dates[$k] = ""; } |             if($i % 3) { $dates[$k] = ""; } | ||||||
|          } |          } | ||||||
|   | |||||||
| @@ -155,7 +155,7 @@ class ModelUserImport extends Model { | |||||||
|  |  | ||||||
|       /* build a list of DNs to exclude from the import */ |       /* build a list of DNs to exclude from the import */ | ||||||
|  |  | ||||||
|       while (list($k, $v) = each($globals)) { |       foreach($globals as $k => $v) { | ||||||
|          if(preg_match("/^reject_/", $k)) { |          if(preg_match("/^reject_/", $k)) { | ||||||
|             $exclude[$v] = $v; |             $exclude[$v] = $v; | ||||||
|          } |          } | ||||||
|   | |||||||
| @@ -49,7 +49,7 @@ class ModelUserUser extends Model { | |||||||
|       $data = array(); |       $data = array(); | ||||||
|       $uids = $uid; |       $uids = $uid; | ||||||
|  |  | ||||||
|       if($uid > 0) { |       if($uid >= 0) { | ||||||
|          $query = $this->db->query("SELECT gid FROM " . TABLE_EMAIL_LIST . " WHERE uid=?", array((int)$uid)); |          $query = $this->db->query("SELECT gid FROM " . TABLE_EMAIL_LIST . " WHERE uid=?", array((int)$uid)); | ||||||
|  |  | ||||||
|          if(isset($query->rows)) { |          if(isset($query->rows)) { | ||||||
| @@ -68,9 +68,6 @@ class ModelUserUser extends Model { | |||||||
|  |  | ||||||
|       } |       } | ||||||
|  |  | ||||||
|       $emails = $this->get_email_addresses_from_groups($data); |  | ||||||
|       $data = array_merge($data, $emails); |  | ||||||
|  |  | ||||||
|       return $data; |       return $data; | ||||||
|    } |    } | ||||||
|  |  | ||||||
| @@ -559,7 +556,10 @@ class ModelUserUser extends Model { | |||||||
|       if(!$this->check_uid($uid)){ return 0; } |       if(!$this->check_uid($uid)){ return 0; } | ||||||
|  |  | ||||||
|       $query = $this->db->query("DELETE FROM " . TABLE_EMAIL . " WHERE uid=?", array((int)$uid)); |       $query = $this->db->query("DELETE FROM " . TABLE_EMAIL . " WHERE uid=?", array((int)$uid)); | ||||||
|  |       $query = $this->db->query("DELETE FROM " . TABLE_USER_SETTINGS . " WHERE username IN (SELECT username FROM " . TABLE_USER . " WHERE uid=?)", array((int)$uid)); | ||||||
|       $query = $this->db->query("DELETE FROM " . TABLE_USER . " WHERE uid=?", array((int)$uid)); |       $query = $this->db->query("DELETE FROM " . TABLE_USER . " WHERE uid=?", array((int)$uid)); | ||||||
|  |       $query = $this->db->query("DELETE FROM " . TABLE_DOMAIN_USER . " WHERE uid=?", array((int)$uid)); | ||||||
|  |       $query = $this->db->query("DELETE FROM " . TABLE_FOLDER_USER . " WHERE uid=?", array((int)$uid)); | ||||||
|  |  | ||||||
|       LOGGER("remove user: uid=$uid"); |       LOGGER("remove user: uid=$uid"); | ||||||
|  |  | ||||||
|   | |||||||
| @@ -2,11 +2,11 @@ | |||||||
| <phpunit colors="true"> | <phpunit colors="true"> | ||||||
|     <testsuites> |     <testsuites> | ||||||
|         <testsuite name="Application Test Suite"> |         <testsuite name="Application Test Suite"> | ||||||
|             <directory>./unit_tests/php</directory> |             <directory>./tests</directory> | ||||||
|         </testsuite> |         </testsuite> | ||||||
|     </testsuites> |     </testsuites> | ||||||
|     <php> |     <php> | ||||||
|         <env name="DIR_BASE" value="webui/" /> |         <env name="DIR_BASE" value="./" /> | ||||||
|         <env name="TEST_FILES_DIR" value="test_files/" /> |         <env name="TEST_FILES_DIR" value="../test_files/" /> | ||||||
|     </php> |     </php> | ||||||
| </phpunit> | </phpunit> | ||||||
| @@ -27,7 +27,9 @@ class Controller { | |||||||
|  |  | ||||||
|  |  | ||||||
|    public function args($args = array()){ |    public function args($args = array()){ | ||||||
|       while(list($key, $value) = each($args)) $this->data[$key] = $value; |       foreach($args as $key => $value) { | ||||||
|  |          $this->data[$key] = $value; | ||||||
|  |       } | ||||||
|    } |    } | ||||||
|  |  | ||||||
|  |  | ||||||
|   | |||||||
| @@ -12,6 +12,10 @@ class LDAP { | |||||||
|       ldap_set_option($this->link, LDAP_OPT_PROTOCOL_VERSION, 3); |       ldap_set_option($this->link, LDAP_OPT_PROTOCOL_VERSION, 3); | ||||||
|       ldap_set_option($this->link, LDAP_OPT_REFERRALS, 0); |       ldap_set_option($this->link, LDAP_OPT_REFERRALS, 0); | ||||||
|  |  | ||||||
|  |       if (LDAP_USE_START_TLS == 1) { | ||||||
|  |          ldap_start_tls($this->link); | ||||||
|  |       } | ||||||
|  |  | ||||||
|       if(@ldap_bind($this->link, $binddn, $bindpw)) { |       if(@ldap_bind($this->link, $binddn, $bindpw)) { | ||||||
|          $this->bind = 1; |          $this->bind = 1; | ||||||
|       } |       } | ||||||
|   | |||||||
| @@ -53,7 +53,7 @@ class MySQL { | |||||||
|  |  | ||||||
|       $R = $s->fetchAll(PDO::FETCH_ASSOC); |       $R = $s->fetchAll(PDO::FETCH_ASSOC); | ||||||
|  |  | ||||||
|       while(list ($k, $v) = each($R)){ |       foreach($R as $k => $v) { | ||||||
|          $data[$i] = $v; |          $data[$i] = $v; | ||||||
|          $i++; |          $i++; | ||||||
|       } |       } | ||||||
|   | |||||||
| @@ -39,13 +39,15 @@ class Sphinx { | |||||||
|       $s = $this->link->prepare($sql); |       $s = $this->link->prepare($sql); | ||||||
|       if(!$s) { return $query; } |       if(!$s) { return $query; } | ||||||
|  |  | ||||||
|       $s->execute($arr); |       if(!$s->execute($arr)) { | ||||||
|  |          syslog(LOG_INFO, $s->errorInfo()[2]); | ||||||
|  |       } | ||||||
|  |  | ||||||
|       $this->affected = $s->rowCount(); |       $this->affected = $s->rowCount(); | ||||||
|  |  | ||||||
|       $R = $s->fetchAll(); |       $R = $s->fetchAll(); | ||||||
|  |  | ||||||
|       while(list ($k, $v) = each($R)){ |       foreach($R as $k => $v) { | ||||||
|          $data[$i] = $v; |          $data[$i] = $v; | ||||||
|          $i++; |          $i++; | ||||||
|       } |       } | ||||||
| @@ -70,7 +72,7 @@ class Sphinx { | |||||||
|  |  | ||||||
|       $meta->execute(); |       $meta->execute(); | ||||||
|       $R = $meta->fetchAll(); |       $R = $meta->fetchAll(); | ||||||
|       while(list ($k, $v) = each($R)){ |       foreach($R as $k => $v) { | ||||||
|          if($v[0] == "total_found") { $query->total_found = $v[1]; } |          if($v[0] == "total_found") { $query->total_found = $v[1]; } | ||||||
|       } |       } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -47,7 +47,7 @@ class SQLite { | |||||||
|  |  | ||||||
|       $R = $s->fetchAll(); |       $R = $s->fetchAll(); | ||||||
|  |  | ||||||
|       while(list ($k, $v) = each($R)){ |       foreach($R as $k => $v) { | ||||||
|          $data[$i] = $v; |          $data[$i] = $v; | ||||||
|          $i++; |          $i++; | ||||||
|       } |       } | ||||||
|   | |||||||
| @@ -3923,7 +3923,7 @@ class HTMLPurifier_Encoder | |||||||
|  |  | ||||||
|         $len = strlen($str); |         $len = strlen($str); | ||||||
|         for ($i = 0; $i < $len; $i++) { |         for ($i = 0; $i < $len; $i++) { | ||||||
|             $in = ord($str{$i}); |             $in = ord($str[$i]); | ||||||
|             $char .= $str[$i]; // append byte to char |             $char .= $str[$i]; // append byte to char | ||||||
|             if (0 == $mState) { |             if (0 == $mState) { | ||||||
|                 // When mState is zero we expect either a US-ASCII character |                 // When mState is zero we expect either a US-ASCII character | ||||||
| @@ -14284,7 +14284,7 @@ class HTMLPurifier_ChildDef_Custom extends HTMLPurifier_ChildDef | |||||||
|     protected function _compileRegex() |     protected function _compileRegex() | ||||||
|     { |     { | ||||||
|         $raw = str_replace(' ', '', $this->dtd_regex); |         $raw = str_replace(' ', '', $this->dtd_regex); | ||||||
|         if ($raw{0} != '(') { |         if ($raw[0] != '(') { | ||||||
|             $raw = "($raw)"; |             $raw = "($raw)"; | ||||||
|         } |         } | ||||||
|         $el = '[#a-zA-Z0-9_.-]+'; |         $el = '[#a-zA-Z0-9_.-]+'; | ||||||
| @@ -20681,7 +20681,7 @@ class HTMLPurifier_TagTransform_Font extends HTMLPurifier_TagTransform | |||||||
|         if (isset($attr['size'])) { |         if (isset($attr['size'])) { | ||||||
|             // normalize large numbers |             // normalize large numbers | ||||||
|             if ($attr['size'] !== '') { |             if ($attr['size'] !== '') { | ||||||
|                 if ($attr['size']{0} == '+' || $attr['size']{0} == '-') { |                 if ($attr['size'][0] == '+' || $attr['size'][0] == '-') { | ||||||
|                     $size = (int)$attr['size']; |                     $size = (int)$attr['size']; | ||||||
|                     if ($size < -2) { |                     if ($size < -2) { | ||||||
|                         $attr['size'] = '-2'; |                         $attr['size'] = '-2'; | ||||||
|   | |||||||
| @@ -15,6 +15,11 @@ | |||||||
|  *  http://www.slproweb.com/products/Win32OpenSSL.html |  *  http://www.slproweb.com/products/Win32OpenSSL.html | ||||||
|  *  http://www.switch.ch/aai/support/howto/openssl-windows.html |  *  http://www.switch.ch/aai/support/howto/openssl-windows.html | ||||||
|  * |  * | ||||||
|  |  * 2021-10-26 Frank Schmirler: | ||||||
|  |  *  - extract certificate chain from TSResponse and feed into ts -verify as -untrusted | ||||||
|  |  *  - unlink temporary files | ||||||
|  |  *  - support for sha256 and sha512 hashes | ||||||
|  |  * | ||||||
|  * @version 0.3 |  * @version 0.3 | ||||||
|  * @author David M<>ller |  * @author David M<>ller | ||||||
|  * @package trustedtimestamps |  * @package trustedtimestamps | ||||||
| @@ -25,16 +30,22 @@ class TrustedTimestamps | |||||||
|     /** |     /** | ||||||
|      * Creates a Timestamp Requestfile from a hash |      * Creates a Timestamp Requestfile from a hash | ||||||
|      * |      * | ||||||
|      * @param string $hash: The hashed data (sha1) |      * @param string $hash: The hashed data (sha1, sha256 or sha512) | ||||||
|      * @return string: path of the created timestamp-requestfile |      * @return string: path of the created timestamp-requestfile | ||||||
|      */ |      */ | ||||||
|     public static function createRequestfile ($hash) |     public static function createRequestfile ($hash) | ||||||
|     { |     { | ||||||
|         if (strlen($hash) !== 40) |         if (strlen($hash) === 40) | ||||||
|  |             $digest="-sha1"; | ||||||
|  |         elseif (strlen($hash) === 64) | ||||||
|  |             $digest="-sha256"; | ||||||
|  |         elseif (strlen($hash) === 128) | ||||||
|  |             $digest="-sha512"; | ||||||
|  |         else | ||||||
|             throw new Exception("Invalid Hash."); |             throw new Exception("Invalid Hash."); | ||||||
|  |  | ||||||
|         $outfilepath = self::createTempFile(); |         $outfilepath = self::createTempFile(); | ||||||
|         $cmd = OPENSSL_BINARY . " ts -query -digest ".escapeshellarg($hash)." -cert -out ".escapeshellarg($outfilepath); |         $cmd = OPENSSL_BINARY . " ts -query $digest -digest ".escapeshellarg($hash)." -cert -out ".escapeshellarg($outfilepath); | ||||||
|  |  | ||||||
|         $retarray = array(); |         $retarray = array(); | ||||||
|         exec($cmd." 2>&1", $retarray, $retcode); |         exec($cmd." 2>&1", $retarray, $retcode); | ||||||
| @@ -106,6 +117,8 @@ class TrustedTimestamps | |||||||
|         $retarray = array(); |         $retarray = array(); | ||||||
|         exec($cmd." 2>&1", $retarray, $retcode); |         exec($cmd." 2>&1", $retarray, $retcode); | ||||||
|  |  | ||||||
|  |         unlink($responsefile); | ||||||
|  |  | ||||||
|         if ($retcode !== 0) |         if ($retcode !== 0) | ||||||
|             throw new Exception("The reply failed: ".implode(", ", $retarray)); |             throw new Exception("The reply failed: ".implode(", ", $retarray)); | ||||||
|  |  | ||||||
| @@ -144,7 +157,7 @@ class TrustedTimestamps | |||||||
|      */ |      */ | ||||||
|     public static function validate ($hash, $base64_response_string, $response_time, $tsa_cert_file) |     public static function validate ($hash, $base64_response_string, $response_time, $tsa_cert_file) | ||||||
|     { |     { | ||||||
|         if (strlen($hash) !== 40) |         if (strlen($hash) !== 40 && strlen($hash) !== 64 && strlen($hash) !== 128) | ||||||
|             throw new Exception("Invalid Hash"); |             throw new Exception("Invalid Hash"); | ||||||
|  |  | ||||||
|         $binary_response_string = base64_decode($base64_response_string); |         $binary_response_string = base64_decode($base64_response_string); | ||||||
| @@ -160,11 +173,22 @@ class TrustedTimestamps | |||||||
|  |  | ||||||
|         $responsefile = self::createTempFile($binary_response_string); |         $responsefile = self::createTempFile($binary_response_string); | ||||||
|  |  | ||||||
|         $cmd = OPENSSL_BINARY . " ts -verify -digest ".escapeshellarg($hash)." -in ".escapeshellarg($responsefile)." -CAfile ".escapeshellarg($tsa_cert_file); |         /* | ||||||
|  |          * extract chain from response | ||||||
|  |          * openssl ts -verify does not include them for verification despite of the man page stating otherwise | ||||||
|  |          */ | ||||||
|  |         $untrustedfile = self::createTempFile(); | ||||||
|  |         $cmd = OPENSSL_BINARY . " ts -reply -in ".escapeshellarg($responsefile)." -token_out | " . OPENSSL_BINARY . " pkcs7 -inform DER -print_certs -out ".escapeshellarg($untrustedfile); | ||||||
|  |         shell_exec($cmd); | ||||||
|  |  | ||||||
|  |         $cmd = OPENSSL_BINARY . " ts -verify -digest ".escapeshellarg($hash)." -in ".escapeshellarg($responsefile)." -CAfile ".escapeshellarg($tsa_cert_file)." -untrusted ".escapeshellarg($untrustedfile); | ||||||
|  |  | ||||||
|         $retarray = array(); |         $retarray = array(); | ||||||
|         exec($cmd." 2>&1", $retarray, $retcode); |         exec($cmd." 2>&1", $retarray, $retcode); | ||||||
|  |  | ||||||
|  |         unlink($untrustedfile); | ||||||
|  |         unlink($responsefile); | ||||||
|  |  | ||||||
|         /* |         /* | ||||||
|          * just 2 "normal" cases: |          * just 2 "normal" cases: | ||||||
|          *  1) Everything okay -> retcode 0 + retarray[0] == "Verification: OK" |          *  1) Everything okay -> retcode 0 + retarray[0] == "Verification: OK" | ||||||
|   | |||||||
| @@ -144,24 +144,13 @@ class Piler_Mime_Decode { | |||||||
|    public static function removeJournal(&$message, $EOL = "\n") { |    public static function removeJournal(&$message, $EOL = "\n") { | ||||||
|       $has_journal = 0; |       $has_journal = 0; | ||||||
|  |  | ||||||
|       $s = self::remove_LF($message); |       self::splitMessageRaw($message, $headers, $journal, $body); | ||||||
|       if(strpos($s, $EOL . $EOL)) { |  | ||||||
|          list($headers, $body) = explode($EOL . $EOL, $s, 2); |       if($journal) { | ||||||
|          if(strstr($headers, "\nX-MS-Journal-Report:")) { |          $has_journal = 1; | ||||||
|             return $has_journal; |  | ||||||
|          } |  | ||||||
|       } |       } | ||||||
|  |  | ||||||
|       $p = strstr($message, "\nX-MS-Journal-Report:"); |       $message = $headers . $EOL . $EOL . $body; | ||||||
|       if($p) { |  | ||||||
|          $q = stristr($p, "message/rfc822"); |  | ||||||
|          if($q) { |  | ||||||
|             $has_journal = 1; |  | ||||||
|             $i = strlen("message/rfc822"); |  | ||||||
|             while(ctype_space($q[$i])) { $i++; } |  | ||||||
|             if($i > 0) { $message = substr($q, $i); } |  | ||||||
|          } |  | ||||||
|       } |  | ||||||
|  |  | ||||||
|       return $has_journal; |       return $has_journal; | ||||||
|    } |    } | ||||||
| @@ -205,6 +194,8 @@ class Piler_Mime_Decode { | |||||||
|       for($i=0; $i<count(self::HEADER_FIELDS); $i++) { |       for($i=0; $i<count(self::HEADER_FIELDS); $i++) { | ||||||
|          if(!isset($headers[self::HEADER_FIELDS[$i]])) { $headers[self::HEADER_FIELDS[$i]] = ''; } |          if(!isset($headers[self::HEADER_FIELDS[$i]])) { $headers[self::HEADER_FIELDS[$i]] = ''; } | ||||||
|  |  | ||||||
|  |          $headers[self::HEADER_FIELDS[$i]] = preg_replace("/gb2312/i", "GBK", $headers[self::HEADER_FIELDS[$i]]); | ||||||
|  |  | ||||||
|          $headers[self::HEADER_FIELDS[$i]] = iconv_mime_decode($headers[self::HEADER_FIELDS[$i]], ICONV_MIME_DECODE_CONTINUE_ON_ERROR); |          $headers[self::HEADER_FIELDS[$i]] = iconv_mime_decode($headers[self::HEADER_FIELDS[$i]], ICONV_MIME_DECODE_CONTINUE_ON_ERROR); | ||||||
|       } |       } | ||||||
|  |  | ||||||
| @@ -264,7 +255,8 @@ class Piler_Mime_Decode { | |||||||
|  |  | ||||||
|       } |       } | ||||||
|  |  | ||||||
|       while(list($k, $v) = each($result)) { |       foreach($result as $k => $v) { | ||||||
|  |  | ||||||
|          if(strchr($v, "\n")) { |          if(strchr($v, "\n")) { | ||||||
|             $result[$k] = explode("\n", $v); |             $result[$k] = explode("\n", $v); | ||||||
|          } |          } | ||||||
| @@ -315,16 +307,19 @@ class Piler_Mime_Decode { | |||||||
|    public static function fixMimeBodyPart($headers = array(), $body = '') { |    public static function fixMimeBodyPart($headers = array(), $body = '') { | ||||||
|  |  | ||||||
|       if(isset($headers['content-transfer-encoding'])) { |       if(isset($headers['content-transfer-encoding'])) { | ||||||
|          if($headers['content-transfer-encoding'] == 'quoted-printable') { |          if(strtolower($headers['content-transfer-encoding']) == 'quoted-printable') { | ||||||
|             $body = quoted_printable_decode($body); |             $body = quoted_printable_decode($body); | ||||||
|          } |          } | ||||||
|  |  | ||||||
|          if($headers['content-transfer-encoding'] == 'base64') { |          if(strtolower($headers['content-transfer-encoding']) == 'base64') { | ||||||
|             $body = base64_decode($body); |             $body = base64_decode($body); | ||||||
|          } |          } | ||||||
|       } |       } | ||||||
|  |  | ||||||
|       if(isset($headers['content-type']['charset'])) { |       if(isset($headers['content-type']['charset'])) { | ||||||
|  |          if(strtolower($headers['content-type']['charset']) == 'gb2312') { | ||||||
|  |             $headers['content-type']['charset'] = 'GBK'; | ||||||
|  |          } | ||||||
|          $body = iconv($headers['content-type']['charset'], 'utf-8' . '//IGNORE', $body); |          $body = iconv($headers['content-type']['charset'], 'utf-8' . '//IGNORE', $body); | ||||||
|       } |       } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -17,7 +17,7 @@ class Language { | |||||||
|       else { |       else { | ||||||
|          $pref_langs = $this->get_preferred_languages(); |          $pref_langs = $this->get_preferred_languages(); | ||||||
|  |  | ||||||
|          while(list($k, $v) = each($pref_langs)) { |          foreach($pref_langs as $k => $v) { | ||||||
|             if(in_array($v, $langs)) { |             if(in_array($v, $langs)) { | ||||||
|                $lang = $v; |                $lang = $v; | ||||||
|                define('LANG', $lang); |                define('LANG', $lang); | ||||||
| @@ -53,7 +53,8 @@ class Language { | |||||||
|  |  | ||||||
|          $l = explode(";", $_SERVER['HTTP_ACCEPT_LANGUAGE']); |          $l = explode(";", $_SERVER['HTTP_ACCEPT_LANGUAGE']); | ||||||
|  |  | ||||||
|          while(list($k, $v) = each($l)) { |          foreach($l as $k => $v) { | ||||||
|  |  | ||||||
|             $a = explode(",", $v); |             $a = explode(",", $v); | ||||||
|  |  | ||||||
|             if(isset($a[0]) && substr($a[0], 0, 2) != 'q=') { |             if(isset($a[0]) && substr($a[0], 0, 2) != 'q=') { | ||||||
|   | |||||||
| @@ -147,16 +147,6 @@ function checkemail($email, $domains) { | |||||||
| function validemail($email = '') { | function validemail($email = '') { | ||||||
|    if($email == '') { return 0; } |    if($email == '') { return 0; } | ||||||
|  |  | ||||||
|    // sphinxsearch supports tokens up to 41 characters long |  | ||||||
|    // If there's a longer token in the query, then sphinx |  | ||||||
|    // reports a query error even if the query is itself correct |  | ||||||
|    // So the workaround is to get rid of these email addresses |  | ||||||
|    if(strlen($email) > MAX_EMAIL_LEN) { |  | ||||||
|       $msg = sprintf("discarding email %s: longer than %d", $email, MAX_EMAIL_LEN); |  | ||||||
|       syslog(LOG_INFO, $msg); |  | ||||||
|       return 0; |  | ||||||
|    } |  | ||||||
|  |  | ||||||
|    if(preg_match("/@local$/", $email)) { return 1; } |    if(preg_match("/@local$/", $email)) { return 1; } | ||||||
|  |  | ||||||
|    if(preg_match('/^[_a-zA-Z0-9-]+(\.[_a-zA-Z0-9-]+)*@[a-zA-Z0-9-]+(\.[a-zA-Z0-9-]+)*(\.[a-zA-Z]{2,10})$/', $email)) { |    if(preg_match('/^[_a-zA-Z0-9-]+(\.[_a-zA-Z0-9-]+)*@[a-zA-Z0-9-]+(\.[a-zA-Z0-9-]+)*(\.[a-zA-Z]{2,10})$/', $email)) { | ||||||
| @@ -196,7 +186,7 @@ function first_n_characters($what, $n){ | |||||||
|    $len = 0; |    $len = 0; | ||||||
|  |  | ||||||
|    $a = explode(" ", $what); |    $a = explode(" ", $what); | ||||||
|    while(list($k, $v) = each($a)){ |    foreach($a as $k => $v) { | ||||||
|       $x .= "$v "; $len += strlen($v) + 1; |       $x .= "$v "; $len += strlen($v) + 1; | ||||||
|       if($len >= $n){ return $x . "..."; } |       if($len >= $n){ return $x . "..."; } | ||||||
|    } |    } | ||||||
| @@ -279,7 +269,7 @@ function my_qp_encode($s){ | |||||||
|       $res = ""; |       $res = ""; | ||||||
|  |  | ||||||
|       $a = explode("\n", $s); |       $a = explode("\n", $s); | ||||||
|       while(list($k, $v) = each($a)){ |       foreach($a as $k => $v) { | ||||||
|          $part = ""; |          $part = ""; | ||||||
|  |  | ||||||
|          for($i=0; $i<strlen($v); $i++){ |          for($i=0; $i<strlen($v); $i++){ | ||||||
| @@ -417,7 +407,7 @@ function parse_string_to_array($s = '', $arr = array()) { | |||||||
|  |  | ||||||
|    parse_str($s, $a); |    parse_str($s, $a); | ||||||
|  |  | ||||||
|    while(list($k, $v) = each($a)) { |    foreach($a as $k => $v) { | ||||||
|       if(!isset($arr[$k]) || $arr[$k] == '') $arr[$k] = $v; |       if(!isset($arr[$k]) || $arr[$k] == '') $arr[$k] = $v; | ||||||
|    } |    } | ||||||
|  |  | ||||||
| @@ -453,7 +443,7 @@ function convert_date_string_to_ymd_by_template($date_string, $date_template) { | |||||||
|       return [$Y, $m, $d]; |       return [$Y, $m, $d]; | ||||||
|    } |    } | ||||||
|  |  | ||||||
|    while(list($k, $v) = each($template_array)) { |    foreach($template_array as $k => $v) { | ||||||
|       $$v = $date_array[$k]; |       $$v = $date_array[$k]; | ||||||
|    } |    } | ||||||
|  |  | ||||||
| @@ -613,7 +603,7 @@ function get_ldap_attribute_names($ldap_type = '') { | |||||||
|  |  | ||||||
|  |  | ||||||
| function htmlentities_on_array($arr = []) { | function htmlentities_on_array($arr = []) { | ||||||
|    while(list($k, $v) = each($arr)) { |    foreach($arr as $k => $v) { | ||||||
|       if(is_array($v)) { |       if(is_array($v)) { | ||||||
|          $arr[$k] = htmlentities_on_array($v); |          $arr[$k] = htmlentities_on_array($v); | ||||||
|       } else { |       } else { | ||||||
|   | |||||||
| @@ -3,6 +3,7 @@ | |||||||
| use PHPUnit\Framework\TestCase; | use PHPUnit\Framework\TestCase; | ||||||
| 
 | 
 | ||||||
| define('DIR_BASE', $_ENV['DIR_BASE']); | define('DIR_BASE', $_ENV['DIR_BASE']); | ||||||
|  | define('MAX_EMAIL_LEN', 41); | ||||||
| 
 | 
 | ||||||
| include_once(DIR_BASE . "system/model.php"); | include_once(DIR_BASE . "system/model.php"); | ||||||
| include_once(DIR_BASE . "model/search/search.php"); | include_once(DIR_BASE . "model/search/search.php"); | ||||||
| @@ -2,9 +2,9 @@ | |||||||
| 
 | 
 | ||||||
| use PHPUnit\Framework\TestCase; | use PHPUnit\Framework\TestCase; | ||||||
| 
 | 
 | ||||||
| include_once("webui/system/model.php"); | include_once("system/model.php"); | ||||||
| include_once("webui/system/misc.php"); | include_once("system/misc.php"); | ||||||
| include_once("webui/model/health/health.php"); | include_once("model/health/health.php"); | ||||||
| 
 | 
 | ||||||
| final class FormatTest extends TestCase | final class FormatTest extends TestCase | ||||||
| { | { | ||||||
| @@ -123,7 +123,7 @@ | |||||||
| 				<tr> | 				<tr> | ||||||
| 					<th colspan="2"><?php print $text_message_disposition; ?></th> | 					<th colspan="2"><?php print $text_message_disposition; ?></th> | ||||||
| 				</tr> | 				</tr> | ||||||
| 			   <?php while(list($k, $v) = each($health['counters'])) { | 			   <?php foreach($health['counters'] as $k => $v) { | ||||||
| 						if(!is_numeric($k)) { ?> | 						if(!is_numeric($k)) { ?> | ||||||
| 						   <tr> | 						   <tr> | ||||||
| 							  <td><?php $a = preg_replace("/^_piler\:/", "", $k); if(isset($$a)) { print $$a; } else { print $k; } ?></td> | 							  <td><?php $a = preg_replace("/^_piler\:/", "", $k); if(isset($$a)) { print $$a; } else { print $k; } ?></td> | ||||||
|   | |||||||
| @@ -36,7 +36,7 @@ | |||||||
|        <label class="control-label" for="ldap_type"><?php print $text_ldap_type; ?>:</label> |        <label class="control-label" for="ldap_type"><?php print $text_ldap_type; ?>:</label> | ||||||
|        <div class="controls"> |        <div class="controls"> | ||||||
|           <select name="ldap_type" id="ldap_type" onchange="Piler.fix_ldap_display();" class="span4"> |           <select name="ldap_type" id="ldap_type" onchange="Piler.fix_ldap_display();" class="span4"> | ||||||
|        <?php while(list($k, $v) = each($ldap_types)) { ?> |        <?php foreach($ldap_types as $k => $v) { ?> | ||||||
|           <option value="<?php print $v; ?>"<?php if(isset($a['ldap_type']) && $a['ldap_type'] == $v) { ?> selected="selected"<?php } ?>><?php print $v; ?></option> |           <option value="<?php print $v; ?>"<?php if(isset($a['ldap_type']) && $a['ldap_type'] == $v) { ?> selected="selected"<?php } ?>><?php print $v; ?></option> | ||||||
|        <?php } ?> |        <?php } ?> | ||||||
|           </select> |           </select> | ||||||
|   | |||||||
| @@ -91,7 +91,7 @@ | |||||||
|         <div class="controls"> |         <div class="controls"> | ||||||
|             <select class="ruleselect" name="folder_id"> |             <select class="ruleselect" name="folder_id"> | ||||||
|                <option value="0">-</option> |                <option value="0">-</option> | ||||||
|             <?php while(list($k,$v) = each($folders)) { ?> |             <?php foreach($folders as $k => $v) { ?> | ||||||
|                <option value="<?php print $k; ?>"><?php print $v; ?></option> |                <option value="<?php print $k; ?>"><?php print $v; ?></option> | ||||||
|             <?php } ?> |             <?php } ?> | ||||||
|             </select> |             </select> | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user