respect https prefix
[k8lowj.git] / src / link.c
blob9f475260bb13cee8f4e3f753dd9799b78764b181
1 /* logjam - a GTK client for LiveJournal.
2 * Copyright (C) 2000-2003 Evan Martin <evan@livejournal.com>
4 * vim: tabstop=4 shiftwidth=4 noexpandtab :
5 */
7 #include "gtk-all.h"
8 #include <gdk/gdkkeysyms.h>
9 #include <gdk/gdktypes.h>
10 #include <stdio.h>
11 #include "util-gtk.h"
12 #include "conf.h"
13 #include "jamdoc.h"
14 #include "util.h"
16 typedef struct {
17 GtkWidget *dlg;
18 GtkWidget *etext, *ruser, *euser, *rurl, *eurl;
19 JamDoc *doc;
20 gint sel_type, clip_type;
21 gchar *sel_input, *clip_input;
22 } LinkDialog;
24 static void
25 select_toggled(GtkToggleButton *tb, GtkWidget *focus) {
26 if (gtk_toggle_button_get_active(tb))
27 gtk_widget_grab_focus(focus);
30 static void
31 entry_focus_cb(GtkWidget *w, GdkEventFocus *e, GtkToggleButton *radio) {
32 gtk_toggle_button_set_active(radio, TRUE);
35 static GtkWidget*
36 radio_option(GSList *g, GtkWidget **radio, GtkWidget **entry,
37 const char *caption, const char *label, const char *initial) {
38 GtkWidget *vbox;
40 vbox = gtk_vbox_new(FALSE, 0);
41 *radio = gtk_radio_button_new_with_mnemonic(g, caption);
42 gtk_box_pack_start(GTK_BOX(vbox), *radio, FALSE, FALSE, 0);
44 *entry = gtk_entry_new();
45 gtk_entry_set_activates_default(GTK_ENTRY(*entry), TRUE);
46 g_signal_connect(G_OBJECT(*entry), "focus-in-event",
47 G_CALLBACK(entry_focus_cb), *radio);
48 if (initial)
49 gtk_entry_set_text(GTK_ENTRY(*entry), initial);
50 gtk_widget_set_size_request(*entry, 75, -1);
51 g_signal_connect(G_OBJECT(*radio), "toggled",
52 G_CALLBACK(select_toggled), *entry);
53 g_signal_connect(G_OBJECT(*radio), "activate",
54 G_CALLBACK(select_toggled), *entry);
56 if (label) {
57 GtkWidget *hbox = gtk_hbox_new(FALSE, 0);
58 gtk_box_pack_start(GTK_BOX(hbox),
59 gtk_label_new(label),
60 FALSE, FALSE, 0);
61 gtk_box_pack_start(GTK_BOX(hbox), *entry, TRUE, TRUE, 0);
62 gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
63 } else {
64 gtk_box_pack_start(GTK_BOX(vbox), *entry, TRUE, TRUE, 0);
67 return vbox;
70 #if !GLIB_CHECK_VERSION(2,2,0)
71 static gboolean
72 g_str_has_prefix(const gchar *str, const gchar *prefix) {
73 return (strncmp(str, prefix, strlen(prefix)) == 0);
75 #endif
77 #if 0
78 gchar*
79 link_magic(LinkRequest *lr) {
80 gchar *a, *b;
81 if (! ((lr->clip_type | lr->sel_type) & JAM_SELECTION_HAS_URL))
82 return NULL;
84 xml_escape(&lr->clip_input);
86 /* boo for no list primitives in c */
87 if (lr->clip_type & JAM_SELECTION_HAS_URL) {
88 a = lr->clip_input; b = lr->sel_input;
89 } else {
90 b = lr->clip_input; a = lr->sel_input;
93 return g_strdup_printf("<a href=\"%s\">%s</a>", a, b);
95 #endif
97 static void
98 make_link_dialog(LinkDialog *ld, GtkWindow *win, gboolean livejournal) {
99 GtkWidget *vbox;
100 GtkWidget *subbox;
101 GSList *rgroup;
103 ld->dlg = gtk_dialog_new_with_buttons(_("Make Link"),
104 win, GTK_DIALOG_MODAL,
105 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
106 GTK_STOCK_OK, GTK_RESPONSE_OK,
107 NULL);
108 gtk_dialog_set_default_response(GTK_DIALOG(ld->dlg), GTK_RESPONSE_OK);
110 vbox = gtk_vbox_new(FALSE, 10);
112 ld->etext = gtk_entry_new();
113 gtk_entry_set_activates_default(GTK_ENTRY(ld->etext), TRUE);
114 subbox = labelled_box_new(_("Link _Text:"), ld->etext);
115 gtk_box_pack_start(GTK_BOX(vbox), subbox, FALSE, FALSE, 0);
117 gtk_box_pack_start(GTK_BOX(vbox),
118 radio_option(NULL, &ld->rurl, &ld->eurl, _("_URL:"), NULL, ""),
119 FALSE, FALSE, 0);
121 rgroup = gtk_radio_button_get_group(GTK_RADIO_BUTTON(ld->rurl));
123 if (livejournal) {
124 gtk_box_pack_start(GTK_BOX(vbox),
125 radio_option(rgroup, &ld->ruser, &ld->euser,
126 _("_LiveJournal User:"), ".../users/", ""),
127 FALSE, FALSE, 0);
130 jam_dialog_set_contents(GTK_DIALOG(ld->dlg), vbox);
133 static gboolean
134 has_url(char *buf) {
135 if (!buf || buf[0] == 0) return FALSE;
136 /* just test a few of the obvious ones... */
137 if (g_str_has_prefix(buf, "http://") ||
138 g_str_has_prefix(buf, "https://") ||
139 g_str_has_prefix(buf, "ftp://") ||
140 g_str_has_suffix(buf, ".com") ||
141 g_str_has_suffix(buf, ".net") ||
142 g_str_has_suffix(buf, ".org"))
143 return TRUE;
144 return FALSE;
147 static void
148 prepopulate_fields(LinkDialog *ld, char *bufsel) {
149 GtkClipboard *clipboard;
150 char *clipsel, *url = NULL;
152 clipboard = gtk_clipboard_get(GDK_SELECTION_CLIPBOARD);
153 clipsel = gtk_clipboard_wait_for_text(clipboard);
155 if (bufsel && has_url(bufsel)) {
156 url = bufsel;
157 } else if (clipsel && has_url(clipsel)) {
158 url = clipsel;
161 if (bufsel)
162 gtk_entry_set_text(GTK_ENTRY(ld->etext), bufsel);
163 if (url) {
164 char *niceurl;
165 if (g_str_has_prefix(url, "http://") ||
166 g_str_has_prefix(url, "https://") ||
167 g_str_has_prefix(url, "ftp://")) {
168 niceurl = url;
169 } else {
170 niceurl = g_strdup_printf("http://%s", url);
172 gtk_entry_set_text(GTK_ENTRY(ld->eurl), niceurl);
173 if (niceurl != url)
174 g_free(niceurl);
177 g_free(clipsel);
180 static char*
181 get_link(LinkDialog *ld, JamAccount *acc) {
182 char *url, *user, *text;
183 char *link = NULL;
185 url = gtk_editable_get_chars(GTK_EDITABLE(ld->eurl), 0, -1);
186 xml_escape(&url);
187 user = gtk_editable_get_chars(GTK_EDITABLE(ld->euser), 0, -1);
188 xml_escape(&user);
189 text = gtk_editable_get_chars(GTK_EDITABLE(ld->etext), 0, -1);
190 xml_escape(&text);
192 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ld->rurl))) {
193 /* build a "url" link. */
194 link = g_strdup_printf("<noindex><a href=\"%s\" rel=\"nofollow\" rel=\"noreferrer\" style=\"text-decoration:overline\">%s</a></noindex>", url, text);
195 } else if (ld->ruser && gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ld->ruser))) {
196 /* build a "friends" link. */
197 LJServer *server = jam_account_lj_get_server(JAM_ACCOUNT_LJ(acc));
198 g_free(url);
199 url = g_strdup(server->url);
200 xml_escape(&url);
201 link = g_strdup_printf("<noindex><a href=\"%s/users/%s\" rel=\"nofollow\" rel=\"noreferrer\" style=\"text-decoration:overline\">%s</a></noindex>",
202 url, user, text);
204 g_free(url);
205 g_free(user);
206 g_free(text);
208 return link;
211 void
212 link_dialog_run(GtkWindow *win, JamDoc *doc) {
213 STACK(LinkDialog, ld);
214 GtkTextBuffer *buffer;
215 GtkTextIter start, end;
216 char *sel = NULL;
217 char *link;
219 JamAccount *acc = jam_doc_get_account(doc);
220 make_link_dialog(ld, win, JAM_ACCOUNT_IS_LJ(acc));
222 buffer = jam_doc_get_text_buffer(doc);
223 if (gtk_text_buffer_get_selection_bounds(buffer, &start, &end))
224 sel = gtk_text_buffer_get_text(buffer, &start, &end, FALSE);
225 prepopulate_fields(ld, sel);
226 g_free(sel);
228 if (gtk_dialog_run(GTK_DIALOG(ld->dlg)) != GTK_RESPONSE_OK) {
229 gtk_widget_destroy(ld->dlg);
230 return;
233 link = get_link(ld, acc);
235 gtk_widget_destroy(ld->dlg);
237 if (link) {
238 gtk_text_buffer_begin_user_action(buffer);
239 gtk_text_buffer_delete(buffer, &start, &end);
240 gtk_text_buffer_insert(buffer, &start, link, -1);
241 gtk_text_buffer_end_user_action(buffer);
242 g_free(link);