~noskcaj/ubuntu/wily/epiphany-browser/merge

1.1.18 by Sebastien Bacher
Import upstream version 2.17.4
1
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
1 by Sebastien Bacher
Import upstream version 1.9.2
2
/*
1.1.15 by Sebastien Bacher
Import upstream version 2.16.1
3
 *  Copyright © 2002-2004 Marco Pesenti Gritti
4
 *  Copyright © 2003, 2004 Christian Persch
1 by Sebastien Bacher
Import upstream version 1.9.2
5
 *
6
 *  This program is free software; you can redistribute it and/or modify
7
 *  it under the terms of the GNU General Public License as published by
8
 *  the Free Software Foundation; either version 2, or (at your option)
9
 *  any later version.
10
 *
11
 *  This program is distributed in the hope that it will be useful,
12
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 *  GNU General Public License for more details.
15
 *
16
 *  You should have received a copy of the GNU General Public License
17
 *  along with this program; if not, write to the Free Software
1.1.24 by Sebastien Bacher
Import upstream version 2.18.1
18
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
1 by Sebastien Bacher
Import upstream version 1.9.2
19
 *
20
 */
21
22
#include "config.h"
23
#include "ephy-bookmarks.h"
1.7.7 by Jeremy Bicha
Import upstream version 3.3.91
24
25
#include "ephy-bookmark-properties.h"
26
#include "ephy-bookmarks-export.h"
27
#include "ephy-bookmarks-import.h"
1 by Sebastien Bacher
Import upstream version 1.9.2
28
#include "ephy-bookmarks-type-builtins.h"
1.7.7 by Jeremy Bicha
Import upstream version 3.3.91
29
#include "ephy-debug.h"
30
#include "ephy-embed-shell.h"
1 by Sebastien Bacher
Import upstream version 1.9.2
31
#include "ephy-file-helpers.h"
1.7.7 by Jeremy Bicha
Import upstream version 3.3.91
32
#include "ephy-history-service.h"
1 by Sebastien Bacher
Import upstream version 1.9.2
33
#include "ephy-node-common.h"
34
#include "ephy-prefs.h"
1.8.9 by Gustavo Noronha Silva
Import upstream version 3.7.91
35
#include "ephy-profile-utils.h"
1.1.62 by Emilio Pozuelo Monfort
Import upstream version 2.91.5
36
#include "ephy-settings.h"
1.7.7 by Jeremy Bicha
Import upstream version 3.3.91
37
#include "ephy-shell.h"
1 by Sebastien Bacher
Import upstream version 1.9.2
38
#include "ephy-signal-accumulator.h"
1.7.7 by Jeremy Bicha
Import upstream version 3.3.91
39
#include "ephy-tree-model-node.h"
1 by Sebastien Bacher
Import upstream version 1.9.2
40
1.8.7 by Jeremy Bicha
Import upstream version 3.6.0
41
#include <avahi-common/error.h>
42
#include <avahi-gobject/ga-client.h>
43
#include <avahi-gobject/ga-enums.h>
44
#include <avahi-gobject/ga-service-browser.h>
45
#include <avahi-gobject/ga-service-resolver.h>
1 by Sebastien Bacher
Import upstream version 1.9.2
46
#include <glib/gi18n.h>
1.1.39 by Sebastien Bacher
Import upstream version 2.23.91
47
#include <gtk/gtk.h>
1.7.7 by Jeremy Bicha
Import upstream version 3.3.91
48
#include <string.h>
1 by Sebastien Bacher
Import upstream version 1.9.2
49
50
#define EPHY_BOOKMARKS_XML_ROOT    "ephy_bookmarks"
51
#define EPHY_BOOKMARKS_XML_VERSION "1.03"
1.1.19 by Sebastien Bacher
Import upstream version 2.17.5
52
#define BOOKMARKS_SAVE_DELAY 3 /* seconds */
1 by Sebastien Bacher
Import upstream version 1.9.2
53
#define UPDATE_URI_DATA_KEY "updated-uri"
54
55
#define EPHY_BOOKMARKS_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), EPHY_TYPE_BOOKMARKS, EphyBookmarksPrivate))
56
1.1.11 by Sebastien Bacher
Import upstream version 2.15.3
57
static const char zeroconf_protos[3][6] =
58
{
59
	"http",
60
	"https",
61
	"ftp"
62
};
63
1 by Sebastien Bacher
Import upstream version 1.9.2
64
struct _EphyBookmarksPrivate
65
{
66
	gboolean init_defaults;
67
	gboolean dirty;
68
	guint save_timeout_id;
69
	char *xml_file;
70
	char *rdf_file;
71
	EphyNodeDb *db;
72
	EphyNode *bookmarks;
73
	EphyNode *keywords;
74
	EphyNode *notcategorized;
75
	EphyNode *smartbookmarks;
76
	EphyNode *lower_fav;
77
	double lower_score;
78
79
	/* Local sites */
80
	EphyNode *local;
1.1.34 by Alexander Sack
Import upstream version 2.21.90
81
	GaClient *ga_client;
82
	GaServiceBrowser *browse_handles[G_N_ELEMENTS (zeroconf_protos)];
1.1.5 by Sebastien Bacher
Import upstream version 1.9.7
83
	GHashTable *resolve_handles;
1 by Sebastien Bacher
Import upstream version 1.9.2
84
};
85
86
static const char *default_topics [] =
87
{
88
	N_("Entertainment"),
89
	N_("News"),
90
	N_("Shopping"),
91
	N_("Sports"),
92
	N_("Travel"),
93
	N_("Work")
94
};
95
96
/* Signals */
97
enum
98
{
99
	TREE_CHANGED,
100
	RESOLVE_ADDRESS,
101
	LAST_SIGNAL
102
};
103
1.1.48 by Gustavo Noronha Silva
Import upstream version 2.28.0
104
static guint ephy_bookmarks_signals[LAST_SIGNAL];
1 by Sebastien Bacher
Import upstream version 1.9.2
105
106
static void ephy_bookmarks_class_init	(EphyBookmarksClass *klass);
107
static void ephy_bookmarks_init		(EphyBookmarks *tab);
108
static void ephy_bookmarks_finalize	(GObject *object);
109
static char *impl_resolve_address	(EphyBookmarks*, const char*, const char*);
1.1.38 by Sebastien Bacher
Import upstream version 2.22.3
110
static void ephy_local_bookmarks_start_client (EphyBookmarks *bookmarks);
1 by Sebastien Bacher
Import upstream version 1.9.2
111
1.1.69 by Gustavo Noronha Silva
Import upstream version 3.2.0
112
G_DEFINE_TYPE (EphyBookmarks, ephy_bookmarks, G_TYPE_OBJECT)
1 by Sebastien Bacher
Import upstream version 1.9.2
113
114
static void
115
ephy_bookmarks_init_defaults (EphyBookmarks *eb)
116
{
117
	int i;
118
119
	for (i = 0; i < G_N_ELEMENTS (default_topics); i++)
120
	{
121
		ephy_bookmarks_add_keyword (eb, _(default_topics[i]));
122
	}
123
1.1.48 by Gustavo Noronha Silva
Import upstream version 2.28.0
124
	ephy_bookmarks_import_rdf (eb, DATADIR "/default-bookmarks.rdf");
1 by Sebastien Bacher
Import upstream version 1.9.2
125
}
126
127
static void
128
ephy_bookmarks_class_init (EphyBookmarksClass *klass)
129
{
130
	GObjectClass *object_class = G_OBJECT_CLASS (klass);
131
132
	object_class->finalize = ephy_bookmarks_finalize;
133
134
	klass->resolve_address = impl_resolve_address;
135
136
	ephy_bookmarks_signals[TREE_CHANGED] =
137
		g_signal_new ("tree-changed",
138
			      G_OBJECT_CLASS_TYPE (object_class),
139
			      G_SIGNAL_RUN_LAST,
140
			      G_STRUCT_OFFSET (EphyBookmarksClass, tree_changed),
141
			      NULL, NULL,
142
			      g_cclosure_marshal_VOID__VOID,
143
			      G_TYPE_NONE,
144
			      0);
145
146
	ephy_bookmarks_signals[RESOLVE_ADDRESS] =
147
		g_signal_new ("resolve-address",
148
			      G_OBJECT_CLASS_TYPE (object_class),
149
			      G_SIGNAL_RUN_LAST,
150
			      G_STRUCT_OFFSET (EphyBookmarksClass, resolve_address),
151
			      ephy_signal_accumulator_string, NULL,
1.1.69 by Gustavo Noronha Silva
Import upstream version 3.2.0
152
			      g_cclosure_marshal_generic,
1 by Sebastien Bacher
Import upstream version 1.9.2
153
			      G_TYPE_STRING,
154
			      2,
155
			      G_TYPE_STRING,
156
			      G_TYPE_STRING);
157
158
	g_type_class_add_private (object_class, sizeof(EphyBookmarksPrivate));
159
}
160
161
static gboolean
162
save_filter (EphyNode *node,
163
	     EphyBookmarks *bookmarks)
164
{
165
	EphyBookmarksPrivate *priv = bookmarks->priv;
166
167
	return node != priv->bookmarks &&
168
	       node != priv->notcategorized &&
169
	       node != priv->local;
170
}
171
172
static gboolean
173
save_filter_local (EphyNode *node,
174
		   EphyBookmarks *bookmarks)
