| 1244 else if (ui_handle != NULL) |
1244 else if (ui_handle != NULL) |
| 1245 gtk_widget_destroy(GTK_WIDGET(ui_handle)); |
1245 gtk_widget_destroy(GTK_WIDGET(ui_handle)); |
| 1246 } |
1246 } |
| 1247 |
1247 |
| 1248 #ifndef _WIN32 |
1248 #ifndef _WIN32 |
| 1249 static gint |
1249 static gboolean |
| 1250 uri_command(const char *command, gboolean sync) |
1250 uri_command(GSList *arg_list, gboolean sync) |
| 1251 { |
1251 { |
| 1252 gchar *tmp; |
1252 gchar *tmp; |
| 1253 GError *error = NULL; |
1253 GError *error = NULL; |
| 1254 gint ret = 0; |
1254 GSList *it; |
| 1255 |
1255 gchar **argv; |
| 1256 purple_debug_misc("gtknotify", "Executing %s\n", command); |
1256 gint argc, i; |
| 1257 |
1257 gchar *program; |
| 1258 if (!purple_program_is_valid(command)) |
1258 |
| 1259 { |
1259 g_return_val_if_fail(arg_list != NULL, FALSE); |
| 1260 tmp = g_strdup_printf(_("The browser command \"%s\" is invalid."), |
1260 |
| 1261 command ? command : "(none)"); |
1261 program = arg_list->data; |
| |
1262 purple_debug_misc("gtknotify", "Executing %s (%s)\n", program, |
| |
1263 sync ? "sync" : "async"); |
| |
1264 |
| |
1265 if (!purple_program_is_valid(program)) { |
| |
1266 purple_debug_error("gtknotify", "Command \"%s\" is invalid\n", |
| |
1267 program); |
| |
1268 tmp = g_strdup_printf( |
| |
1269 _("The browser command \"%s\" is invalid."), |
| |
1270 program ? program : "(null)"); |
| 1262 purple_notify_error(NULL, NULL, _("Unable to open URL"), tmp, NULL); |
1271 purple_notify_error(NULL, NULL, _("Unable to open URL"), tmp, NULL); |
| 1263 g_free(tmp); |
1272 g_free(tmp); |
| 1264 |
1273 |
| 1265 } |
1274 return FALSE; |
| 1266 else if (sync) |
1275 } |
| |
1276 |
| |
1277 argc = g_slist_length(arg_list); |
| |
1278 argv = g_new(gchar*, argc + 1); |
| |
1279 i = 0; |
| |
1280 for (it = arg_list; it; it = g_slist_next(it)) { |
| |
1281 if (purple_debug_is_verbose()) { |
| |
1282 purple_debug_misc("gtknotify", "argv[%d] = \"%s\"\n", |
| |
1283 i, (gchar*)it->data); |
| |
1284 } |
| |
1285 argv[i++] = it->data; |
| |
1286 } |
| |
1287 argv[i] = NULL; |
| |
1288 |
| |
1289 if (sync) { |
| |
1290 gint exit_status = 0; |
| |
1291 |
| |
1292 if (g_spawn_sync(NULL, argv, NULL, G_SPAWN_SEARCH_PATH | |
| |
1293 G_SPAWN_STDOUT_TO_DEV_NULL | G_SPAWN_STDERR_TO_DEV_NULL, |
| |
1294 NULL, NULL, NULL, NULL, &exit_status, &error) && |
| |
1295 exit_status == 0) |
| |
1296 { |
| |
1297 g_free(argv); |
| |
1298 return TRUE; |
| |
1299 } |
| |
1300 |
| |
1301 purple_debug_error("gtknotify", |
| |
1302 "Error launching \"%s\": %s (status: %d)\n", program, |
| |
1303 error ? error->message : "(null)", exit_status); |
| |
1304 tmp = g_strdup_printf(_("Error launching \"%s\": %s"), program, |
| |
1305 error ? error->message : "(null)"); |
| |
1306 g_error_free(error); |
| |
1307 purple_notify_error(NULL, NULL, _("Unable to open URL"), tmp, NULL); |
| |
1308 g_free(tmp); |
| |
1309 |
| |
1310 g_free(argv); |
| |
1311 return FALSE; |
| |
1312 } |
| |
1313 |
| |
1314 if (g_spawn_async(NULL, argv, NULL, G_SPAWN_SEARCH_PATH | |
| |
1315 G_SPAWN_STDOUT_TO_DEV_NULL | G_SPAWN_STDERR_TO_DEV_NULL, NULL, |
| |
1316 NULL, NULL, &error)) |
| 1267 { |
1317 { |
| 1268 gint status; |
1318 g_free(argv); |
| 1269 |
1319 return TRUE; |
| 1270 if (!g_spawn_command_line_sync(command, NULL, NULL, &status, &error)) |
1320 } |
| 1271 { |
1321 |
| 1272 tmp = g_strdup_printf(_("Error launching \"%s\": %s"), |
1322 purple_debug_warning("gtknotify", "Error launching \"%s\": %s\n", |
| 1273 command, error->message); |
1323 program, error ? error->message : "(null)"); |
| 1274 purple_notify_error(NULL, NULL, _("Unable to open URL"), tmp, NULL); |
1324 g_error_free(error); |
| 1275 g_free(tmp); |
1325 |
| 1276 g_error_free(error); |
1326 g_free(argv); |
| 1277 } |
1327 return FALSE; |
| 1278 else |
|
| 1279 ret = status; |
|
| 1280 } |
|
| 1281 else |
|
| 1282 { |
|
| 1283 if (!g_spawn_command_line_async(command, &error)) |
|
| 1284 { |
|
| 1285 tmp = g_strdup_printf(_("Error launching \"%s\": %s"), |
|
| 1286 command, error->message); |
|
| 1287 purple_notify_error(NULL, NULL, _("Unable to open URL"), tmp, NULL); |
|
| 1288 g_free(tmp); |
|
| 1289 g_error_free(error); |
|
| 1290 } |
|
| 1291 } |
|
| 1292 |
|
| 1293 return ret; |
|
| 1294 } |
1328 } |
| 1295 #endif /* _WIN32 */ |
1329 #endif /* _WIN32 */ |
| 1296 |
1330 |
| 1297 static void * |
1331 static void * |
| 1298 pidgin_notify_uri(const char *uri) |
1332 pidgin_notify_uri(const char *uri) |
| 1299 { |
1333 { |
| 1300 #ifndef _WIN32 |
1334 #ifndef _WIN32 |
| 1301 char *escaped = g_shell_quote(uri); |
|
| 1302 char *command = NULL; |
|
| 1303 char *remote_command = NULL; |
|
| 1304 const char *web_browser; |
1335 const char *web_browser; |
| 1305 int place; |
1336 int place; |
| 1306 |
1337 gchar *uri_escaped, *uri_custom = NULL; |
| 1307 web_browser = purple_prefs_get_string(PIDGIN_PREFS_ROOT "/browsers/browser"); |
1338 GSList *argv = NULL, *argv_remote = NULL; |
| |
1339 gchar **usercmd_argv = NULL; |
| |
1340 |
| |
1341 /* Replace some special characters like $ with their percent-encoded |
| |
1342 value. This shouldn't be necessary because we shell-escape the entire |
| |
1343 arg before exec'ing the browser, however, we had a report that a URL |
| |
1344 containing $(xterm) was causing xterm to start on his system. This is |
| |
1345 obviously a bug on his system, but it's pretty easy for us to protect |
| |
1346 against it. */ |
| |
1347 uri_escaped = g_uri_escape_string(uri, ":;/%#,+?=&@", FALSE); |
| |
1348 |
| |
1349 web_browser = purple_prefs_get_string(PIDGIN_PREFS_ROOT |
| |
1350 "/browsers/browser"); |
| 1308 place = purple_prefs_get_int(PIDGIN_PREFS_ROOT "/browsers/place"); |
1351 place = purple_prefs_get_int(PIDGIN_PREFS_ROOT "/browsers/place"); |
| 1309 |
1352 |
| 1310 /* if they are running gnome, use the gnome web browser */ |
1353 /* if they are running gnome, use the gnome web browser */ |
| 1311 if (purple_running_gnome() == TRUE) |
1354 if (purple_running_gnome() == TRUE) { |
| 1312 { |
|
| 1313 char *tmp = g_find_program_in_path("xdg-open"); |
1355 char *tmp = g_find_program_in_path("xdg-open"); |
| 1314 if (tmp == NULL) |
1356 if (tmp == NULL) |
| 1315 command = g_strdup_printf("gnome-open %s", escaped); |
1357 argv = g_slist_append(argv, "gnome-open"); |
| 1316 else |
1358 else |
| 1317 command = g_strdup_printf("xdg-open %s", escaped); |
1359 argv = g_slist_append(argv, "xdg-open"); |
| 1318 g_free(tmp); |
1360 g_free(tmp); |
| 1319 } |
1361 argv = g_slist_append(argv, uri_escaped); |
| 1320 else if (purple_running_osx() == TRUE) |
1362 } else if (purple_running_osx() == TRUE) { |
| 1321 { |
1363 argv = g_slist_append(argv, "open"); |
| 1322 command = g_strdup_printf("open %s", escaped); |
1364 argv = g_slist_append(argv, uri_escaped); |
| 1323 } |
1365 } else if (!strcmp(web_browser, "epiphany") || |
| 1324 else if (!strcmp(web_browser, "epiphany") || |
|
| 1325 !strcmp(web_browser, "galeon")) |
1366 !strcmp(web_browser, "galeon")) |
| 1326 { |
1367 { |
| |
1368 argv = g_slist_append(argv, (gpointer)web_browser); |
| |
1369 |
| 1327 if (place == PIDGIN_BROWSER_NEW_WINDOW) |
1370 if (place == PIDGIN_BROWSER_NEW_WINDOW) |
| 1328 command = g_strdup_printf("%s -w %s", web_browser, escaped); |
1371 argv = g_slist_append(argv, "-w"); |
| 1329 else if (place == PIDGIN_BROWSER_NEW_TAB) |
1372 else if (place == PIDGIN_BROWSER_NEW_TAB) |
| 1330 command = g_strdup_printf("%s -n %s", web_browser, escaped); |
1373 argv = g_slist_append(argv, "-n"); |
| 1331 else |
1374 |
| 1332 command = g_strdup_printf("%s %s", web_browser, escaped); |
1375 argv = g_slist_append(argv, uri_escaped); |
| 1333 } |
1376 } else if (!strcmp(web_browser, "xdg-open")) { |
| 1334 else if (!strcmp(web_browser, "xdg-open")) |
1377 argv = g_slist_append(argv, "xdg-open"); |
| 1335 { |
1378 argv = g_slist_append(argv, uri_escaped); |
| 1336 command = g_strdup_printf("xdg-open %s", escaped); |
1379 } else if (!strcmp(web_browser, "gnome-open")) { |
| 1337 } |
1380 argv = g_slist_append(argv, "gnome-open"); |
| 1338 else if (!strcmp(web_browser, "gnome-open")) |
1381 argv = g_slist_append(argv, uri_escaped); |
| 1339 { |
1382 } else if (!strcmp(web_browser, "kfmclient")) { |
| 1340 command = g_strdup_printf("gnome-open %s", escaped); |
1383 argv = g_slist_append(argv, "kfmclient"); |
| 1341 } |
1384 argv = g_slist_append(argv, "openURL"); |
| 1342 else if (!strcmp(web_browser, "kfmclient")) |
1385 argv = g_slist_append(argv, uri_escaped); |
| 1343 { |
|
| 1344 command = g_strdup_printf("kfmclient openURL %s", escaped); |
|
| 1345 /* |
1386 /* |
| 1346 * Does Konqueror have options to open in new tab |
1387 * Does Konqueror have options to open in new tab |
| 1347 * and/or current window? |
1388 * and/or current window? |
| 1348 */ |
1389 */ |
| 1349 } |
1390 } else if (!strcmp(web_browser, "mozilla") || |
| 1350 else if (!strcmp(web_browser, "mozilla") || |
1391 !strcmp(web_browser, "mozilla-firebird") || |
| 1351 !strcmp(web_browser, "mozilla-firebird") || |
1392 !strcmp(web_browser, "firefox") || |
| 1352 !strcmp(web_browser, "firefox") || |
1393 !strcmp(web_browser, "seamonkey")) |
| 1353 !strcmp(web_browser, "seamonkey")) |
|
| 1354 { |
1394 { |
| 1355 char *args = ""; |
1395 argv = g_slist_append(argv, (gpointer)web_browser); |
| 1356 |
1396 argv = g_slist_append(argv, uri_escaped); |
| 1357 command = g_strdup_printf("%s %s", web_browser, escaped); |
1397 |
| 1358 |
1398 g_assert(uri_custom == NULL); |
| 1359 /* |
1399 if (place == PIDGIN_BROWSER_NEW_WINDOW) { |
| 1360 * Firefox 0.9 and higher require a "-a firefox" option when |
1400 uri_custom = g_strdup_printf("openURL(%s,new-window)", |
| 1361 * using -remote commands. This breaks older versions of |
1401 uri_escaped); |
| 1362 * mozilla. So we include this other handly little string |
1402 } else if (place == PIDGIN_BROWSER_NEW_TAB) { |
| 1363 * when calling firefox. If the API for remote calls changes |
1403 uri_custom = g_strdup_printf("openURL(%s,new-tab)", |
| 1364 * any more in firefox then firefox should probably be split |
1404 uri_escaped); |
| 1365 * apart from mozilla-firebird and mozilla... but this is good |
1405 } |
| 1366 * for now. |
1406 |
| |
1407 if (uri_custom != NULL) { |
| |
1408 argv_remote = g_slist_append(argv_remote, |
| |
1409 (gpointer)web_browser); |
| |
1410 |
| |
1411 /* Firefox 0.9 and higher require a "-a firefox" option |
| |
1412 * when using -remote commands. This breaks older |
| |
1413 * versions of mozilla. So we include this other handly |
| |
1414 * little string when calling firefox. If the API for |
| |
1415 * remote calls changes any more in firefox then firefox |
| |
1416 * should probably be split apart from mozilla-firebird |
| |
1417 * and mozilla... but this is good for now. |
| |
1418 */ |
| |
1419 if (!strcmp(web_browser, "firefox")) { |
| |
1420 argv_remote = g_slist_append(argv_remote, "-a"); |
| |
1421 argv_remote = g_slist_append(argv_remote, |
| |
1422 "firefox"); |
| |
1423 } |
| |
1424 |
| |
1425 argv_remote = g_slist_append(argv_remote, "-remote"); |
| |
1426 argv_remote = g_slist_append(argv_remote, uri_custom); |
| |
1427 } |
| |
1428 } else if (!strcmp(web_browser, "opera")) { |
| |
1429 argv = g_slist_append(argv, "opera"); |
| |
1430 |
| |
1431 if (place == PIDGIN_BROWSER_NEW_WINDOW) |
| |
1432 argv = g_slist_append(argv, "-newwindow"); |
| |
1433 else if (place == PIDGIN_BROWSER_NEW_TAB) |
| |
1434 argv = g_slist_append(argv, "-newpage"); |
| |
1435 /* `opera -remote "openURL(%s)"` command causes Pidgin to hang, |
| |
1436 * if there is no Opera instance running. |
| 1367 */ |
1437 */ |
| 1368 if (!strcmp(web_browser, "firefox")) |
1438 |
| 1369 args = "-a firefox"; |
1439 argv = g_slist_append(argv, uri_escaped); |
| 1370 |
1440 } else if (!strcmp(web_browser, "google-chrome")) { |
| 1371 if (place == PIDGIN_BROWSER_NEW_WINDOW) |
1441 /* Google Chrome doesn't have command-line arguments that |
| 1372 remote_command = g_strdup_printf("%s %s -remote " |
1442 * control the opening of links from external calls. This is |
| 1373 "openURL(%s,new-window)", |
1443 * controlled solely from a preference within Google Chrome. |
| 1374 web_browser, args, escaped); |
1444 */ |
| 1375 else if (place == PIDGIN_BROWSER_NEW_TAB) |
1445 argv = g_slist_append(argv, "google-chrome"); |
| 1376 remote_command = g_strdup_printf("%s %s -remote " |
1446 argv = g_slist_append(argv, uri_escaped); |
| 1377 "openURL(%s,new-tab)", |
1447 } else if (!strcmp(web_browser, "chrome")) { |
| 1378 web_browser, args, escaped); |
1448 /* Chromium doesn't have command-line arguments that control |
| 1379 } |
1449 * the opening of links from external calls. This is controlled |
| 1380 else if (!strcmp(web_browser, "opera")) |
1450 * solely from a preference within Chromium. |
| 1381 { |
1451 */ |
| 1382 if (place == PIDGIN_BROWSER_NEW_WINDOW) |
1452 argv = g_slist_append(argv, "chrome"); |
| 1383 command = g_strdup_printf("opera -newwindow %s", escaped); |
1453 argv = g_slist_append(argv, uri_escaped); |
| 1384 else if (place == PIDGIN_BROWSER_NEW_TAB) |
1454 } else if (!strcmp(web_browser, "chromium-browser")) { |
| 1385 command = g_strdup_printf("opera -newpage %s", escaped); |
|
| 1386 else |
|
| 1387 command = g_strdup_printf("opera %s", escaped); |
|
| 1388 |
|
| 1389 } |
|
| 1390 else if (!strcmp(web_browser, "google-chrome")) |
|
| 1391 { |
|
| 1392 /* Google Chrome doesn't have command-line arguments that control the |
|
| 1393 * opening of links from external calls. This is controlled solely from |
|
| 1394 * a preference within Google Chrome. */ |
|
| 1395 command = g_strdup_printf("google-chrome %s", escaped); |
|
| 1396 } |
|
| 1397 else if (!strcmp(web_browser, "chrome")) |
|
| 1398 { |
|
| 1399 /* Chromium doesn't have command-line arguments that control the |
1455 /* Chromium doesn't have command-line arguments that control the |
| 1400 * opening of links from external calls. This is controlled solely from |
1456 * opening of links from external calls. This is controlled |
| 1401 * a preference within Chromium. */ |
1457 * solely from a preference within Chromium. |
| 1402 command = g_strdup_printf("chrome %s", escaped); |
1458 */ |
| 1403 } |
1459 argv = g_slist_append(argv, "chromium-browser"); |
| 1404 else if (!strcmp(web_browser, "chromium-browser")) |
1460 argv = g_slist_append(argv, uri_escaped); |
| 1405 { |
1461 } else if (!strcmp(web_browser, "custom")) { |
| 1406 /* Chromium doesn't have command-line arguments that control the |
1462 GError *error = NULL; |
| 1407 * opening of links from external calls. This is controlled solely from |
1463 const char *usercmd_command; |
| 1408 * a preference within Chromium. */ |
1464 gint usercmd_argc, i; |
| 1409 command = g_strdup_printf("chromium-browser %s", escaped); |
1465 gboolean uri_added = FALSE; |
| 1410 } |
1466 |
| 1411 else if (!strcmp(web_browser, "custom")) |
1467 usercmd_command = purple_prefs_get_string(PIDGIN_PREFS_ROOT |
| 1412 { |
1468 "/browsers/manual_command"); |
| 1413 const char *web_command; |
1469 |
| 1414 |
1470 if (usercmd_command == NULL || *usercmd_command == '\0') { |
| 1415 web_command = purple_prefs_get_string(PIDGIN_PREFS_ROOT "/browsers/manual_command"); |
|
| 1416 |
|
| 1417 if (web_command == NULL || *web_command == '\0') |
|
| 1418 { |
|
| 1419 purple_notify_error(NULL, NULL, _("Unable to open URL"), |
1471 purple_notify_error(NULL, NULL, _("Unable to open URL"), |
| 1420 _("The 'Manual' browser command has been " |
1472 _("The 'Manual' browser command has been " |
| 1421 "chosen, but no command has been set."), NULL); |
1473 "chosen, but no command has been set."), NULL); |
| |
1474 g_free(uri_escaped); |
| 1422 return NULL; |
1475 return NULL; |
| 1423 } |
1476 } |
| 1424 |
1477 |
| 1425 if (strstr(web_command, "%s")) |
1478 if (!g_shell_parse_argv(usercmd_command, &usercmd_argc, |
| 1426 command = purple_strreplace(web_command, "%s", escaped); |
1479 &usercmd_argv, &error)) |
| 1427 else |
|
| 1428 { |
1480 { |
| 1429 /* |
1481 purple_notify_error(NULL, NULL, _("Unable to open URL: " |
| 1430 * There is no "%s" in the browser command. Assume the user |
1482 "the 'Manual' browser command seems invalid."), |
| 1431 * wanted the URL tacked on to the end of the command. |
1483 error ? error->message : NULL, NULL); |
| 1432 */ |
1484 g_error_free(error); |
| 1433 command = g_strdup_printf("%s %s", web_command, escaped); |
1485 g_free(uri_escaped); |
| 1434 } |
1486 return NULL; |
| 1435 } |
1487 } |
| 1436 |
1488 |
| 1437 g_free(escaped); |
1489 for (i = 0; i < usercmd_argc; i++) { |
| 1438 |
1490 gchar *cmd_part = usercmd_argv[i]; |
| 1439 if (remote_command != NULL) |
1491 |
| 1440 { |
1492 if (uri_added || strstr(cmd_part, "%s") == NULL) { |
| |
1493 argv = g_slist_append(argv, cmd_part); |
| |
1494 continue; |
| |
1495 } |
| |
1496 |
| |
1497 uri_custom = purple_strreplace(cmd_part, "%s", |
| |
1498 uri_escaped); |
| |
1499 argv = g_slist_append(argv, uri_custom); |
| |
1500 uri_added = TRUE; |
| |
1501 } |
| |
1502 |
| |
1503 /* There is no "%s" in the browser command. Assume the user |
| |
1504 * wanted the URL tacked on to the end of the command. |
| |
1505 */ |
| |
1506 if (!uri_added) |
| |
1507 argv = g_slist_append(argv, uri_escaped); |
| |
1508 } |
| |
1509 |
| |
1510 if (argv_remote != NULL) { |
| 1441 /* try the remote command first */ |
1511 /* try the remote command first */ |
| 1442 if (uri_command(remote_command, TRUE) != 0) |
1512 if (!uri_command(argv_remote, TRUE)) |
| 1443 uri_command(command, FALSE); |
1513 uri_command(argv, FALSE); |
| 1444 |
1514 } else |
| 1445 g_free(remote_command); |
1515 uri_command(argv, FALSE); |
| 1446 |
1516 |
| 1447 } |
1517 g_strfreev(usercmd_argv); |
| 1448 else |
1518 g_free(uri_escaped); |
| 1449 uri_command(command, FALSE); |
1519 g_free(uri_custom); |
| 1450 |
1520 g_slist_free(argv); |
| 1451 g_free(command); |
1521 g_slist_free(argv_remote); |
| 1452 |
1522 |
| 1453 #else /* !_WIN32 */ |
1523 #else /* !_WIN32 */ |
| 1454 winpidgin_notify_uri(uri); |
1524 winpidgin_notify_uri(uri); |
| 1455 #endif /* !_WIN32 */ |
1525 #endif /* !_WIN32 */ |
| 1456 |
1526 |