/* util-inet.c generated by valac 0.56.3, the Vala compiler
 * generated from util-inet.vala, do not modify */

/* Copyright 2016 Software Freedom Conservancy Inc.
 *
 * This software is licensed under the GNU Lesser General Public License
 * (version 2.1 or later).  See the COPYING file in this distribution.
 */

#include <stdlib.h>
#include <string.h>
#include <glib.h>
#include "geary-engine.h"
#include <gio/gio.h>

#define GEARY_INET_HOST_PART_REGEX "^(?!-)[\\p{L}\\p{N}-]{1,63}(?<!-)$"
#define GEARY_INET_IPv6_REGEX "^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][" \
"0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$|^(([a-zA-Z]|[a-zA-Z][a-zA-Z0-9\\-" \
"]*[a-zA-Z0-9])\\.)*([A-Za-z]|[A-Za-z][A-Za-z0-9\\-]*[A-Za-z0-9])$|^\\s" \
"*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}" \
"(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|" \
"2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A" \
"-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]" \
"|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9" \
"A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\\d|1\\d\\d|" \
"[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(([0-9A-" \
"Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:(" \
"(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1" \
"-9]?\\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|" \
"((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(2" \
"5[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(" \
"((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\\" \
"d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:)" \
")|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[" \
"0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3" \
"}))|:)))(%.+)?\\s*$"

#define _g_free0(var) (var = (g_free (var), NULL))
#define _g_regex_unref0(var) ((var == NULL) ? NULL : (var = (g_regex_unref (var), NULL)))
#define _g_error_free0(var) ((var == NULL) ? NULL : (var = (g_error_free (var), NULL)))

static void _vala_array_destroy (gpointer array,
                          gssize array_length,
                          GDestroyNotify destroy_func);
static void _vala_array_free (gpointer array,
                       gssize array_length,
                       GDestroyNotify destroy_func);
static gssize _vala_array_length (gpointer array);

/**
 * Formats a socket address as a "name:port" string.
 */
gchar*
geary_inet_address_to_string (GInetSocketAddress* addr)
{
	GInetAddress* _tmp0_;
	GInetAddress* _tmp1_;
	gchar* _tmp2_;
	gchar* _tmp3_;
	guint _tmp4_;
	guint _tmp5_;
	gchar* _tmp6_;
	gchar* _tmp7_;
	gchar* result;
	g_return_val_if_fail (G_TYPE_CHECK_INSTANCE_TYPE (addr, g_inet_socket_address_get_type ()), NULL);
	_tmp0_ = g_inet_socket_address_get_address (addr);
	_tmp1_ = _tmp0_;
	_tmp2_ = g_inet_address_to_string (_tmp1_);
	_tmp3_ = _tmp2_;
	_tmp4_ = g_inet_socket_address_get_port (addr);
	_tmp5_ = _tmp4_;
	_tmp6_ = g_strdup_printf ("%s:%u", _tmp3_, _tmp5_);
	_tmp7_ = _tmp6_;
	_g_free0 (_tmp3_);
	result = _tmp7_;
	return result;
}

/**
 * Determines if a string represents a valid host name or IP address.
 *
 * This function validates a host name or IP address for display,
 * i.e. without IDN or URI encoding. It simply performs a syntactic
 * check, it does not attempt to resolve the host name. Note that both
 * valid IPv4 addresses (such as "123.0.10.100") and invalid IPv4
 * addresses (such as "123" or "555.123.456.789") are valid host
 * names, so it is not possible to determine if an IPv4 address is
 * invalid.
 */
static gchar
string_get (const gchar* self,
            glong index)
{
	gchar _tmp0_;
	gchar result;
	g_return_val_if_fail (self != NULL, '\0');
	_tmp0_ = ((gchar*) self)[index];
	result = _tmp0_;
	return result;
}

static gchar*
string_slice (const gchar* self,
              glong start,
              glong end)
{
	glong string_length = 0L;
	gint _tmp0_;
	gint _tmp1_;
	gboolean _tmp2_ = FALSE;
	gboolean _tmp3_ = FALSE;
	gchar* _tmp4_;
	gchar* result;
	g_return_val_if_fail (self != NULL, NULL);
	_tmp0_ = strlen (self);
	_tmp1_ = _tmp0_;
	string_length = (glong) _tmp1_;
	if (start < ((glong) 0)) {
		start = string_length + start;
	}
	if (end < ((glong) 0)) {
		end = string_length + end;
	}
	if (start >= ((glong) 0)) {
		_tmp2_ = start <= string_length;
	} else {
		_tmp2_ = FALSE;
	}
	g_return_val_if_fail (_tmp2_, NULL);
	if (end >= ((glong) 0)) {
		_tmp3_ = end <= string_length;
	} else {
		_tmp3_ = FALSE;
	}
	g_return_val_if_fail (_tmp3_, NULL);
	g_return_val_if_fail (start <= end, NULL);
	_tmp4_ = g_strndup (((gchar*) self) + start, (gsize) (end - start));
	result = _tmp4_;
	return result;
}