175
{
176
	EphyBookmarksPrivate *priv = bookmarks->priv;
177
1.1.11 by Sebastien Bacher
Import upstream version 2.15.3
178
	return !ephy_node_has_child (priv->local, node);
1 by Sebastien Bacher
Import upstream version 1.9.2
179
}
180
181
static void
182
ephy_bookmarks_save (EphyBookmarks *eb)
183
{
184
185
	LOG ("Saving bookmarks");
186
187
	ephy_node_db_write_to_xml_safe
188
		(eb->priv->db,
189
		 (xmlChar *) eb->priv->xml_file,
190
		 (xmlChar *) EPHY_BOOKMARKS_XML_ROOT,
191
		 (xmlChar *) EPHY_BOOKMARKS_XML_VERSION,
192
		 (xmlChar *) "Do not rely on this file, it's only for internal use. Use bookmarks.rdf instead.",
193
		 eb->priv->keywords, (EphyNodeFilterFunc) save_filter, eb,
194
		 eb->priv->bookmarks, (EphyNodeFilterFunc) save_filter_local, eb,
195
		 NULL);
196
197
	/* Export bookmarks in rdf */
198
	ephy_bookmarks_export_rdf (eb, eb->priv->rdf_file);
199
}
200
201
static gboolean
202
save_bookmarks_delayed (EphyBookmarks *bookmarks)
203
{
204
	ephy_bookmarks_save (bookmarks);
205
	bookmarks->priv->dirty = FALSE;
206
	bookmarks->priv->save_timeout_id = 0;
207
208
	return FALSE;
209
}
210
211
static void
212
ephy_bookmarks_save_delayed (EphyBookmarks *bookmarks, int delay)
213
{
214
	if (!bookmarks->priv->dirty)
215
	{
216
		bookmarks->priv->dirty = TRUE;
217
218
		if (delay > 0)
219
		{
220
			bookmarks->priv->save_timeout_id =
1.1.19 by Sebastien Bacher
Import upstream version 2.17.5
221
				g_timeout_add_seconds (BOOKMARKS_SAVE_DELAY,
1 by Sebastien Bacher
Import upstream version 1.9.2
222
					       (GSourceFunc) save_bookmarks_delayed,
223
					       bookmarks);
1.8.12 by Sjoerd Simons
Import upstream version 3.12.0
224
			g_source_set_name_by_id (bookmarks->priv->save_timeout_id, "[epiphany] save_bookmarks_delayed");
1 by Sebastien Bacher
Import upstream version 1.9.2
225
		}
226
		else
227
		{
228
			bookmarks->priv->save_timeout_id =
229
				g_idle_add ((GSourceFunc) save_bookmarks_delayed,
230
					    bookmarks);
231
		}
232
	}
233
}
234
1.8.9 by Gustavo Noronha Silva
Import upstream version 3.7.91
235
static void
236
icon_updated_cb (WebKitFaviconDatabase *favicon_database,
237
		 const char *address,
238
		 const char *icon,
239
		 EphyBookmarks *eb)
240
{
241
	ephy_bookmarks_set_icon (eb, address, icon);
242
}
1.1.33 by Sebastien Bacher
Import upstream version 2.21.4
243
244
static void
1 by Sebastien Bacher
Import upstream version 1.9.2
245
ephy_setup_history_notifiers (EphyBookmarks *eb)
246
{
1.8.9 by Gustavo Noronha Silva
Import upstream version 3.7.91
247
	WebKitFaviconDatabase *favicon_database;
1.8.16 by Michael Biebl
Import upstream version 3.16.1
248
	EphyEmbedShell *shell = ephy_embed_shell_get_default ();
1.8.9 by Gustavo Noronha Silva
Import upstream version 3.7.91
249
1.8.16 by Michael Biebl
Import upstream version 3.16.1
250
	favicon_database = webkit_web_context_get_favicon_database (ephy_embed_shell_get_web_context (shell));
1.8.9 by Gustavo Noronha Silva
Import upstream version 3.7.91
251
	g_signal_connect (favicon_database, "favicon-changed",
252
			  G_CALLBACK (icon_updated_cb), eb);
1 by Sebastien Bacher
Import upstream version 1.9.2
253
}
254
255
static void
256
update_bookmark_keywords (EphyBookmarks *eb, EphyNode *bookmark)
257
{
258
	GPtrArray *children;
259
	int i;
260
	GString *list;
261
	const char *title;
262
	char *normalized_keywords, *case_normalized_keywords;
263
264
	list = g_string_new (NULL);
265
266
	children = ephy_node_get_children (eb->priv->keywords);
267
	for (i = 0; i < children->len; i++)
268
	{
269
		EphyNode *kid;
270
271
		kid = g_ptr_array_index (children, i);
272
273
		if (kid != eb->priv->notcategorized && 
274
		    kid != eb->priv->bookmarks &&
275
		    kid != eb->priv->local &&
276
		    ephy_node_has_child (kid, bookmark))
277
		{
278
			const char *topic;
279
			topic = ephy_node_get_property_string
280
				(kid, EPHY_NODE_KEYWORD_PROP_NAME);
281
			g_string_append (list, topic);
282
			g_string_append (list, " ");
283
		}
284
	}
285
286
	title = ephy_node_get_property_string
287
		(bookmark, EPHY_NODE_BMK_PROP_TITLE);
288
	g_string_append (list, " ");
289
	g_string_append (list, title);
290
291
	normalized_keywords = g_utf8_normalize (list->str, -1, G_NORMALIZE_ALL);
292
	case_normalized_keywords = g_utf8_casefold (normalized_keywords, -1);
293
1.1.18 by Sebastien Bacher
Import upstream version 2.17.4
294
	ephy_node_set_property_string (bookmark, EPHY_NODE_BMK_PROP_KEYWORDS,
295
				       case_normalized_keywords);
1 by Sebastien Bacher
Import upstream version 1.9.2
296
297
	g_string_free (list, TRUE);
298
	g_free (normalized_keywords);
299
	g_free (case_normalized_keywords);
300
}
301
302
static void
303
bookmarks_changed_cb (EphyNode *node,
304
		      EphyNode *child,
305
		      guint property_id,
306
		      EphyBookmarks *eb)
307
{
308
	if (property_id == EPHY_NODE_BMK_PROP_TITLE)
309
	{
310
		update_bookmark_keywords (eb, child);
311
	}
312
313
	ephy_bookmarks_save_delayed (eb, BOOKMARKS_SAVE_DELAY);
314
}
315
316
static void
317
bookmarks_removed_cb (EphyNode *node,
318
		      EphyNode *child,
319
		      guint old_index,
320
		      EphyBookmarks *eb)
321
{
322
	ephy_bookmarks_save_delayed (eb, BOOKMARKS_SAVE_DELAY);
323
}
324
325
static gboolean
326
bookmark_is_categorized (EphyBookmarks *eb, EphyNode *bookmark)
327
{
328
	GPtrArray *children;
329
	int i;
330
331
	children = ephy_node_get_children (eb->priv->keywords);
332
	for (i = 0; i < children->len; i++)
333
	{
334
		EphyNode *kid;
335
336
		kid = g_ptr_array_index (children, i);
337
338
		if (kid != eb->priv->notcategorized && 
339
		    kid != eb->priv->bookmarks &&
340
		    kid != eb->priv->local &&
341
		    ephy_node_has_child (kid, bookmark))
342
		{
343
			return TRUE;
344
		}
345
	}
346
347
	return FALSE;
348
}
349
350
static void
351
topics_removed_cb (EphyNode *node,
352
		   EphyNode *child,
353
		   guint old_index,
354
		   EphyBookmarks *eb)
355
{
356
	GPtrArray *children;
357
	int i;
358
359
	children = ephy_node_get_children (child);
360
	for (i = 0; i < children->len; i++)
361
	{
362
		EphyNode *kid;
363
364
		kid = g_ptr_array_index (children, i);
365
366
		if (!bookmark_is_categorized (eb, kid) &&
367
		    !ephy_node_has_child (eb->priv->notcategorized, kid))
368
		{
369
			ephy_node_add_child
370
				(eb->priv->notcategorized, kid);
371
		}
372
373
		update_bookmark_keywords (eb, kid);
374
	}
375
}
376
377
static void
1.1.5 by Sebastien Bacher
Import upstream version 1.9.7
378
fix_hierarchy_topic (EphyBookmarks *eb,
379
		     EphyNode *topic)
380
{
381
	GPtrArray *children;
382
	EphyNode *bookmark;
383
	const char *name;
384
	char **split;
385
	int i, j;
386
387
	children = ephy_node_get_children (topic);
388
	name = ephy_node_get_property_string (topic, EPHY_NODE_KEYWORD_PROP_NAME);
389
	split = g_strsplit (name, "->", -1);
390
	
391
	for (i = 0; split[i]; i++)
392
	{
393
		if (split[i][0] == '\0') continue;
394
		
395
		topic = ephy_bookmarks_find_keyword (eb, split[i], FALSE);
396
		if (topic == NULL)
397
		{
398
			topic = ephy_bookmarks_add_keyword (eb, split[i]);
399
		}
400
		for (j = 0; j < children->len; j++)
401
		{
402
			bookmark = g_ptr_array_index (children, j);
403
			ephy_bookmarks_set_keyword (eb, topic, bookmark);
404
		}
405
	}
406
	
407
	g_strfreev (split);
408
}
409
410
static void
411
fix_hierarchy (EphyBookmarks *eb)
412
{
413
	GPtrArray *topics;
414
	EphyNode *topic;
415
	const char *name;
416
	int i;
417
	
418
	topics = ephy_node_get_children (eb->priv->keywords);
419
	for (i = (int)topics->len - 1; i >= 0; i--)
420
	{
421
		topic = (EphyNode *)g_ptr_array_index (topics, i);
422
		name = ephy_node_get_property_string
423
			(topic, EPHY_NODE_KEYWORD_PROP_NAME);
424
		if (strstr (name, "->") != NULL)
425
		{
426
			fix_hierarchy_topic (eb, topic);
427
			ephy_node_remove_child (eb->priv->keywords, topic);
428
		}
429
	}
430
}
431
432
static void
1 by Sebastien Bacher
Import upstream version 1.9.2
433
backup_file (const char *original_filename, const char *extension)
434
{
435
	char *template, *backup_filename;
436
	int result = 0;
437
438
	if (g_file_test (original_filename, G_FILE_TEST_EXISTS) == FALSE)
439
	{
440
		return;
441
	}
442
443
	template = g_strconcat (original_filename, ".backup-XXXXXX", NULL);
444
	backup_filename = ephy_file_tmp_filename (template, extension);
445
446
	if (backup_filename != NULL)
447
	{
448
		result = rename (original_filename, backup_filename);
449
	}
450
451
	if (result >= 0)
452
	{
453
		g_message ("Your old bookmarks file was backed up as \"%s\".\n",
454
			   backup_filename);
455
	}
456
	else
457
	{
458
		g_warning ("Backup failed! Your old bookmarks file was lost.\n");
459
	}
460
461
	g_free (template);
462
	g_free (backup_filename);
463
}
464
1.1.34 by Alexander Sack
Import upstream version 2.21.90
465
/* C&P adapted from gnome-vfs-dns-sd.c */
466
static GHashTable *
467
decode_txt_record (AvahiStringList *input_text)
468
{
469
	GHashTable *hash;
470
	int i;
471
	int len;
472
	char *key, *value, *end;
473
	char *key_dup, *value_dup;
474
	char *raw_txt;
475
	size_t raw_txt_len;
1.1.37 by Alexander Sack
Import upstream version 2.22.1.1
476
477
	if (!input_text)
478
		return NULL;
479
1.1.34 by Alexander Sack
Import upstream version 2.21.90
480
	raw_txt_len = avahi_string_list_serialize (input_text, NULL, 0);
481
	raw_txt = g_malloc (raw_txt_len);
482
	raw_txt_len = avahi_string_list_serialize (input_text, raw_txt, raw_txt_len);
483
484
	if (raw_txt == NULL)
485
		return NULL;
486
	
487
	hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
488
489
	i = 0;
490
	while (i < raw_txt_len) {
491
		len = raw_txt[i++];
492
		
493
		if (i + len > raw_txt_len) {
494
			break;
495
		}
496
		
497
		if (len == 0) {
498
			continue;
499
		}
500
		
501
		key = &raw_txt[i];
502
		end = &raw_txt[i + len];
503
		i += len;
504
505
		if (*key == '=') {
506
			/* 6.4 - silently ignore keys starting with = */
507
			continue;
508
		}
509
		
510
		value = memchr (key, '=', len);
511
		if (value) {
512
			key_dup = g_strndup (key, value - key);
513
			value++; /* Skip '=' */
514
			value_dup = g_strndup (value, end - value);
515
		} else {
516
			key_dup = g_strndup (key, len);
517
			value_dup = NULL;
518
		}
519
		if (!g_hash_table_lookup_extended (hash,
520
						   key_dup,
521
						   NULL, NULL)) {
522
			g_hash_table_insert (hash,
523
					     key_dup,
524
					     value_dup);
525
		} else {
526
			g_free (key_dup);
527
			g_free (value_dup);
528
		}
529
	}
530
531
	return hash;
532
}
533
534
/* End of copied code */
535
1.1.5 by Sebastien Bacher
Import upstream version 1.9.7
536
static char *
1.1.34 by Alexander Sack
Import upstream version 2.21.90
537
get_id_for_response (const char *type,
538
		     const char *domain,
539
		     const char *name)
