diff --git a/cph_policies.patch b/cph_policies.patch new file mode 100644 index 0000000..b7d3d00 --- /dev/null +++ b/cph_policies.patch @@ -0,0 +1,639 @@ +--- src/cups.c 2009-02-27 14:55:03.000000000 +0100 ++++ src/cups.c 2009-02-27 14:53:40.000000000 +0100 +@@ -182,17 +182,16 @@ cph_cups_init (CphCups *cups) + gboolean + cph_cups_reconnect (CphCups *cups) + { +- gint return_value = -1; +- gint i; ++ int return_value = -1; ++ int i; + + cups->priv->reconnecting = TRUE; + + for (i = 0; i < MAX_RECONNECT_ATTEMPTS; i++) { +- return_value = httpReconnect (cups->priv->connection); +- if (return_value == 0) { +- break; +- } +- g_usleep (RECONNECT_DELAY); ++ return_value = httpReconnect (cups->priv->connection); ++ if (return_value == 0) ++ break; ++ g_usleep (RECONNECT_DELAY); + } + + cups->priv->reconnecting = FALSE; +@@ -347,6 +346,7 @@ _CPH_CUPS_IS_VALID (ppd_filename, "PPD f + _CPH_CUPS_IS_VALID (job_sheet, "job sheet", FALSE) + _CPH_CUPS_IS_VALID (error_policy, "error policy", FALSE) + _CPH_CUPS_IS_VALID (op_policy, "op policy", FALSE) ++_CPH_CUPS_IS_VALID (job_hold_until, "job hold until", FALSE) + + /* Check for users. Those are some printable strings, which souldn't be NULL. + * They should also not be empty, but it appears that it's possible to carry +@@ -411,7 +411,7 @@ _cph_cups_add_class_uri (ipp_t *req + + static void + _cph_cups_add_job_uri (ipp_t *request, +- gint job_id) ++ int job_id) + { + char uri[HTTP_MAX_URI + 1]; + +@@ -585,12 +585,18 @@ _cph_cups_send_new_printer_class_request + static gboolean + _cph_cups_send_new_simple_job_request (CphCups *cups, + ipp_op_t op, +- gint job_id, ++ int job_id, ++ const char *user_name, + CphResource resource) + { + ipp_t *request; + + request = ippNewRequest (op); ++ ++ if (user_name != NULL) ++ ippAddString (request, IPP_TAG_OPERATION, IPP_TAG_NAME, ++ "requesting-user-name", NULL, user_name); ++ + _cph_cups_add_job_uri (request, job_id); + + return _cph_cups_send_request (cups, request, resource); +@@ -598,18 +604,23 @@ _cph_cups_send_new_simple_job_request (C + + static gboolean + _cph_cups_send_new_job_attributes_request (CphCups *cups, +- gint job_id, ++ int job_id, + const char *name, + const char *value, ++ const char *user_name, + CphResource resource) + { + cups_option_t *options = NULL; + ipp_t *request; +- gint num_options = 0; ++ int num_options = 0; + + request = ippNewRequest (IPP_SET_JOB_ATTRIBUTES); + _cph_cups_add_job_uri (request, job_id); + ++ if (user_name != NULL) ++ ippAddString (request, IPP_TAG_OPERATION, IPP_TAG_NAME, ++ "requesting-user-name", NULL, user_name); ++ + num_options = cupsAddOption (name, value, + num_options, &options); + cupsEncodeOptions (request, num_options, options); +@@ -894,6 +905,7 @@ cph_cups_file_get (CphCups *cups, + + /* reset the internal status: we'll use the cups status */ + _cph_cups_set_internal_status (cups, NULL); ++ + cups->priv->last_status = cupsGetFile (cups->priv->connection, + resource, filename); + +@@ -908,6 +920,7 @@ cph_cups_file_get (CphCups *cups, + chown (filename, uid, gid); + + _cph_cups_set_internal_status (cups, NULL); ++ + cups->priv->last_status = cupsGetFile (cups->priv->connection, + resource, filename); + } +@@ -1687,41 +1700,78 @@ cph_cups_server_set_settings (CphCups + } + + gboolean +-cph_cups_job_cancel (CphCups *cups, +- gint job_id) ++cph_cups_job_cancel (CphCups *cups, ++ int job_id, ++ const char *user_name) + { + g_return_val_if_fail (CPH_IS_CUPS (cups), FALSE); + + return _cph_cups_send_new_simple_job_request (cups, IPP_CANCEL_JOB, + job_id, ++ user_name, + CPH_RESOURCE_ADMIN); + } + + gboolean +-cph_cups_job_restart (CphCups *cups, +- gint job_id) ++cph_cups_job_restart (CphCups *cups, ++ int job_id, ++ const char *user_name) + { + g_return_val_if_fail (CPH_IS_CUPS (cups), FALSE); + + return _cph_cups_send_new_simple_job_request (cups, IPP_RESTART_JOB, + job_id, ++ user_name, + CPH_RESOURCE_ADMIN); + } + + gboolean + cph_cups_job_set_hold_until (CphCups *cups, +- gint job_id, +- const char *job_hold_until) ++ int job_id, ++ const char *job_hold_until, ++ const char *user_name) + { + g_return_val_if_fail (CPH_IS_CUPS (cups), FALSE); + ++ if (!_cph_cups_is_job_hold_until_valid (cups, job_hold_until)) ++ return FALSE; ++ + return _cph_cups_send_new_job_attributes_request (cups, + job_id, + "job-hold-until", + job_hold_until, ++ user_name, + CPH_RESOURCE_ADMIN); + } + ++CphJobStatus ++cph_cups_job_get_status (CphCups *cups, ++ int job_id, ++ const char *user) ++{ ++ CphJobStatus status = CPH_JOB_STATUS_INVALID; ++ cups_job_t *jobs; ++ int num_jobs = 0; ++ int i; ++ ++ g_return_val_if_fail (CPH_IS_CUPS (cups), CPH_JOB_STATUS_INVALID); ++ ++ num_jobs = cupsGetJobs2 (cups->priv->connection, &jobs, NULL, 0, 0); ++ ++ for (i = 0; i < num_jobs; i++) { ++ if (jobs[i].id == job_id) { ++ status = CPH_JOB_STATUS_NOT_OWNED_BY_USER; ++ if (user != NULL && g_strcmp0 (jobs[i].user, user) == 0) ++ status = CPH_JOB_STATUS_OWNED_BY_USER; ++ break; ++ } ++ } ++ ++ cupsFreeJobs (num_jobs, jobs); ++ ++ return status; ++} ++ + /****************************************************** + * Non-object functions + ******************************************************/ +@@ -1788,28 +1838,3 @@ cph_cups_is_printer_uri_local (const cha + /* we don't know, so we assume it's not local */ + return FALSE; + } +- +-gboolean +-cph_cups_is_job_owner (CphCups *cups, +- gint job_id, +- const char *user) +-{ +- cups_job_t *jobs; +- gboolean user_job = FALSE; +- gint num_jobs = 0; +- gint i; +- +- g_return_val_if_fail (CPH_IS_CUPS (cups), FALSE); +- +- if (user == NULL) +- return FALSE; +- +- num_jobs = cupsGetJobs2 (cups->priv->connection, &jobs, NULL, 0, 0); +- +- for (i = 0; i < num_jobs; i++) { +- if (jobs[i].id == job_id && g_strcmp0 (jobs[i].user, user) == 0) +- user_job = TRUE; +- } +- +- return user_job; +-} +--- src/cups.h 2009-02-27 14:55:03.000000000 +0100 ++++ src/cups.h 2009-02-27 14:53:40.000000000 +0100 +@@ -48,6 +48,13 @@ typedef struct + GObjectClass parent_class; + } CphCupsClass; + ++typedef enum ++{ ++ CPH_JOB_STATUS_INVALID, ++ CPH_JOB_STATUS_OWNED_BY_USER, ++ CPH_JOB_STATUS_NOT_OWNED_BY_USER ++} CphJobStatus; ++ + GType cph_cups_get_type (void); + + CphCups *cph_cups_new (void); +@@ -161,18 +168,21 @@ gboolean cph_cups_is_printer_local (CphC + gboolean cph_cups_is_printer_uri_local (const char *uri); + + gboolean cph_cups_job_cancel (CphCups *cups, +- gint job_id); ++ int job_id, ++ const char *user_name); + + gboolean cph_cups_job_restart (CphCups *cups, +- gint job_id); ++ int job_id, ++ const char *user_name); + + gboolean cph_cups_job_set_hold_until (CphCups *cups, +- gint job_id, +- const char *job_hold_until); +- +-gboolean cph_cups_is_job_owner (CphCups *cups, +- gint job_id, +- const char *user); ++ int job_id, ++ const char *job_hold_until, ++ const char *user_name); ++ ++CphJobStatus cph_cups_job_get_status (CphCups *cups, ++ int job_id, ++ const char *user); + + G_END_DECLS + +--- src/cups-pk-helper-mechanism.c 2009-02-27 14:55:03.000000000 +0100 ++++ src/cups-pk-helper-mechanism.c 2009-02-27 14:53:40.000000000 +0100 +@@ -47,8 +47,6 @@ + + #include + +-#include +- + #include + + #include "cups-pk-helper-mechanism.h" +@@ -470,6 +468,28 @@ _cph_mechanism_get_action_for_name (CphM + return "printer-remote-edit"; + } + ++char * ++_cph_mechanism_get_callers_user_name (CphMechanism *mechanism, ++ DBusGMethodInvocation *context) ++{ ++ unsigned long sender_uid; ++ struct passwd *password_entry; ++ DBusError dbus_error; ++ gchar *sender; ++ char *user_name = NULL; ++ ++ sender = dbus_g_method_get_sender (context); ++ dbus_error_init (&dbus_error); ++ sender_uid = dbus_bus_get_unix_user (dbus_g_connection_get_connection (mechanism->priv->system_bus_connection), sender, &dbus_error); ++ password_entry = getpwuid ((uid_t) sender_uid); ++ ++ if (password_entry != NULL) ++ user_name = g_strdup (password_entry->pw_name); ++ ++ g_free (sender); ++ ++ return user_name; ++} + + /* helpers */ + +@@ -902,18 +922,21 @@ cph_mechanism_printer_set_default (CphMe + DBusGMethodInvocation *context) + { + gboolean ret; +- const char *action; ++ const char *last_action; + + reset_killtimer (mechanism); + +- action = _cph_mechanism_get_action_for_name (mechanism, name); ++ last_action = _cph_mechanism_get_action_for_name (mechanism, name); + if (!_check_polkit_for_action_v (mechanism, context, + "printeraddremove", ++ /* this is not the last check because ++ * it's likely most useful to the user ++ * to give "printer-X-edit" powers */ ++ "printer-default", + /* quite important, since it's + * automatically called after adding a + * printer */ +- action, +- "printer-set-default", ++ last_action, + NULL)) + return FALSE; + +@@ -930,19 +953,21 @@ cph_mechanism_printer_set_enabled (CphMe + DBusGMethodInvocation *context) + { + gboolean ret; +- const char *action; ++ const char *last_action; + + reset_killtimer (mechanism); + +- action = _cph_mechanism_get_action_for_name (mechanism, name); +- ++ last_action = _cph_mechanism_get_action_for_name (mechanism, name); + if (!_check_polkit_for_action_v (mechanism, context, + "printeraddremove", ++ /* this is not the last check because ++ * it's likely most useful to the user ++ * to give "printer-X-edit" powers */ ++ "printer-enable", + /* quite important, since it's + * automatically called after adding a + * printer */ +- action, +- "printer-enable", ++ last_action, + NULL)) + return FALSE; + +@@ -1013,115 +1038,114 @@ cph_mechanism_server_set_settings (CphMe + return TRUE; + } + +-gchar * +-cph_mechanism_get_callers_user_name (CphMechanism *mechanism, +- DBusGMethodInvocation *context) +-{ +- unsigned long sender_uid; +- struct passwd *password_entry; +- const gchar *sender; +- DBusError dbus_error; +- gchar *user_name = NULL; +- +- sender = dbus_g_method_get_sender (context); +- dbus_error_init (&dbus_error); +- sender_uid = dbus_bus_get_unix_user (dbus_g_connection_get_connection (mechanism->priv->system_bus_connection), sender, &dbus_error); +- password_entry = getpwuid ((uid_t) sender_uid); +- +- if (password_entry != NULL) { +- user_name = g_strdup(password_entry->pw_name); +- } +- +- return user_name; +-} +- + gboolean + cph_mechanism_job_cancel (CphMechanism *mechanism, +- gint id, ++ int id, + DBusGMethodInvocation *context) + { +- gboolean ret; +- gboolean callers_job = FALSE; +- char *user_name = NULL; ++ CphJobStatus job_status; ++ gboolean ret; ++ char *user_name = NULL; + + reset_killtimer (mechanism); + +- user_name = cph_mechanism_get_callers_user_name (mechanism, context); +- callers_job = cph_cups_is_job_owner (mechanism->priv->cups, id, user_name); +- g_free (user_name); ++ user_name = _cph_mechanism_get_callers_user_name (mechanism, context); ++ job_status = cph_cups_job_get_status (mechanism->priv->cups, id, user_name); + +- if (callers_job) { +- if (!_check_polkit_for_action (mechanism, context, "job-cancel")) +- return FALSE; +- } +- else { +- if (!_check_polkit_for_action (mechanism, context, "job-cancel-another-owner")) ++ switch (job_status) { ++ case CPH_JOB_STATUS_OWNED_BY_USER: { ++ if (!_check_polkit_for_action_v (mechanism, context, "job-not-owned-edit", "job-edit", NULL)) ++ return FALSE; ++ break; ++ } ++ case CPH_JOB_STATUS_NOT_OWNED_BY_USER: { ++ if (!_check_polkit_for_action (mechanism, context, "job-not-owned-edit")) ++ return FALSE; ++ break; ++ } ++ case CPH_JOB_STATUS_INVALID: + return FALSE; + } + +- ret = cph_cups_job_cancel (mechanism->priv->cups, id); ++ ret = cph_cups_job_cancel (mechanism->priv->cups, id, user_name); + _cph_mechanism_return_error (mechanism, context, !ret); + ++ g_free (user_name); ++ + return TRUE; + } + + gboolean + cph_mechanism_job_restart (CphMechanism *mechanism, +- gint id, ++ int id, + DBusGMethodInvocation *context) + { +- gboolean ret; +- gboolean callers_job = FALSE; +- char *user_name = NULL; ++ CphJobStatus job_status; ++ gboolean ret; ++ char *user_name = NULL; + + reset_killtimer (mechanism); + +- user_name = cph_mechanism_get_callers_user_name (mechanism, context); +- callers_job = cph_cups_is_job_owner (mechanism->priv->cups, id, user_name); +- g_free (user_name); ++ user_name = _cph_mechanism_get_callers_user_name (mechanism, context); ++ job_status = cph_cups_job_get_status (mechanism->priv->cups, id, user_name); + +- if (callers_job) { +- if (!_check_polkit_for_action (mechanism, context, "job-restart")) +- return FALSE; +- } +- else { +- if (!_check_polkit_for_action (mechanism, context, "job-restart-another-owner")) ++ switch (job_status) { ++ case CPH_JOB_STATUS_OWNED_BY_USER: { ++ if (!_check_polkit_for_action_v (mechanism, context, "job-not-owned-edit", "job-edit", NULL)) ++ return FALSE; ++ break; ++ } ++ case CPH_JOB_STATUS_NOT_OWNED_BY_USER: { ++ if (!_check_polkit_for_action (mechanism, context, "job-not-owned-edit")) ++ return FALSE; ++ break; ++ } ++ case CPH_JOB_STATUS_INVALID: + return FALSE; + } + +- ret = cph_cups_job_restart (mechanism->priv->cups, id); ++ ret = cph_cups_job_restart (mechanism->priv->cups, id, user_name); + _cph_mechanism_return_error (mechanism, context, !ret); + ++ g_free (user_name); ++ + return TRUE; + } + + gboolean + cph_mechanism_job_set_hold_until (CphMechanism *mechanism, +- gint id, ++ int id, + const char *job_hold_until, + DBusGMethodInvocation *context) + { +- gboolean ret; +- gboolean callers_job = FALSE; +- char *user_name = NULL; ++ CphJobStatus job_status; ++ gboolean ret; ++ char *user_name = NULL; + + reset_killtimer (mechanism); + +- user_name = cph_mechanism_get_callers_user_name (mechanism, context); +- callers_job = cph_cups_is_job_owner (mechanism->priv->cups, id, user_name); +- g_free (user_name); ++ user_name = _cph_mechanism_get_callers_user_name (mechanism, context); ++ job_status = cph_cups_job_get_status (mechanism->priv->cups, id, user_name); + +- if (callers_job) { +- if (!_check_polkit_for_action (mechanism, context, "job-set-hold-until")) +- return FALSE; +- } +- else { +- if (!_check_polkit_for_action (mechanism, context, "job-set-hold-until-another-owner")) ++ switch (job_status) { ++ case CPH_JOB_STATUS_OWNED_BY_USER: { ++ if (!_check_polkit_for_action_v (mechanism, context, "job-not-owned-edit", "job-edit", NULL)) ++ return FALSE; ++ break; ++ } ++ case CPH_JOB_STATUS_NOT_OWNED_BY_USER: { ++ if (!_check_polkit_for_action (mechanism, context, "job-not-owned-edit")) ++ return FALSE; ++ break; ++ } ++ case CPH_JOB_STATUS_INVALID: + return FALSE; + } + +- ret = cph_cups_job_set_hold_until (mechanism->priv->cups, id, job_hold_until); ++ ret = cph_cups_job_set_hold_until (mechanism->priv->cups, id, job_hold_until, user_name); + _cph_mechanism_return_error (mechanism, context, !ret); + ++ g_free (user_name); ++ + return TRUE; + } +--- src/cups-pk-helper-mechanism.h 2009-02-27 14:55:03.000000000 +0100 ++++ src/cups-pk-helper-mechanism.h 2009-02-27 14:53:40.000000000 +0100 +@@ -222,17 +222,17 @@ cph_mechanism_server_set_settings (CphMe + + gboolean + cph_mechanism_job_cancel (CphMechanism *mechanism, +- gint id, ++ int id, + DBusGMethodInvocation *context); + + gboolean + cph_mechanism_job_restart (CphMechanism *mechanism, +- gint id, ++ int id, + DBusGMethodInvocation *context); + + gboolean + cph_mechanism_job_set_hold_until (CphMechanism *mechanism, +- gint id, ++ int id, + const char *job_hold_until, + DBusGMethodInvocation *context); + +--- src/org.opensuse.CupsPkHelper.Mechanism.conf 2008-09-19 12:48:34.000000000 +0200 ++++ src/org.opensuse.CupsPkHelper.Mechanism.conf 2009-02-06 15:39:25.000000000 +0100 +@@ -8,12 +8,11 @@ + + + +- + + + + +- ++ + + + +--- src/org.opensuse.cupspkhelper.mechanism.policy.in 2009-02-27 14:55:03.000000000 +0100 ++++ src/org.opensuse.cupspkhelper.mechanism.policy.in 2009-02-27 14:53:40.000000000 +0100 +@@ -68,54 +68,18 @@ + + + +- +- <_description>Cancel a job +- <_message>Privileges are required to cancel a job. ++ ++ <_description>Restart/Cancel/Edit a job ++ <_message>Privileges are required to restart/cancel/edit a job. + + no + auth_self + + + +- +- <_description>Cancel a job owned by another user +- <_message>Privileges are required to cancel a job owned by another user. +- +- no +- auth_admin +- +- +- +- +- <_description>Restart a job +- <_message>Privileges are required to restart a job. +- +- no +- yes +- +- +- +- +- <_description>Restart a job owned by another user +- <_message>Privileges are required to restart a job owned by another user. +- +- no +- auth_admin +- +- +- +- +- <_description>Set hold-until time of a job +- <_message>Privileges are required to set hold-until time of a job. +- +- no +- yes +- +- +- +- +- <_description>Set hold-until time of a job owned by another user +- <_message>Privileges are required to set hold-until time of a job owned by another user. ++ ++ <_description>Restart/Cancel/Edit a job owned by another user ++ <_message>Privileges are required to restart/cancel/edit a job owned by another user. + + no + auth_admin diff --git a/cups-pk-helper.spec b/cups-pk-helper.spec index 4ae7efa..b6fa95f 100644 --- a/cups-pk-helper.spec +++ b/cups-pk-helper.spec @@ -1,6 +1,6 @@ Name: cups-pk-helper Version: 0.0.3 -Release: 5%{?dist} +Release: 6%{?dist} Summary: A helper that makes system-config-printer use PolicyKit Group: System Environment/Base @@ -12,6 +12,7 @@ Patch0: dependencies.patch Patch1: pk_order.patch Patch2: pk_jobs.patch Patch3: cph_reconnect.patch +Patch4: cph_policies.patch BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) @@ -38,6 +39,7 @@ interfaces available under control of PolicyKit. %patch1 -p0 -b .pk-order %patch2 -p0 -b .pk-jobs %patch3 -p0 -b .cph-reconnect +%patch4 -p0 -b .cph-policies %build %configure @@ -64,6 +66,12 @@ rm -rf $RPM_BUILD_ROOT %changelog +* Fri Feb 27 2009 Marek Kasik - 0.0.3-6 +- Replace job-cancel, job-restart and job-set-hold-until with job-edit +- Replace job-cancel-another-owner, job-restart-another-owner + and job-set-hold-until-another-owner with job-not-owned-edit +- Add cph_cups_job_get_status() function + some minor changes + * Tue Feb 24 2009 Fedora Release Engineering - 0.0.3-5 - Rebuilt for https://fedoraproject.org/wiki/Fedora_11_Mass_Rebuild