gboolean
geary_inet_is_valid_display_host (gchar* name)
{
	gboolean is_valid = FALSE;
	GError* _inner_error0_ = NULL;
	gboolean result;
	is_valid = FALSE;
	if (!geary_string_is_empty (name)) {
		gint _tmp0_;
		gint _tmp1_;
		_tmp0_ = strlen (name);
		_tmp1_ = _tmp0_;
		if (_tmp1_ <= 253) {
			gint _tmp2_;
			gint _tmp3_;
			_tmp2_ = strlen (name);
			_tmp3_ = _tmp2_;
			if (string_get (name, (glong) (_tmp3_ - 1)) == '.') {
				gchar* _tmp4_;
				_tmp4_ = string_slice (name, (glong) 0, (glong) -1);
				_g_free0 (name);
				name = _tmp4_;
			}
			{
				GRegex* part_regex = NULL;
				GRegex* _tmp5_;
				gchar** _tmp6_;
				gchar** _tmp7_;
				_tmp5_ = g_regex_new (GEARY_INET_HOST_PART_REGEX, 0, 0, &_inner_error0_);
				part_regex = _tmp5_;
				if (G_UNLIKELY (_inner_error0_ != NULL)) {
					goto __catch0_g_error;
				}
				is_valid = TRUE;
				_tmp7_ = _tmp6_ = g_strsplit (name, ".", 0);
				{
					gchar** part_collection = NULL;
					gint part_collection_length1 = 0;
					gint _part_collection_size_ = 0;
					gint part_it = 0;
					part_collection = _tmp7_;
					part_collection_length1 = _vala_array_length (_tmp6_);
					for (part_it = 0; part_it < part_collection_length1; part_it = part_it + 1) {
						gchar* _tmp8_;
						gchar* part = NULL;
						_tmp8_ = g_strdup (part_collection[part_it]);
						part = _tmp8_;
						{
							GRegex* _tmp9_;
							const gchar* _tmp10_;
							_tmp9_ = part_regex;
							_tmp10_ = part;
							if (!g_regex_match (_tmp9_, _tmp10_, 0, NULL)) {
								is_valid = FALSE;
								_g_free0 (part);
								break;
							}
							_g_free0 (part);
						}
					}
					part_collection = (_vala_array_free (part_collection, part_collection_length1, (GDestroyNotify) g_free), NULL);
				}
				_g_regex_unref0 (part_regex);
			}
			goto __finally0;
			__catch0_g_error:
			{
				GError* err = NULL;
				GError* _tmp11_;
				const gchar* _tmp12_;
				err = _inner_error0_;
				_inner_error0_ = NULL;
				_tmp11_ = err;
				_tmp12_ = _tmp11_->message;
				g_debug ("util-inet.vala:48: Error validating as host name: %s", _tmp12_);
				_g_error_free0 (err);
			}
			__finally0:
			if (G_UNLIKELY (_inner_error0_ != NULL)) {
				gboolean _tmp13_ = FALSE;
				_g_free0 (name);
				g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, __LINE__, _inner_error0_->message, g_quark_to_string (_inner_error0_->domain), _inner_error0_->code);
				g_clear_error (&_inner_error0_);
				return _tmp13_;
			}
		}
		if (!is_valid) {
			{
				GRegex* address_regex = NULL;
				GRegex* _tmp14_;
				GRegex* _tmp15_;
				_tmp14_ = g_regex_new (GEARY_INET_IPv6_REGEX, G_REGEX_CASELESS, 0, &_inner_error0_);
				address_regex = _tmp14_;
				if (G_UNLIKELY (_inner_error0_ != NULL)) {
					goto __catch1_g_error;
				}
				_tmp15_ = address_regex;
				is_valid = g_regex_match (_tmp15_, name, 0, NULL);
				_g_regex_unref0 (address_regex);
			}
			goto __finally1;
			__catch1_g_error:
			{
				GError* err = NULL;
				GError* _tmp16_;
				const gchar* _tmp17_;
				err = _inner_error0_;
				_inner_error0_ = NULL;
				_tmp16_ = err;
				_tmp17_ = _tmp16_->message;
				g_debug ("util-inet.vala:60: Error validating as IPv6 address: %s", _tmp17_);
				_g_error_free0 (err);
			}
			__finally1:
			if (G_UNLIKELY (_inner_error0_ != NULL)) {
				gboolean _tmp18_ = FALSE;
				_g_free0 (name);
				g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, __LINE__, _inner_error0_->message, g_quark_to_string (_inner_error0_->domain), _inner_error0_->code);
				g_clear_error (&_inner_error0_);
				return _tmp18_;
			}
		}
	}
	result = is_valid;
	_g_free0 (name);
	return result;
}

static void
_vala_array_destroy (gpointer array,
                     gssize array_length,
                     GDestroyNotify destroy_func)
{
	if ((array != NULL) && (destroy_func != NULL)) {
		gssize i;
		for (i = 0; i < array_length; i = i + 1) {
			if (((gpointer*) array)[i] != NULL) {
				destroy_func (((gpointer*) array)[i]);
			}
		}
	}
}

static void
_vala_array_free (gpointer array,
                  gssize array_length,
                  GDestroyNotify destroy_func)
{
	_vala_array_destroy (array, array_length, destroy_func);
	g_free (array);
}

static gssize
_vala_array_length (gpointer array)
{
	gssize length;
	length = 0;
	if (array) {
		while (((gpointer*) array)[length]) {
			length++;
		}
	}
	return length;
}