1.1.5 by Sebastien Bacher
Import upstream version 1.9.7
540
{
541
	/* FIXME: limit length! */
542
	return g_strdup_printf ("%s\1%s\1%s",
1.1.34 by Alexander Sack
Import upstream version 2.21.90
543
				type,
544
				domain,
545
				name);
1.1.5 by Sebastien Bacher
Import upstream version 1.9.7
546
}
547
548
typedef struct
549
{
550
	EphyBookmarks *bookmarks;
1.1.37 by Alexander Sack
Import upstream version 2.22.1.1
551
	GaServiceResolver *resolver;
1.1.5 by Sebastien Bacher
Import upstream version 1.9.7
552
	EphyNode *node;
1.1.37 by Alexander Sack
Import upstream version 2.22.1.1
553
	char *name;
554
	char *type;
555
	char *domain;
1.1.5 by Sebastien Bacher
Import upstream version 1.9.7
556
} ResolveData;
557
1 by Sebastien Bacher
Import upstream version 1.9.2
558
static void
1.1.34 by Alexander Sack
Import upstream version 2.21.90
559
resolver_found_cb (GaServiceResolver *resolver,
560
		   int interface,
561
		   GaProtocol protocol,
562
		   const char *name,
563
		   const char *type,
564
		   const char *domain,
565
		   const char *host_name,
566
		   const AvahiAddress *address,
567
		   guint16 port,
568
		   AvahiStringList *txt,
569
		   glong flags,
570
		   ResolveData *data)
1 by Sebastien Bacher
Import upstream version 1.9.2
571
{
1.1.5 by Sebastien Bacher
Import upstream version 1.9.7
572
	EphyBookmarks *bookmarks = data->bookmarks;
1 by Sebastien Bacher
Import upstream version 1.9.2
573
	EphyBookmarksPrivate *priv = bookmarks->priv;
574
	GValue value = { 0, };
575
	const char *path = NULL;
1.1.34 by Alexander Sack
Import upstream version 2.21.90
576
	char host[128];
577
	GHashTable *text_table;
1 by Sebastien Bacher
Import upstream version 1.9.2
578
	char *url;
1.1.10 by Sebastien Bacher
Import upstream version 2.14.1.1
579
	gboolean was_immutable;
1.1.37 by Alexander Sack
Import upstream version 2.22.1.1
580
	gboolean is_new_node = FALSE;
1.1.11 by Sebastien Bacher
Import upstream version 2.15.3
581
	guint i;
1.1.10 by Sebastien Bacher
Import upstream version 2.14.1.1
582
1.1.37 by Alexander Sack
Import upstream version 2.22.1.1
583
	LOG ("resolver_found_cb resolver %p\n", resolver);
584
1.1.10 by Sebastien Bacher
Import upstream version 2.14.1.1
585
	was_immutable = ephy_node_db_is_immutable (priv->db);
586
	ephy_node_db_set_immutable (priv->db, FALSE);
1 by Sebastien Bacher
Import upstream version 1.9.2
587
1.1.11 by Sebastien Bacher
Import upstream version 2.15.3
588
	/* Find the protocol */
589
	for (i = 0; i < G_N_ELEMENTS (zeroconf_protos); ++i)
590
	{
591
		char proto[20];
592
593
		g_snprintf (proto, sizeof (proto), "_%s._tcp", zeroconf_protos[i]);
1.1.34 by Alexander Sack
Import upstream version 2.21.90
594
		if (strcmp (type, proto) == 0) break;
1.1.11 by Sebastien Bacher
Import upstream version 2.15.3
595
	}
596
	if (i == G_N_ELEMENTS (zeroconf_protos)) return;
1.1.34 by Alexander Sack
Import upstream version 2.21.90
597
	
1.1.37 by Alexander Sack
Import upstream version 2.22.1.1
598
	if (address == NULL)
599
	{
600
		g_warning ("Zeroconf failed to resolve host %s", name);
601
		return;
602
	}
603
1.1.34 by Alexander Sack
Import upstream version 2.21.90
604
	text_table = decode_txt_record (txt);
1.1.11 by Sebastien Bacher
Import upstream version 2.15.3
605
1.1.34 by Alexander Sack
Import upstream version 2.21.90
606
	if (text_table != NULL)
1 by Sebastien Bacher
Import upstream version 1.9.2
607
	{
1.1.34 by Alexander Sack
Import upstream version 2.21.90
608
		path = g_hash_table_lookup (text_table, "path");
1 by Sebastien Bacher
Import upstream version 1.9.2
609
	}
610
	if (path == NULL || path[0] == '\0')
611
	{
612
		path = "/";
613
	}
1.1.34 by Alexander Sack
Import upstream version 2.21.90
614
	
615
	avahi_address_snprint (host, sizeof (host), address);
1 by Sebastien Bacher
Import upstream version 1.9.2
616
1.1.11 by Sebastien Bacher
Import upstream version 2.15.3
617
	LOG ("0conf RESOLVED type=%s domain=%s name=%s => proto=%s host=%s port=%d path=%s\n",
1.1.34 by Alexander Sack
Import upstream version 2.21.90
618
	     type, domain, name,
619
	     zeroconf_protos[i], host, port, path);
1.1.5 by Sebastien Bacher
Import upstream version 1.9.7
620
1.1.37 by Alexander Sack
Import upstream version 2.22.1.1
621
	was_immutable = ephy_node_db_is_immutable (priv->db);
622
	ephy_node_db_set_immutable (priv->db, FALSE);
623
624
	if (data->node == NULL)
625
	{
626
		is_new_node = TRUE;
627
628
		data->node = ephy_node_new (priv->db);
629
		g_assert (data->node != NULL);
630
631
		/* don't allow dragging this node */
632
		ephy_node_set_is_drag_source (data->node, FALSE);
633
634
		g_value_init (&value, G_TYPE_STRING);
635
		g_value_take_string (&value,
636
				     get_id_for_response (data->type, 
637
							  data->domain,
638
							  data->name));
639
		ephy_node_set_property (data->node, EPHY_NODE_BMK_PROP_SERVICE_ID, &value);
640
		g_value_unset (&value);
641
642
		/* FIXME: limit length! */
643
		ephy_node_set_property_string (data->node,
644
					       EPHY_NODE_BMK_PROP_TITLE,
645
					       name);
646
647
		ephy_node_set_property_boolean (data->node,
648
						EPHY_NODE_BMK_PROP_IMMUTABLE,
649
						TRUE);
650
	}
651
1.1.5 by Sebastien Bacher
Import upstream version 1.9.7
652
	/* FIXME: limit length! */
1.1.11 by Sebastien Bacher
Import upstream version 2.15.3
653
	url = g_strdup_printf ("%s://%s:%d%s", zeroconf_protos[i], host, port, path);
1 by Sebastien Bacher
Import upstream version 1.9.2
654
655
	g_value_init (&value, G_TYPE_STRING);
656
	g_value_take_string (&value, url);
1.1.37 by Alexander Sack
Import upstream version 2.22.1.1
657
	ephy_node_set_property (data->node, EPHY_NODE_BMK_PROP_LOCATION, &value);
1 by Sebastien Bacher
Import upstream version 1.9.2
658
	g_value_unset (&value);
659
1.1.37 by Alexander Sack
Import upstream version 2.22.1.1
660
	if (is_new_node)
1.1.5 by Sebastien Bacher
Import upstream version 1.9.7
661
	{
1.1.37 by Alexander Sack
Import upstream version 2.22.1.1
662
		ephy_node_add_child (priv->bookmarks, data->node);
663
		ephy_node_add_child (priv->local, data->node);
1.1.5 by Sebastien Bacher
Import upstream version 1.9.7
664
	}
1.1.10 by Sebastien Bacher
Import upstream version 2.14.1.1
665
	
666
	ephy_node_db_set_immutable (priv->db, was_immutable);
1.1.37 by Alexander Sack
Import upstream version 2.22.1.1
667
1.1.44 by Sebastien Bacher
Import upstream version 2.25.91
668
	if (text_table != NULL)
669
	{
670
		g_hash_table_unref (text_table);
671
	}
1 by Sebastien Bacher
Import upstream version 1.9.2
672
}
673
674
static void
1.1.34 by Alexander Sack
Import upstream version 2.21.90
675
resolver_failure_cb (GaServiceResolver *resolver,
676
		     GError *error,
677
		     ResolveData *data)
