aboutsummaryrefslogtreecommitdiffstats
path: root/lib/ephy-string.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/ephy-string.c')
-rw-r--r--lib/ephy-string.c240
1 files changed, 240 insertions, 0 deletions
diff --git a/lib/ephy-string.c b/lib/ephy-string.c
index 391ad9b39..4dc8d8e9a 100644
--- a/lib/ephy-string.c
+++ b/lib/ephy-string.c
@@ -26,6 +26,8 @@
#include <string.h>
#include <stdlib.h>
#include <glib.h>
+#include <sys/types.h>
+#include <pwd.h>
#define ELLIPSIS "\xe2\x80\xa6"
@@ -286,3 +288,241 @@ ephy_string_enum_to_string (GType type,
return retval;
}
+
+/* Following code copied from gnome-vfs-private-utils.c */
+
+static int
+find_next_slash (const char *path, int current_offset)
+{
+ const char *match;
+
+ g_assert (current_offset <= strlen (path));
+
+ match = strchr (path + current_offset, G_DIR_SEPARATOR);
+ return match == NULL ? -1 : match - path;
+}
+
+static int
+find_slash_before_offset (const char *path, int to)
+{
+ int result;
+ int next_offset;
+
+ result = -1;
+ next_offset = 0;
+ for (;;) {
+ next_offset = find_next_slash (path, next_offset);
+ if (next_offset < 0 || next_offset >= to) {
+ break;
+ }
+ result = next_offset;
+ next_offset++;
+ }
+ return result;
+}
+
+static void
+collapse_slash_runs (char *path, int from_offset)
+{
+ int i;
+ /* Collapse multiple `/'s in a row. */
+ for (i = from_offset;; i++) {
+ if (path[i] != G_DIR_SEPARATOR) {
+ break;
+ }
+ }
+
+ if (from_offset < i) {
+ memmove (path + from_offset, path + i, strlen (path + i) + 1);
+ i = from_offset + 1;
+ }
+}
+
+/* Canonicalize path, and return a new path. Do everything in situ. The new
+ path differs from path in:
+
+ Multiple `/'s are collapsed to a single `/'.
+ Leading `./'s and trailing `/.'s are removed.
+ Non-leading `../'s and trailing `..'s are handled by removing
+ portions of the path. */
+char *
+ephy_string_canonicalize_pathname (const char *cpath)
+{
+ char *path;
+ int i, marker;
+
+ path = g_strdup (cpath);
+
+ if (path == NULL || strlen (path) == 0) {
+ return "";
+ }
+
+ /* Walk along path looking for things to compact. */
+ for (i = 0, marker = 0;;) {
+ if (!path[i])
+ break;
+
+ /* Check for `../', `./' or trailing `.' by itself. */
+ if (path[i] == '.') {
+ /* Handle trailing `.' by itself. */
+ if (path[i + 1] == '\0') {
+ if (i > 1 && path[i - 1] == G_DIR_SEPARATOR) {
+ /* strip the trailing /. */
+ path[i - 1] = '\0';
+ } else {
+ /* convert path "/." to "/" */
+ path[i] = '\0';
+ }
+ break;
+ }
+
+ /* Handle `./'. */
+ if (path[i + 1] == G_DIR_SEPARATOR) {
+ memmove (path + i, path + i + 2,
+ strlen (path + i + 2) + 1);
+ if (i == 0) {
+ /* don't leave leading '/' for paths that started
+ * as relative (.//foo)
+ */
+ collapse_slash_runs (path, i);
+ marker = 0;
+ }
+ continue;
+ }
+
+ /* Handle `../' or trailing `..' by itself.
+ * Remove the previous xxx/ part
+ */
+ if (path[i + 1] == '.'
+ && (path[i + 2] == G_DIR_SEPARATOR
+ || path[i + 2] == '\0')) {
+
+ /* ignore ../ at the beginning of a path */
+ if (i != 0) {
+ marker = find_slash_before_offset (path, i - 1);
+
+ /* Either advance past '/' or point to the first character */
+ marker ++;
+ if (path [i + 2] == '\0' && marker > 1) {
+ /* If we are looking at a /.. at the end of the uri and we
+ * need to eat the last '/' too.
+ */
+ marker--;
+ }
+ g_assert(marker < i);
+
+ if (path[i + 2] == G_DIR_SEPARATOR) {
+ /* strip the entire ../ string */
+ i++;
+ }
+
+ memmove (path + marker, path + i + 2,
+ strlen (path + i + 2) + 1);
+ i = marker;
+ } else {
+ i = 2;
+ if (path[i] == G_DIR_SEPARATOR) {
+ i++;
+ }
+ }
+ collapse_slash_runs (path, i);
+ continue;
+ }
+ }
+
+ /* advance to the next '/' */
+ i = find_next_slash (path, i);
+
+ /* If we didn't find any slashes, then there is nothing left to do. */
+ if (i < 0) {
+ break;
+ }
+
+ marker = i++;
+ collapse_slash_runs (path, i);
+ }
+ return path;
+}
+
+/* End of copied code */
+
+char *
+ephy_string_get_host_name (const char *url)
+{
+ const char *start;
+ const char *p;
+
+ if (url == NULL || g_str_has_prefix (url, "file://")) return NULL;
+
+ start = strstr (url, "//");
+ if (start == NULL || start == '\0')
+ {
+ /* Not an URL */
+ return NULL;
+ }
+ if (strlen (start) > 2)
+ {
+ /* Go past the protocol part */
+ start = start + 2;
+ }
+ else
+ {
+ /* Not an URL again */
+ return NULL;
+ }
+ p = strchr (start, '@');
+ if (p != NULL)
+ {
+ /* We have a username:password@hostname scheme, skip it. */
+ if (strlen (p) > 1) start = ++p;
+ }
+ p = strchr (start, ':');
+ if (p != NULL)
+ {
+ /* hostname:port, skip port */
+ return g_strndup (start, (p - start));
+ }
+ p = strchr (start, '/');
+ if (p == NULL)
+ {
+ /* No more slashes in the url, we assume it's a host name */
+ return g_strdup (start);
+ }
+
+ return g_strndup (start, (p - start));
+}
+
+char *
+ephy_string_expand_initial_tilde (const char *path)
+{
+ char *slash_after_user_name, *user_name;
+ struct passwd *passwd_file_entry;
+
+ g_return_val_if_fail (path != NULL, NULL);
+
+ if (path[0] != '~') {
+ return g_strdup (path);
+ }
+
+ if (path[1] == '/' || path[1] == '\0') {
+ return g_strconcat (g_get_home_dir (), &path[1], NULL);
+ }
+
+ slash_after_user_name = strchr (&path[1], '/');
+ if (slash_after_user_name == NULL) {
+ user_name = g_strdup (&path[1]);
+ } else {
+ user_name = g_strndup (&path[1],
+ slash_after_user_name - &path[1]);
+ }
+ passwd_file_entry = getpwnam (user_name);
+ g_free (user_name);
+
+ if (passwd_file_entry == NULL || passwd_file_entry->pw_dir == NULL) {
+ return g_strdup (path);
+ }
+
+ return g_strconcat (passwd_file_entry->pw_dir,
+ slash_after_user_name,
+ NULL);
+}