678
{
1.1.37 by Alexander Sack
Import upstream version 2.22.1.1
679
	LOG ("resolver_failure_cb resolver %p: %s\n", resolver, error?error->message:"(null)");
680
681
	/* Remove the node, if present */
682
	if (data->node != NULL)
683
	{	
684
		EphyBookmarks *bookmarks = data->bookmarks;
685
		EphyBookmarksPrivate *priv = bookmarks->priv;
686
		gboolean was_immutable;
687
688
		was_immutable = ephy_node_db_is_immutable (priv->db);
689
		ephy_node_db_set_immutable (priv->db, FALSE);	
690
		ephy_node_unref (data->node);
691
		data->node = NULL;
692
		ephy_node_db_set_immutable (priv->db, was_immutable);
693
	}
1.1.34 by Alexander Sack
Import upstream version 2.21.90
694
}
695
696
static void
1.1.37 by Alexander Sack
Import upstream version 2.22.1.1
697
resolve_data_free (ResolveData* data)
1.1.34 by Alexander Sack
Import upstream version 2.21.90
698
{
1.1.37 by Alexander Sack
Import upstream version 2.22.1.1
699
	if (data->resolver)
700
		g_object_unref (data->resolver);
701
702
	g_free (data->type);
703
	g_free (data->name);
704
	g_free (data->domain);
1.1.34 by Alexander Sack
Import upstream version 2.21.90
705
	g_slice_free (ResolveData, data);
706
}
707
708
static void
709
browser_new_service_cb (GaServiceBrowser *browser,
710
			int interface,
711
			GaProtocol protocol,
712
			const char *name,
713
			const char *type,
714
			const char *domain,
715
			glong flags,
716
			EphyBookmarks *bookmarks)
717
{
718
	EphyBookmarksPrivate *priv = bookmarks->priv;
1.1.5 by Sebastien Bacher
Import upstream version 1.9.7
719
	ResolveData *data;
1.1.34 by Alexander Sack
Import upstream version 2.21.90
720
	char *node_id;
1.1.37 by Alexander Sack
Import upstream version 2.22.1.1
721
	GError *error = NULL;
1.1.34 by Alexander Sack
Import upstream version 2.21.90
722
	
723
	node_id = get_id_for_response (type, domain, name);
724
	
1.1.5 by Sebastien Bacher
Import upstream version 1.9.7
725
	LOG ("0conf ADD: type=%s domain=%s name=%s\n",
1.1.34 by Alexander Sack
Import upstream version 2.21.90
726
	     type, domain, name);
727
	
1.1.37 by Alexander Sack
Import upstream version 2.22.1.1
728
	if (g_hash_table_lookup (priv->resolve_handles, node_id) != NULL)
1.1.5 by Sebastien Bacher
Import upstream version 1.9.7
729
	{
1.1.37 by Alexander Sack
Import upstream version 2.22.1.1
730
		g_free (node_id);
731
		return;
1.1.5 by Sebastien Bacher
Import upstream version 1.9.7
732
	}
733
1.1.34 by Alexander Sack
Import upstream version 2.21.90
734
	data = g_slice_new0 (ResolveData);
1.1.5 by Sebastien Bacher
Import upstream version 1.9.7
735
	data->bookmarks = bookmarks;
1.1.37 by Alexander Sack
Import upstream version 2.22.1.1
736
	data->node = NULL;
737
	data->type = g_strdup (type);
738
	data->name = g_strdup (name);
739
	data->domain = g_strdup (domain);
1.1.34 by Alexander Sack
Import upstream version 2.21.90
740
	
1.1.37 by Alexander Sack
Import upstream version 2.22.1.1
741
	data->resolver = ga_service_resolver_new (AVAHI_IF_UNSPEC,
742
						  AVAHI_PROTO_UNSPEC,
743
						  name, type, domain,
744
						  AVAHI_PROTO_UNSPEC,
745
						  GA_LOOKUP_USE_MULTICAST);
746
	g_signal_connect (data->resolver, "found",
747
			  G_CALLBACK (resolver_found_cb), data);
748
	g_signal_connect (data->resolver, "failure",
749
			  G_CALLBACK (resolver_failure_cb), data);
750
	if (!ga_service_resolver_attach (data->resolver,
1.1.34 by Alexander Sack
Import upstream version 2.21.90
751
					 priv->ga_client,
1.1.37 by Alexander Sack
Import upstream version 2.22.1.1
752
					 &error))
1 by Sebastien Bacher
Import upstream version 1.9.2
753
	{
1.1.37 by Alexander Sack
Import upstream version 2.22.1.1
754
		g_warning ("Unable to resolve Zeroconf service %s: %s", name, error ? error->message : "(null)");
755
		g_clear_error (&error);
756
		resolve_data_free (data);
757
		g_free (node_id);
1.1.5 by Sebastien Bacher
Import upstream version 1.9.7
758
		return;
1 by Sebastien Bacher
Import upstream version 1.9.2
759
	}
1.1.37 by Alexander Sack
Import upstream version 2.22.1.1
760
1.1.5 by Sebastien Bacher
Import upstream version 1.9.7
761
	g_hash_table_insert (priv->resolve_handles,
1.1.37 by Alexander Sack
Import upstream version 2.22.1.1
762
			     node_id /* transfer ownership */, data);
763
}
764
765
static void
766
browser_removed_service_cb (GaServiceBrowser *browser,
767
			    int interface,
768
			    GaProtocol protocol,
769
			    const char *name,
770
			    const char *type,
771
			    const char *domain,
772
			    glong flags,
773
			    EphyBookmarks *bookmarks)
774
{
775
	EphyBookmarksPrivate *priv = bookmarks->priv;
776
	char *node_id;
777
	ResolveData *data;
778
779
	node_id = get_id_for_response (type, domain, name);
780
	data = g_hash_table_lookup (priv->resolve_handles, node_id);
781
	/* shouldn't really happen, but let's play safe */
782
	if (!data)
783
	{
784
		g_free (node_id);
785
		return;
786
	}
787
788
	if (data->node != NULL)
789
	{	
790
		gboolean was_immutable;
791
792
		was_immutable = ephy_node_db_is_immutable (priv->db);
793
		ephy_node_db_set_immutable (priv->db, FALSE);	
794
		ephy_node_unref (data->node);
795
		data->node = NULL;
796
		ephy_node_db_set_immutable (priv->db, was_immutable);
797
	}
798
799
	g_hash_table_remove (priv->resolve_handles, node_id);
800
	g_free (node_id);
1.1.34 by Alexander Sack
Import upstream version 2.21.90
801
}
802
803
static void
804
start_browsing (GaClient *ga_client,
805
		EphyBookmarks *bookmarks)
806
{
807
	EphyBookmarksPrivate *priv = bookmarks->priv;
808
	guint i;
809
810
	for (i = 0; i < G_N_ELEMENTS (zeroconf_protos); ++i)
811
	{
812
		GaServiceBrowser *browser = NULL;
813
		char proto[20];
814
815
		g_snprintf (proto, sizeof (proto), "_%s._tcp", zeroconf_protos[i]);
816
817
		browser = ga_service_browser_new (proto);
818
		g_signal_connect (browser, "new-service",
819
				  G_CALLBACK (browser_new_service_cb), bookmarks);
820
		g_signal_connect (browser, "removed-service",
821
				  G_CALLBACK (browser_removed_service_cb), bookmarks);
822
		if (!ga_service_browser_attach (browser,
823
						ga_client,
824
						NULL))
825
		{
826
			g_warning ("Unable to start Zeroconf subsystem");
1.1.37 by Alexander Sack
Import upstream version 2.22.1.1
827
			g_object_unref (browser);
1.1.34 by Alexander Sack
Import upstream version 2.21.90
828
			return;
829
		}
1.1.37 by Alexander Sack
Import upstream version 2.22.1.1
830
1.1.34 by Alexander Sack
Import upstream version 2.21.90
831
		priv->browse_handles[i] = browser;
832
	}
833
}
834
835
static void
836
ga_client_state_changed_cb (GaClient *ga_client,
837
			    GaClientState state,
838
			    EphyBookmarks *bookmarks)
839
{
840
	if (state == GA_CLIENT_STATE_FAILURE)
841
	{
842
		if (avahi_client_errno (ga_client->avahi_client) == AVAHI_ERR_DISCONNECTED)
843
		{
1.1.38 by Sebastien Bacher
Import upstream version 2.22.3
844
                        EphyBookmarksPrivate *priv = bookmarks->priv;
845
846
                        g_object_unref (priv->ga_client);
847
                        priv->ga_client = NULL;
848
849
                        ephy_local_bookmarks_start_client (bookmarks);
1.1.34 by Alexander Sack
Import upstream version 2.21.90
850
		}
851
	}
852
	if (state == GA_CLIENT_STATE_S_RUNNING)
853
	{
854
		start_browsing (ga_client, bookmarks);
855
	}
1 by Sebastien Bacher
Import upstream version 1.9.2
856
}
857
858
static void
1.1.38 by Sebastien Bacher
Import upstream version 2.22.3
859
ephy_local_bookmarks_start_client (EphyBookmarks *bookmarks)
1 by Sebastien Bacher
Import upstream version 1.9.2
860
{
861
	EphyBookmarksPrivate *priv = bookmarks->priv;
1.1.34 by Alexander Sack
Import upstream version 2.21.90
862
	GaClient *ga_client;
863
864
	ga_client = ga_client_new (GA_CLIENT_FLAG_NO_FAIL);
865
	g_signal_connect (ga_client, "state-changed",
866
			  G_CALLBACK (ga_client_state_changed_cb),
867
			  bookmarks);
868
	if (!ga_client_start (ga_client, NULL))
1 by Sebastien Bacher
Import upstream version 1.9.2
869
	{
1.1.34 by Alexander Sack
Import upstream version 2.21.90
870
		g_warning ("Unable to start Zeroconf subsystem");
1.1.38 by Sebastien Bacher
Import upstream version 2.22.3
871
                g_object_unref (ga_client);
1.1.34 by Alexander Sack
Import upstream version 2.21.90
872
		return;
1 by Sebastien Bacher
Import upstream version 1.9.2
873
	}
1.1.34 by Alexander Sack
Import upstream version 2.21.90
874
	priv->ga_client = ga_client;
1.1.38 by Sebastien Bacher
Import upstream version 2.22.3
875
}
876
877
static void
878
ephy_local_bookmarks_init (EphyBookmarks *bookmarks)
879
{
880
	EphyBookmarksPrivate *priv = bookmarks->priv;
1.1.37 by Alexander Sack
Import upstream version 2.22.1.1
881
	priv->resolve_handles =	g_hash_table_new_full (g_str_hash, g_str_equal,
882
						       g_free,
883
						       (GDestroyNotify) resolve_data_free);
1.1.38 by Sebastien Bacher
Import upstream version 2.22.3
884
        ephy_local_bookmarks_start_client (bookmarks);
1 by Sebastien Bacher
Import upstream version 1.9.2
885
}
886
887
static void
888
ephy_local_bookmarks_stop (EphyBookmarks *bookmarks)
889
{
890
	EphyBookmarksPrivate *priv = bookmarks->priv;
1.1.11 by Sebastien Bacher
Import upstream version 2.15.3
891
	guint i;
1 by Sebastien Bacher
Import upstream version 1.9.2
892
1.1.11 by Sebastien Bacher
Import upstream version 2.15.3
893
	for (i = 0; i < G_N_ELEMENTS (zeroconf_protos); ++i)
1 by Sebastien Bacher
Import upstream version 1.9.2
894
	{
1.1.11 by Sebastien Bacher
Import upstream version 2.15.3
895
		if (priv->browse_handles[i] != NULL)
896
		{
1.1.37 by Alexander Sack
Import upstream version 2.22.1.1
897
			g_object_unref (priv->browse_handles[i]);
1.1.11 by Sebastien Bacher
Import upstream version 2.15.3
898
			priv->browse_handles[i] = NULL;
899
		}
1 by Sebastien Bacher
Import upstream version 1.9.2
900
	}
901
1.1.5 by Sebastien Bacher
Import upstream version 1.9.7
902
	if (priv->resolve_handles != NULL)
903
	{
904
		g_hash_table_destroy (priv->resolve_handles);
905
		priv->resolve_handles = NULL;
906
	}
1.1.11 by Sebastien Bacher
Import upstream version 2.15.3
907
908
	if (priv->local != NULL)
909
	{
1.1.37 by Alexander Sack
Import upstream version 2.22.1.1
910
		ephy_node_unref (priv->local);
911
		priv->local = NULL;
1.1.11 by Sebastien Bacher
Import upstream version 2.15.3
912
	}
1.1.34 by Alexander Sack
Import upstream version 2.21.90
913
	
914
	if (priv->ga_client != NULL)
915
	{
916
		g_object_unref (priv->ga_client);
917
		priv->ga_client = NULL;
918
	}
1 by Sebastien Bacher
Import upstream version 1.9.2
919
}
920
921
static void
922
ephy_bookmarks_init (EphyBookmarks *eb)
923
{
924
	EphyNodeDb *db;
925
1.1.18 by Sebastien Bacher
Import upstream version 2.17.4
926
	/* Translators: this topic contains all bookmarks */
1.1.48 by Gustavo Noronha Silva
Import upstream version 2.28.0
927
	const char *bk_all = C_("bookmarks", "All");
1.1.18 by Sebastien Bacher
Import upstream version 2.17.4
928
929
	/* Translators: this topic contains the not categorized
930
	   bookmarks */
1.1.48 by Gustavo Noronha Silva
Import upstream version 2.28.0
931
	const char *bk_not_categorized = C_("bookmarks", "Not Categorized");
1.1.18 by Sebastien Bacher
Import upstream version 2.17.4
932
	
933
	/* Translators: this is an automatic topic containing local
934
	 * websites bookmarks autodiscovered with zeroconf. */
1.1.48 by Gustavo Noronha Silva
Import upstream version 2.28.0
935
	const char *bk_local_sites = C_("bookmarks", "Nearby Sites");
1.1.18 by Sebastien Bacher
Import upstream version 2.17.4
936
1 by Sebastien Bacher
Import upstream version 1.9.2
937
	eb->priv = EPHY_BOOKMARKS_GET_PRIVATE (eb);
938
939
	db = ephy_node_db_new (EPHY_NODE_DB_BOOKMARKS);
940
	eb->priv->db = db;
941
942
	eb->priv->xml_file = g_build_filename (ephy_dot_dir (),
1.8.9 by Gustavo Noronha Silva
Import upstream version 3.7.91
943
					       EPHY_BOOKMARKS_FILE,
1 by Sebastien Bacher
Import upstream version 1.9.2
944
					       NULL);
945
	eb->priv->rdf_file = g_build_filename (ephy_dot_dir (),
1.8.9 by Gustavo Noronha Silva
Import upstream version 3.7.91
946
					       EPHY_BOOKMARKS_FILE_RDF,
1 by Sebastien Bacher
Import upstream version 1.9.2
947
					       NULL);
948
949
	/* Bookmarks */
950
	eb->priv->bookmarks = ephy_node_new_with_id (db, BOOKMARKS_NODE_ID);
1.1.18 by Sebastien Bacher
Import upstream version 2.17.4
951
	
952
	ephy_node_set_property_string (eb->priv->bookmarks,
953
				       EPHY_NODE_KEYWORD_PROP_NAME,
954
				       bk_all);
1 by Sebastien Bacher
Import upstream version 1.9.2
955
	ephy_node_signal_connect_object (eb->priv->bookmarks,
956
					 EPHY_NODE_CHILD_REMOVED,
957
					 (EphyNodeCallback) bookmarks_removed_cb,
958
					 G_OBJECT (eb));
959
	ephy_node_signal_connect_object (eb->priv->bookmarks,
960
					 EPHY_NODE_CHILD_CHANGED,
961
					 (EphyNodeCallback) bookmarks_changed_cb,
962
					 G_OBJECT (eb));
963
964
	/* Keywords */
965
	eb->priv->keywords = ephy_node_new_with_id (db, KEYWORDS_NODE_ID);
1.1.18 by Sebastien Bacher
Import upstream version 2.17.4
966
	ephy_node_set_property_int (eb->priv->bookmarks,
967
				    EPHY_NODE_KEYWORD_PROP_PRIORITY,
968
				    EPHY_NODE_ALL_PRIORITY);
969
	
1 by Sebastien Bacher
Import upstream version 1.9.2
970
	ephy_node_signal_connect_object (eb->priv->keywords,
971
					 EPHY_NODE_CHILD_REMOVED,
972
					 (EphyNodeCallback) topics_removed_cb,
973
					 G_OBJECT (eb));
974
975
	ephy_node_add_child (eb->priv->keywords,
976
			     eb->priv->bookmarks);
977
978
	/* Not categorized */
979
	eb->priv->notcategorized = ephy_node_new_with_id (db, BMKS_NOTCATEGORIZED_NODE_ID);
1.1.18 by Sebastien Bacher
Import upstream version 2.17.4
980
	
981
	
982
	ephy_node_set_property_string (eb->priv->notcategorized,
983
				       EPHY_NODE_KEYWORD_PROP_NAME,
984
				       bk_not_categorized);
985
986
	ephy_node_set_property_int (eb->priv->notcategorized,
987
				    EPHY_NODE_KEYWORD_PROP_PRIORITY,
988
				    EPHY_NODE_SPECIAL_PRIORITY);
989
	
1 by Sebastien Bacher
Import upstream version 1.9.2
990
	ephy_node_add_child (eb->priv->keywords, eb->priv->notcategorized);
991
992
	/* Local Websites */
993
	eb->priv->local = ephy_node_new_with_id (db, BMKS_LOCAL_NODE_ID);
994
995
	/* don't allow drags to this topic */
996
	ephy_node_set_is_drag_dest (eb->priv->local, FALSE);
997
1.1.18 by Sebastien Bacher
Import upstream version 2.17.4
998
	
999
	ephy_node_set_property_string (eb->priv->local,
1000
				       EPHY_NODE_KEYWORD_PROP_NAME,
1001
				       bk_local_sites);
1002
	ephy_node_set_property_int (eb->priv->local,
1003
				    EPHY_NODE_KEYWORD_PROP_PRIORITY,
1004
				    EPHY_NODE_SPECIAL_PRIORITY);
1005
	
1 by Sebastien Bacher
Import upstream version 1.9.2
1006
	ephy_node_add_child (eb->priv->keywords, eb->priv->local);
1007
	ephy_local_bookmarks_init (eb);
1008
1009
	/* Smart bookmarks */
1010
	eb->priv->smartbookmarks = ephy_node_new_with_id (db, SMARTBOOKMARKS_NODE_ID);
1011
1012
	if (g_file_test (eb->priv->xml_file, G_FILE_TEST_EXISTS) == FALSE
1013
	    && g_file_test (eb->priv->rdf_file, G_FILE_TEST_EXISTS) == FALSE)
1014
	{
1015
		eb->priv->init_defaults = TRUE;
1016
	}
1017
	else if (ephy_node_db_load_from_file (eb->priv->db, eb->priv->xml_file,
1018
					      (xmlChar *) EPHY_BOOKMARKS_XML_ROOT,
1019
					      (xmlChar *) EPHY_BOOKMARKS_XML_VERSION) == FALSE)
1020
	{
1021
		/* save the corrupted files so the user can late try to
1022
		 * manually recover them. See bug #128308.
1023
		 */
1024
1025
		g_warning ("Could not read bookmarks file \"%s\", trying to "
1026
			   "re-import bookmarks from \"%s\"\n",
1027
			   eb->priv->xml_file, eb->priv->rdf_file);
1028
1029
		backup_file (eb->priv->xml_file, "xml");
1030
1031
		if (ephy_bookmarks_import_rdf (eb, eb->priv->rdf_file) == FALSE)
1032
		{
1033
			backup_file (eb->priv->rdf_file, "rdf");
1034
1035
			eb->priv->init_defaults = TRUE;
1036
		}
1037
	}
1038
	
1039
	if (eb->priv->init_defaults)
1040
	{
1041
		ephy_bookmarks_init_defaults (eb);
1042
	}
1.1.5 by Sebastien Bacher
Import upstream version 1.9.7
1043
	
1044
	fix_hierarchy (eb);
1 by Sebastien Bacher
Import upstream version 1.9.2
1045
1.1.62 by Emilio Pozuelo Monfort
Import upstream version 2.91.5
1046
	g_settings_bind (EPHY_SETTINGS_LOCKDOWN,
1047
			 EPHY_PREFS_LOCKDOWN_BOOKMARK_EDITING,
1048
			 eb->priv->db, "immutable",
1049
			 G_SETTINGS_BIND_GET);
1 by Sebastien Bacher
Import upstream version 1.9.2
1050
1051
	ephy_setup_history_notifiers (eb);
1052
}
1053
1054
static void
1055
ephy_bookmarks_finalize (GObject *object)
1056
{
1057
	EphyBookmarks *eb = EPHY_BOOKMARKS (object);
1.1.5 by Sebastien Bacher
Import upstream version 1.9.7
1058
	EphyBookmarksPrivate *priv = eb->priv;
1059
1060
	if (priv->save_timeout_id != 0)
1 by Sebastien Bacher
Import upstream version 1.9.2
1061
	{
1.1.5 by Sebastien Bacher
Import upstream version 1.9.7
1062
		g_source_remove (priv->save_timeout_id);
1 by Sebastien Bacher
Import upstream version 1.9.2
1063
	}
1064
1.1.5 by Sebastien Bacher
Import upstream version 1.9.7
1065
	ephy_bookmarks_save (eb);
1066
1 by Sebastien Bacher
Import upstream version 1.9.2
1067
	ephy_local_bookmarks_stop (eb);
1068
1.1.5 by Sebastien Bacher
Import upstream version 1.9.7
1069
	ephy_node_unref (priv->bookmarks);
1070
	ephy_node_unref (priv->keywords);
1071
	ephy_node_unref (priv->notcategorized);
1.1.62 by Emilio Pozuelo Monfort
Import upstream version 2.91.5
1072
	ephy_node_unref (priv->smartbookmarks);
1.1.5 by Sebastien Bacher
Import upstream version 1.9.7
1073
1074
	g_object_unref (priv->db);
1075
1076
	g_free (priv->xml_file);
1077
	g_free (priv->rdf_file);
1 by Sebastien Bacher
Import upstream version 1.9.2
1078
1079
	LOG ("Bookmarks finalized");
1080
1.1.37 by Alexander Sack
Import upstream version 2.22.1.1
1081
	G_OBJECT_CLASS (ephy_bookmarks_parent_class)->finalize (object);
1 by Sebastien Bacher
Import upstream version 1.9.2
1082
}
1083
1084
EphyBookmarks *
1085
ephy_bookmarks_new (void)
1086
{
1.1.5 by Sebastien Bacher
Import upstream version 1.9.7
1087
	return EPHY_BOOKMARKS (g_object_new (EPHY_TYPE_BOOKMARKS, NULL));
1 by Sebastien Bacher
Import upstream version 1.9.2
1088
}
1089
1090
static void
1091
update_has_smart_address (EphyBookmarks *bookmarks, EphyNode *bmk, const char *address)
1092
{
1093
	EphyNode *smart_bmks;
1094
	gboolean smart = FALSE, with_options = FALSE;
1095
1096
	smart_bmks = bookmarks->priv->smartbookmarks;
1097
1098
	if (address)
1099
	{
1100
		smart = strstr (address, "%s") != NULL;
1101
		with_options = strstr (address, "%s%{") != NULL;
1102
	}
1103
1104
	/* if we have a smart bookmark with width specification,
1105
	 * remove from smart bookmarks first to force an update
1106
	 * in the toolbar
1107
	 */
1108
	if (smart && with_options)
1109
	{
1.1.16 by Sebastien Bacher
Import upstream version 2.17.2
1110
		if (ephy_node_has_child (smart_bmks, bmk))
1111
		{
1112
			ephy_node_remove_child (smart_bmks, bmk);
1113
		}
1 by Sebastien Bacher
Import upstream version 1.9.2
1114
		ephy_node_add_child (smart_bmks, bmk);
1115
	}
1116
	else if (smart)
1117
	{
1118
		if (!ephy_node_has_child (smart_bmks, bmk))
1119
		{
1120
			ephy_node_add_child (smart_bmks, bmk);
1121
		}
1122
	}
1123
	else
1124
	{
1125
		if (ephy_node_has_child (smart_bmks, bmk))
1126
		{
1127
			ephy_node_remove_child (smart_bmks, bmk);
1128
		}
1129
	}
1130
}
1131
1132
EphyNode *
1133
ephy_bookmarks_add (EphyBookmarks *eb,
1134
		    const char *title,
1135
		    const char *url)
1136
{
1137
	EphyNode *bm;
1.8.1 by Jeremy Bicha
Import upstream version 3.3.92
1138
	WebKitFaviconDatabase *favicon_database;
1.8.16 by Michael Biebl
Import upstream version 3.16.1
1139
	EphyEmbedShell *shell = ephy_embed_shell_get_default ();
1 by Sebastien Bacher
Import upstream version 1.9.2
1140
1141
	bm = ephy_node_new (eb->priv->db);
1142
1143
	if (bm == NULL) return NULL;
1.1.3 by Sebastien Bacher
Import upstream version 1.9.5.1
1144
	
1145
	if (url == NULL) return NULL;
1.1.18 by Sebastien Bacher
Import upstream version 2.17.4
1146
	ephy_node_set_property_string (bm, EPHY_NODE_BMK_PROP_LOCATION, url);
1147
	
1.1.3 by Sebastien Bacher
Import upstream version 1.9.5.1
1148
	if (title == NULL || title[0] == '\0')
1149
	{
1150
		title = _("Untitled");
1.1.18 by Sebastien Bacher
Import upstream version 2.17.4
1151
	}
1152
	ephy_node_set_property_string (bm, EPHY_NODE_BMK_PROP_TITLE, title);
1 by Sebastien Bacher
Import upstream version 1.9.2
1153
1.8.16 by Michael Biebl
Import upstream version 3.16.1
1154
	favicon_database = webkit_web_context_get_favicon_database (ephy_embed_shell_get_web_context (shell));
1.8.1 by Jeremy Bicha
Import upstream version 3.3.92
1155
	if (favicon_database != NULL)
1.1.3 by Sebastien Bacher
Import upstream version 1.9.5.1
1156
	{
1.8.5 by Jeremy Bicha
Import upstream version 3.5.3
1157
		char *icon = webkit_favicon_database_get_favicon_uri (favicon_database, url);
1.1.3 by Sebastien Bacher
Import upstream version 1.9.5.1
1158
		if (icon != NULL)
1159
		{
1.1.18 by Sebastien Bacher
Import upstream version 2.17.4
1160
			ephy_node_set_property_string
1161
				(bm, EPHY_NODE_BMK_PROP_ICON, icon);
1.8.5 by Jeremy Bicha
Import upstream version 3.5.3
1162
			g_free (icon);
1.1.3 by Sebastien Bacher
Import upstream version 1.9.5.1
1163
		}
1164
	}
1 by Sebastien Bacher
Import upstream version 1.9.2
1165
1166
	update_has_smart_address (eb, bm, url);
1167
	update_bookmark_keywords (eb, bm);
1168
1169
	ephy_node_add_child (eb->priv->bookmarks, bm);
1170
	ephy_node_add_child (eb->priv->notcategorized, bm);
1171
1172
	ephy_bookmarks_save_delayed (eb, 0);
1173
1174
	return bm;
1175
}
1176
1177
void
1178
ephy_bookmarks_set_address (EphyBookmarks *eb,
1179
			    EphyNode *bookmark,
1180
			    const char *address)
1181
{
1.1.18 by Sebastien Bacher
Import upstream version 2.17.4
1182
	ephy_node_set_property_string (bookmark, EPHY_NODE_BMK_PROP_LOCATION,
1183
				       address);
1 by Sebastien Bacher
Import upstream version 1.9.2
1184
1185
	update_has_smart_address (eb, bookmark, address);
1186
}
1187
1188
EphyNode *
1189
ephy_bookmarks_find_bookmark (EphyBookmarks *eb,
1190
			      const char *url)
1191
{
1192
	GPtrArray *children;
1193
	int i;
1194
1195
	g_return_val_if_fail (EPHY_IS_BOOKMARKS (eb), NULL);
1196
	g_return_val_if_fail (eb->priv->bookmarks != NULL, NULL);
1197
	g_return_val_if_fail (url != NULL, NULL);
1198
1199
	children = ephy_node_get_children (eb->priv->bookmarks);
1200
	for (i = 0; i < children->len; i++)
1201
	{
1202
		EphyNode *kid;
1203
		const char *location;
1204
1205
		kid = g_ptr_array_index (children, i);
1206
		location = ephy_node_get_property_string
1207
			(kid, EPHY_NODE_BMK_PROP_LOCATION);
1208
1209
		if (location != NULL && strcmp (url, location) == 0)
1210
		{
1211
			return kid;
1212
		}
1213
	}
1214
1215
	return NULL;
1216
}
1217
1.1.4 by Sebastien Bacher
Import upstream version 1.9.6
1218
static gboolean
1219
is_similar (const char *url1, const char *url2)
1220
{
1.1.5 by Sebastien Bacher
Import upstream version 1.9.7
1221
	int i, j;
1222
	
1223
	for (i = 0; url1[i]; i++)
1224
	  if (url1[i] == '#' || url1[i] == '?')
1225
	    break;
1226
	while(i>0 && url1[i] == '/')
1227
	  i--;
1228
	
1229
	for (j = 0; url2[j]; j++)
1230
	  if (url2[j] == '#' || url2[j] == '?')
1231
	    break;
1232
	while(j>0 && url2[j] == '/') 
1233
	  j--;
1234
	
1235
	if (i != j) return FALSE;
1236
	if (strncmp (url1, url2, i) != 0) return FALSE;
1237
	return TRUE;
1.1.4 by Sebastien Bacher
Import upstream version 1.9.6
1238
}
1239
1240
gint
1241
ephy_bookmarks_get_similar (EphyBookmarks *eb,
1242
			    EphyNode *bookmark,
1243
			    GPtrArray *identical,
1244
			    GPtrArray *similar)
1245
{
1246
	GPtrArray *children;
1247
	const char *url;
1248
	int i, result;
1249
1250
	g_return_val_if_fail (EPHY_IS_BOOKMARKS (eb), -1);
1251
	g_return_val_if_fail (eb->priv->bookmarks != NULL, -1);
1252
	g_return_val_if_fail (bookmark != NULL, -1);
1253
	
1254
	url = ephy_node_get_property_string 
1255
	  (bookmark, EPHY_NODE_BMK_PROP_LOCATION);
1256
1257
	g_return_val_if_fail (url != NULL, -1);
1258
	
1259
	result = 0;
1260
	
1261
	children = ephy_node_get_children (eb->priv->bookmarks);
1262
	for (i = 0; i < children->len; i++)
1263
	{
1264
		EphyNode *kid;
1265
		const char *location;
1266
1267
		kid = g_ptr_array_index (children, i);
1268
		if (kid == bookmark)
1269
		{
1270
			continue;
1271
		}
1272
		
1273
		location = ephy_node_get_property_string
1274
			(kid, EPHY_NODE_BMK_PROP_LOCATION);
1275
1276
		if (location != NULL)
1277
		{
1278
			if(identical != NULL && strcmp (url, location) == 0)
1279
			{
1280
				g_ptr_array_add (identical, kid);
1281
				result++;
1282
			}
1283
			else if(is_similar (url, location))
1284
			{
1285
				if (similar != NULL)
1286
				{
1287
					g_ptr_array_add (similar, kid);
1288
				}
1289
				result++;
1290
			}
1291
		}
1292
	}
1293
	
1294
	return result;
1295
}
1296
1 by Sebastien Bacher
Import upstream version 1.9.2
1297
void
1298
ephy_bookmarks_set_icon	(EphyBookmarks *eb,
1299
			 const char *url,
1300
			 const char *icon)
1301
{
1302
	EphyNode *node;
1303
1304
	g_return_if_fail (icon != NULL);
1305
1306
	node = ephy_bookmarks_find_bookmark (eb, url);
1307
	if (node == NULL) return;
1308
1.1.18 by Sebastien Bacher
Import upstream version 2.17.4
1309
	ephy_node_set_property_string (node, EPHY_NODE_BMK_PROP_ICON, icon);
1 by Sebastien Bacher
Import upstream version 1.9.2
1310
}
1311
1.1.3 by Sebastien Bacher
Import upstream version 1.9.5.1
1312
1313
void
1314
ephy_bookmarks_set_usericon (EphyBookmarks *eb,
1315
			     const char *url,
1316
			     const char *icon)
1317
{
1318
	EphyNode *node;
1319
1320
	g_return_if_fail (icon != NULL);
1321
1322
	node = ephy_bookmarks_find_bookmark (eb, url);
1323
	if (node == NULL) return;
1324
1.1.18 by Sebastien Bacher
Import upstream version 2.17.4
1325
	ephy_node_set_property_string (node, EPHY_NODE_BMK_PROP_USERICON,
1326
				       icon);
1.1.3 by Sebastien Bacher
Import upstream version 1.9.5.1
1327
}
1328
1329
1 by Sebastien Bacher
Import upstream version 1.9.2
1330
/* name must end with '=' */
1331
static char *
1332
get_option (char *start,
1333
	    const char *name,
1334
	    char **optionsend)
1335
{
1336
	char *end, *p;
1337
1338
	*optionsend = start;
1339
1340
	if (start == NULL || start[0] != '%' || start[1] != '{') return NULL;
1341
	start += 2;
1342
1343
	end = strstr (start, "}");
1344
	if (end == NULL) return NULL;
1345
	*optionsend = end + 1;
1346
1347
	start = strstr (start, name);
1348
	if (start == NULL || start > end) return NULL;
1349
	start += strlen (name);
1350
1351
	/* Find end of option, either ',' or '}' */
1352
	end = strstr (start, ",");
1353
	if (end == NULL || end >= *optionsend) end = *optionsend - 1;
1354
1355
	/* limit option length and sanity-check it */
1356
	if (end - start > 32) return NULL;
1357
	for (p = start; p < end; ++p)
1358
	{
1359
		if (!g_ascii_isalnum (*p)) return NULL;
1360
	}
1361
1362
	return g_strndup (start, end - start);
1363
}
1364
1365
static char *
1366
impl_resolve_address (EphyBookmarks *eb,
1367
		      const char *address,
1368
		      const char *content)
1369
{
1370
	GString *result;
1371
	char *pos, *oldpos, *arg, *escaped_arg, *encoding, *optionsend;
1372
1373
	if (address == NULL) return NULL;
1374
	if (content == NULL) content = "";
1375
1376
	result = g_string_new_len (NULL, strlen (content) + strlen (address));
1377
1378
	/* substitute %s's */
1379
	oldpos = (char*) address;
1380
	while ((pos = strstr (oldpos, "%s")) != NULL)
1381
	{
1382
		g_string_append_len (result, oldpos, pos - oldpos);
1383
		pos += 2;
1384
1385
		encoding = get_option (pos, "encoding=", &optionsend);
1386
		if (encoding != NULL)
1387
		{
1388
			GError *error = NULL;
1389
1390
			arg = g_convert (content, strlen (content), encoding,
1391
					 "UTF-8", NULL, NULL, &error);
1392
			if (error != NULL)
1393
			{
1394
				g_warning ("Error when converting arg to encoding '%s': %s\n",
1395
					   encoding, error->message);
1396
				g_error_free (error);
1397
			}
1398
			else
1399
			{
1.1.34 by Alexander Sack
Import upstream version 2.21.90
1400
				escaped_arg = g_uri_escape_string (arg, NULL, TRUE);
1 by Sebastien Bacher
Import upstream version 1.9.2
1401
				g_string_append (result, escaped_arg);
1402
				g_free (escaped_arg);
1403
				g_free (arg);
1404
			}
1405
1406
			g_free (encoding);
1407
		}
1408
		else
1409
		{
1.1.34 by Alexander Sack
Import upstream version 2.21.90
1410
			arg = g_uri_escape_string (content, NULL, TRUE);
1 by Sebastien Bacher
Import upstream version 1.9.2
1411
			g_string_append (result, arg);
1412
			g_free (arg);
1413
		}
1414
1415
		oldpos = optionsend;
1416
	}
1417
	g_string_append (result, oldpos);
1418
1419
	return g_string_free (result, FALSE);
1420
}
1421
1422
char *
1423
ephy_bookmarks_resolve_address (EphyBookmarks *eb,
1424
				const char *address,
1425
				const char *parameter)
1426
{
1427
	char *retval = NULL;
1428
1429
	g_return_val_if_fail (EPHY_IS_BOOKMARKS (eb), NULL);
1430
	g_return_val_if_fail (address != NULL, NULL);
1431
1432
	g_signal_emit (eb, ephy_bookmarks_signals[RESOLVE_ADDRESS], 0,
1433
		       address, parameter, &retval);
1434
1435
	return retval;
1436
}
1437
1438
guint
1439
ephy_bookmarks_get_smart_bookmark_width (EphyNode *bookmark)
1440
{
1441
	const char *url;
1442
	char *option, *end, *number;
1443
	guint width;
1444
1445
	url = ephy_node_get_property_string (bookmark, EPHY_NODE_BMK_PROP_LOCATION);
1446
	if (url == NULL) return 0;
1447
1448
	/* this takes the first %s, but that's okay since we only support one text entry box */
1449
	option = strstr (url, "%s%{");
1450
	if (option == NULL) return 0;
1451
	option += 2;
1452
1453
	number = get_option (option, "width=", &end);
1454
	if (number == NULL) return 0;
1455
1456
	width = (guint) g_ascii_strtoull (number, NULL, 10);
1457
	g_free (number);
1458
1459
	return CLAMP (width, 1, 64);
1460
}
1461
1462
EphyNode *
1463
ephy_bookmarks_add_keyword (EphyBookmarks *eb,
1464
			    const char *name)
1465
{
1466
	EphyNode *key;
1467
1468
	key = ephy_node_new (eb->priv->db);
1469
1470
	if (key == NULL) return NULL;
1471
1.1.18 by Sebastien Bacher
Import upstream version 2.17.4
1472
	ephy_node_set_property_string (key, EPHY_NODE_KEYWORD_PROP_NAME,
1473
				       name);
1474
	ephy_node_set_property_int (key, EPHY_NODE_KEYWORD_PROP_PRIORITY,
1475
				    EPHY_NODE_NORMAL_PRIORITY);
1476
	
1 by Sebastien Bacher
Import upstream version 1.9.2
1477
	ephy_node_add_child (eb->priv->keywords, key);
1478
1479
	return key;
1480
}
1481
1482
void
1483
ephy_bookmarks_remove_keyword (EphyBookmarks *eb,
1484
			       EphyNode *keyword)
1485
{
1486
	ephy_node_remove_child (eb->priv->keywords, keyword);
1487
}
1488
1489
char *
1490
ephy_bookmarks_get_topic_uri (EphyBookmarks *eb,
1491
			      EphyNode *node)
1492
{
1493
	char *uri;
1494
1495
	if (ephy_bookmarks_get_bookmarks (eb) == node)
1496
	{
1497
		uri = g_strdup ("topic://Special/All");
1498
	}
1499
	else if (ephy_bookmarks_get_not_categorized (eb) == node)
1500
	{
1501
		uri = g_strdup ("topic://Special/NotCategorized");
1502
	}
1503
	else if (ephy_bookmarks_get_local (eb) == node)
1504
	{
1.1.27 by Sebastien Bacher
Import upstream version 2.19.6
1505
		/* Note: do not change to "Nearby" because of existing custom toolbars */
1 by Sebastien Bacher
Import upstream version 1.9.2
1506
		uri = g_strdup ("topic://Special/Local");
1507
	}
1508
	else
1509
	{
1510
		const char *name;
1511
1512
		name = ephy_node_get_property_string
1513
			(node, EPHY_NODE_KEYWORD_PROP_NAME);
1514
1515
		uri = g_strdup_printf ("topic://%s", name);
1516
	}
1517
1518
	return uri;
1519
}
1520
1521
EphyNode *
1522
ephy_bookmarks_find_keyword (EphyBookmarks *eb,
1523
			     const char *name,
1524
			     gboolean partial_match)
1525
{
1526
	EphyNode *node;
1527
	GPtrArray *children;
1528
	int i;
1529
	const char *topic_name;
1530
1531
	g_return_val_if_fail (name != NULL, NULL);
1532
1533
	topic_name = name;
1534
1535
	if (g_utf8_strlen (name, -1) == 0)
1536
	{
1537
		LOG ("Empty name, no keyword matches.");
1538
		return NULL;
1539
	}
1540
1541
	if (strcmp (name, "topic://Special/All") == 0)
1542
	{
1543
		return ephy_bookmarks_get_bookmarks (eb);
1544
	}
1545
	else if (strcmp (name, "topic://Special/NotCategorized") == 0)
1546
	{
1547
		return ephy_bookmarks_get_not_categorized (eb);
1548
	}
1549
	else if (strcmp (name, "topic://Special/Local") == 0)
1550
	{
1551
		return ephy_bookmarks_get_local (eb);
1552
	}
1553
	else if (g_str_has_prefix (name, "topic://"))
1554
	{
1555
		topic_name += strlen ("topic://");
1556
	}
1557
1558
	children = ephy_node_get_children (eb->priv->keywords);
1559
	node = NULL;
1560
	for (i = 0; i < children->len; i++)
1561
	{
1562
		 EphyNode *kid;
1563
		 const char *key;
1564
1565
		 kid = g_ptr_array_index (children, i);
1566
		 key = ephy_node_get_property_string (kid, EPHY_NODE_KEYWORD_PROP_NAME);
1567
1568
		 if ((partial_match && g_str_has_prefix (key, topic_name) > 0) ||
1569
		     (!partial_match && strcmp (key, topic_name) == 0))
1570
		 {
1571
			 node = kid;
1572
		 }
1573
	}
1574
1575
	return node;
1576
}
1577
1578
gboolean
1579
ephy_bookmarks_has_keyword (EphyBookmarks *eb,
1580
			    EphyNode *keyword,
1581
			    EphyNode *bookmark)
1582
{
1583
	return ephy_node_has_child (keyword, bookmark);
1584
}
1585
1586
void
1587
ephy_bookmarks_set_keyword (EphyBookmarks *eb,
1588
			    EphyNode *keyword,
1589
			    EphyNode *bookmark)
1590
{
1591
	if (ephy_node_has_child (keyword, bookmark)) return;
1592
1593
	ephy_node_add_child (keyword, bookmark);
1594
1595
	if (ephy_node_has_child (eb->priv->notcategorized, bookmark))
1596
	{
1597
		LOG ("Remove from categorized bookmarks");
1598
		ephy_node_remove_child
1599
			(eb->priv->notcategorized, bookmark);
1600
	}
1601
1602
	update_bookmark_keywords (eb, bookmark);
1603
1604
	g_signal_emit (G_OBJECT (eb), ephy_bookmarks_signals[TREE_CHANGED], 0);
1605
}
1606
1607
void
1608
ephy_bookmarks_unset_keyword (EphyBookmarks *eb,
1609
			      EphyNode *keyword,
1610
			      EphyNode *bookmark)
1611
{
1612
	if (!ephy_node_has_child (keyword, bookmark)) return;
1613
1614
	ephy_node_remove_child (keyword, bookmark);
1615
1616
	if (!bookmark_is_categorized (eb, bookmark) &&
1617
	    !ephy_node_has_child (eb->priv->notcategorized, bookmark))
1618
	{
1619
		LOG ("Add to not categorized bookmarks");
1620
		ephy_node_add_child
1621
			(eb->priv->notcategorized, bookmark);
1622
	}
1623
1624
	update_bookmark_keywords (eb, bookmark);
1625
1626
	g_signal_emit (G_OBJECT (eb), ephy_bookmarks_signals[TREE_CHANGED], 0);
1627
}
1628
1.1.51 by Sebastian Dröge
Import upstream version 2.29.3
1629
/**
1630
 * ephy_bookmarks_get_smart_bookmarks:
1631
 *
1632
 * Return value: (transfer none):
1633
 **/
1 by Sebastien Bacher
Import upstream version 1.9.2
1634
EphyNode *
1635
ephy_bookmarks_get_smart_bookmarks (EphyBookmarks *eb)
1636
{
1637
	return eb->priv->smartbookmarks;
1638
}
1639
1.1.51 by Sebastian Dröge
Import upstream version 2.29.3
1640
/**
1641
 * ephy_bookmarks_get_keywords:
1642
 *
1643
 * Return value: (transfer none):
1644
 **/
1 by Sebastien Bacher
Import upstream version 1.9.2
1645
EphyNode *
1646
ephy_bookmarks_get_keywords (EphyBookmarks *eb)
1647
{
1648
	return eb->priv->keywords;
1649
}
1650
1.1.51 by Sebastian Dröge
Import upstream version 2.29.3
1651
/**
1652
 * ephy_bookmarks_get_bookmarks:
1653
 *
1654
 * Return value: (transfer none):
1655
 **/
1 by Sebastien Bacher
Import upstream version 1.9.2
1656
EphyNode *
1657
ephy_bookmarks_get_bookmarks (EphyBookmarks *eb)
1658
{
1659
	return eb->priv->bookmarks;
1660
}
1661
1.1.51 by Sebastian Dröge
Import upstream version 2.29.3
1662
/**
1663
 * ephy_bookmarks_get_local:
1664
 *
1665
 * Return value: (transfer none):
1666
 **/
1 by Sebastien Bacher
Import upstream version 1.9.2
1667
EphyNode *
1668
ephy_bookmarks_get_local (EphyBookmarks *eb)
1669
{
1670
	return eb->priv->local;
1671
}
1672
1.1.51 by Sebastian Dröge
Import upstream version 2.29.3
1673
/**
1674
 * ephy_bookmarks_get_not_categorized:
1675
 *
1676
 * Return value: (transfer none):
1677
 **/
1 by Sebastien Bacher
Import upstream version 1.9.2
1678
EphyNode *
1679
ephy_bookmarks_get_not_categorized (EphyBookmarks *eb)
1680
{
1681
	return eb->priv->notcategorized;
1682
}
1683
1.1.51 by Sebastian Dröge
Import upstream version 2.29.3
1684
/**
1685
 * ephy_bookmarks_get_from_id:
1686
 *
1687
 * Return value: (transfer none):
1688
 **/
1 by Sebastien Bacher
Import upstream version 1.9.2
1689
EphyNode *
1690
ephy_bookmarks_get_from_id (EphyBookmarks *eb, long id)
1691
{
1692
	return ephy_node_db_get_node_from_id (eb->priv->db, id);
1693
}
1694
1695
int
1696
ephy_bookmarks_compare_topics (gconstpointer a, gconstpointer b)
1697
{
1698
	EphyNode *node_a = (EphyNode *)a;
1699
	EphyNode *node_b = (EphyNode *)b;
1700
	const char *title1, *title2;
1701
	int priority1, priority2;
1702
1703
	priority1 = ephy_node_get_property_int (node_a, EPHY_NODE_KEYWORD_PROP_PRIORITY);
1704
	priority2 = ephy_node_get_property_int (node_b, EPHY_NODE_KEYWORD_PROP_PRIORITY);
1705
	
1706
	if (priority1 > priority2) return 1;
1707
	if (priority1 < priority2) return -1;
1708
1709
	title1 = ephy_node_get_property_string (node_a, EPHY_NODE_KEYWORD_PROP_NAME);
1710
	title2 = ephy_node_get_property_string (node_b, EPHY_NODE_KEYWORD_PROP_NAME);
1711
1712
	if (title1 == title2) return 0;
1713
	if (title1 == NULL) return -1;
1714
	if (title2 == NULL) return 1;
1715
	return g_utf8_collate (title1, title2);
1716
}
1717
1718
int
1719
ephy_bookmarks_compare_topic_pointers (gconstpointer a, gconstpointer b)
1720
{
1721
	EphyNode *node_a = *(EphyNode **)a;
1722
	EphyNode *node_b = *(EphyNode **)b;
1723
	
1724
	return ephy_bookmarks_compare_topics (node_a, node_b);
1725
}
1726
1727
int
1728
ephy_bookmarks_compare_bookmarks (gconstpointer a, gconstpointer b)
1729
{
1730
	EphyNode *node_a = (EphyNode *)a;
1731
	EphyNode *node_b = (EphyNode *)b;
1732
	const char *title1, *title2;
1733
	
1734
	title1 = ephy_node_get_property_string (node_a, EPHY_NODE_BMK_PROP_TITLE);
1735
	title2 = ephy_node_get_property_string (node_b, EPHY_NODE_BMK_PROP_TITLE);
1736
1737
	if (title1 == title2) return 0;
1738
	if (title1 == NULL) return -1;
1739
	if (title2 == NULL) return 1;
1740
	return g_utf8_collate (title1, title2);
1741
}
1742
1743
int
1744
ephy_bookmarks_compare_bookmark_pointers (gconstpointer a, gconstpointer b)
1745
{
1746
	EphyNode *node_a = *(EphyNode **)a;
1747
	EphyNode *node_b = *(EphyNode **)b;
1748
	
1749
	return ephy_bookmarks_compare_bookmarks (node_a, node_b);
1750
}