From cd98f85260efd90cc93db78ee1efed997d0221c2 Mon Sep 17 00:00:00 2001 From: Andy Staudacher Date: Thu, 11 Feb 2010 13:11:31 -0800 Subject: Fix for ticket 1010: Don't leak valid user names in "forgot password" form. Includes fixes for user forms as well (edit user / email / password). --- modules/user/controllers/password.php | 44 +++++++++++++++++++---------------- modules/user/controllers/users.php | 12 +++++----- 2 files changed, 30 insertions(+), 26 deletions(-) (limited to 'modules/user') diff --git a/modules/user/controllers/password.php b/modules/user/controllers/password.php index 07fdc1ed..c6d7e889 100644 --- a/modules/user/controllers/password.php +++ b/modules/user/controllers/password.php @@ -19,12 +19,19 @@ */ class Password_Controller extends Controller { public function reset() { + $form = self::_reset_form(); if (request::method() == "post") { // @todo separate the post from get parts of this function access::verify_csrf(); - $this->_send_reset(); + // Basic validation (was some user name specified?) + if ($form->validate()) { + $this->_send_reset($form); + } else { + print json_encode(array("result" => "error", + "form" => (string) $form)); + } } else { - print $this->_reset_form(); + print $form; } } @@ -41,19 +48,9 @@ class Password_Controller extends Controller { } } - private function _send_reset() { - $form = $this->_reset_form(); - - $valid = $form->validate(); - if ($valid) { - $user = user::lookup_by_name($form->reset->inputs["name"]->value); - if (!$user->loaded() || empty($user->email)) { - $form->reset->inputs["name"]->add_error("no_email", 1); - $valid = false; - } - } - - if ($valid) { + private function _send_reset($form) { + $user = user::lookup_by_name($form->reset->inputs["name"]->value); + if ($user && !empty($user->email)) { $user->hash = md5(rand()); $user->save(); $message = new View("reset_password.html"); @@ -71,22 +68,29 @@ class Password_Controller extends Controller { log::success( "user", t("Password reset email sent for user %name", array("name" => $user->name))); - } else { + } else if (!$user) { // Don't include the username here until you're sure that it's XSS safe log::warning( - "user", "Password reset email requested for bogus user"); + "user", t("Password reset email requested for bogus user")); + } else { + log::warning( + "user", t("Password reset failed for %user_name (has no email address on record).", + array("user_name" => $user->name))); } + // Always pretend that an email has been sent to avoid leaking + // information on what user names are actually real. message::success(t("Password reset email sent")); print json_encode( array("result" => "success")); } - private function _reset_form() { + private static function _reset_form() { $form = new Forge(url::current(true), "", "post", array("id" => "g-reset-form")); $group = $form->group("reset")->label(t("Reset Password")); - $group->input("name")->label(t("Username"))->id("g-name")->class(null)->rules("required"); - $group->inputs["name"]->error_messages("no_email", t("No email, unable to reset password")); + $group->input("name")->label(t("Username"))->id("g-name")->class(null) + ->rules("required") + ->error_messages("required", t("You must enter a user name")); $group->submit("")->value(t("Reset")); return $form; diff --git a/modules/user/controllers/users.php b/modules/user/controllers/users.php index 0730f391..cd7d271f 100644 --- a/modules/user/controllers/users.php +++ b/modules/user/controllers/users.php @@ -20,7 +20,7 @@ class Users_Controller extends Controller { public function update($id) { $user = user::lookup($id); - if ($user->guest || $user->id != identity::active_user()->id) { + if (!$user || $user->guest || $user->id != identity::active_user()->id) { access::forbidden(); } @@ -63,7 +63,7 @@ class Users_Controller extends Controller { public function change_password($id) { $user = user::lookup($id); - if ($user->guest || $user->id != identity::active_user()->id) { + if (!$user || $user->guest || $user->id != identity::active_user()->id) { access::forbidden(); } @@ -99,7 +99,7 @@ class Users_Controller extends Controller { public function change_email($id) { $user = user::lookup($id); - if ($user->guest || $user->id != identity::active_user()->id) { + if (!$user || $user->guest || $user->id != identity::active_user()->id) { access::forbidden(); } @@ -134,7 +134,7 @@ class Users_Controller extends Controller { public function form_edit($id) { $user = user::lookup($id); - if ($user->guest || $user->id != identity::active_user()->id) { + if (!$user || $user->guest || $user->id != identity::active_user()->id) { access::forbidden(); } @@ -143,7 +143,7 @@ class Users_Controller extends Controller { public function form_change_password($id) { $user = user::lookup($id); - if ($user->guest || $user->id != identity::active_user()->id) { + if (!$user || $user->guest || $user->id != identity::active_user()->id) { access::forbidden(); } @@ -152,7 +152,7 @@ class Users_Controller extends Controller { public function form_change_email($id) { $user = user::lookup($id); - if ($user->guest || $user->id != identity::active_user()->id) { + if (!$user || $user->guest || $user->id != identity::active_user()->id) { access::forbidden(); } -- cgit v1.2.3 From dc94f6e45a7d45747582cd0ab99439330cd844f1 Mon Sep 17 00:00:00 2001 From: Andy Staudacher Date: Thu, 11 Feb 2010 14:35:05 -0800 Subject: Include user name in logging message for failed password reset. As Bharat points out, t() ensures that parameters are escaped for XSS. --- modules/user/controllers/password.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'modules/user') diff --git a/modules/user/controllers/password.php b/modules/user/controllers/password.php index c6d7e889..2f8dd990 100644 --- a/modules/user/controllers/password.php +++ b/modules/user/controllers/password.php @@ -49,7 +49,8 @@ class Password_Controller extends Controller { } private function _send_reset($form) { - $user = user::lookup_by_name($form->reset->inputs["name"]->value); + $user_name = $form->reset->inputs["name"]->value; + $user = user::lookup_by_name($user_name); if ($user && !empty($user->email)) { $user->hash = md5(rand()); $user->save(); @@ -71,7 +72,8 @@ class Password_Controller extends Controller { } else if (!$user) { // Don't include the username here until you're sure that it's XSS safe log::warning( - "user", t("Password reset email requested for bogus user")); + "user", t("Password reset email requested for user %user_name, which does not exist.", + array("user_name" => $user_name))); } else { log::warning( "user", t("Password reset failed for %user_name (has no email address on record).", -- cgit v1.2.3 From cd45c94fe69f24b0f80a79e4b9c402763739ecfc Mon Sep 17 00:00:00 2001 From: Andy Staudacher Date: Thu, 11 Feb 2010 15:59:17 -0800 Subject: Get rid of unnecessary view file. --- modules/user/controllers/password.php | 7 +++---- modules/user/views/confirm_reset_password.html.php | 2 -- 2 files changed, 3 insertions(+), 6 deletions(-) delete mode 100644 modules/user/views/confirm_reset_password.html.php (limited to 'modules/user') diff --git a/modules/user/controllers/password.php b/modules/user/controllers/password.php index 2f8dd990..f5190974 100644 --- a/modules/user/controllers/password.php +++ b/modules/user/controllers/password.php @@ -116,20 +116,19 @@ class Password_Controller extends Controller { "mistyped", t("The password and the confirm password must match")); $group->submit("")->value(t("Update")); - $template->content = new View("confirm_reset_password.html"); - $template->content->form = $form; + $template->content = $form; return $template; } private function _change_password() { $view = $this->_new_password_form(); - if ($view->content->form->validate()) { + if ($view->content->validate()) { $user = user::lookup_by_hash(Input::instance()->post("hash")); if (empty($user)) { throw new Exception("@todo FORBIDDEN", 503); } - $user->password = $view->content->form->reset->password->value; + $user->password = $view->content->reset->password->value; $user->hash = null; $user->save(); message::success(t("Password reset successfully")); diff --git a/modules/user/views/confirm_reset_password.html.php b/modules/user/views/confirm_reset_password.html.php deleted file mode 100644 index 4993189e..00000000 --- a/modules/user/views/confirm_reset_password.html.php +++ /dev/null @@ -1,2 +0,0 @@ - - \ No newline at end of file -- cgit v1.2.3 From 409121942590e12692eaf4e6e9e8b71bfe5ed60c Mon Sep 17 00:00:00 2001 From: Andy Staudacher Date: Sun, 14 Feb 2010 19:26:34 -0800 Subject: Fix for ticket #491: Make user and group names translatable. Also fixed a UI bug: No longer showing the edit user buttons to admins in the profile view (to be consistent with the requirements in the controller). --- modules/gallery/controllers/user_profile.php | 5 +++-- modules/gallery/helpers/gallery_event.php | 3 +++ modules/gallery/views/permissions_form.html.php | 2 +- modules/user/helpers/user_installer.php | 8 ++++---- modules/user/models/user.php | 2 +- modules/user/views/admin_users.html.php | 2 +- modules/user/views/admin_users_group.html.php | 6 +++--- 7 files changed, 16 insertions(+), 12 deletions(-) (limited to 'modules/user') diff --git a/modules/gallery/controllers/user_profile.php b/modules/gallery/controllers/user_profile.php index 327d2ff1..05373466 100644 --- a/modules/gallery/controllers/user_profile.php +++ b/modules/gallery/controllers/user_profile.php @@ -23,7 +23,8 @@ class User_Profile_Controller extends Controller { $user = identity::lookup_user($id); $active_user = identity::active_user(); $is_current_active = $active_user->id == $id; - $display_all = $active_user->admin || ($is_current_active && !$active_user->guest); + $can_edit = $is_current_active && !$active_user->guest; + $display_all = $active_user->admin || $can_edit; $v = new Theme_View("page.html", "other", "profile"); $v->page_title = t("%name Profile", array("name" => $user->display_name())); @@ -32,7 +33,7 @@ class User_Profile_Controller extends Controller { // @todo modify user_home to supply a link to their album, $v->content->user = $user; $v->content->not_current = !$is_current_active; - $v->content->editable = identity::is_writable() && $display_all; + $v->content->editable = identity::is_writable() && $can_edit; $event_data = (object)array("user" => $user, "display_all" => $display_all, "content" => array()); module::event("show_user_profile", $event_data); diff --git a/modules/gallery/helpers/gallery_event.php b/modules/gallery/helpers/gallery_event.php index faf1c0c6..3f77bc42 100644 --- a/modules/gallery/helpers/gallery_event.php +++ b/modules/gallery/helpers/gallery_event.php @@ -423,6 +423,9 @@ class gallery_event_Core { if ($field == "locale") { $value = locales::display_name($value); } + if ($field == "full_name") { + $value = t($value); + } $v->user_profile_data[(string) $label] = $value; } } diff --git a/modules/gallery/views/permissions_form.html.php b/modules/gallery/views/permissions_form.html.php index f1714119..b486acb7 100644 --- a/modules/gallery/views/permissions_form.html.php +++ b/modules/gallery/views/permissions_form.html.php @@ -5,7 +5,7 @@ - name) ?> + name)) ?> diff --git a/modules/user/helpers/user_installer.php b/modules/user/helpers/user_installer.php index 729f087a..c57ad010 100644 --- a/modules/user/helpers/user_installer.php +++ b/modules/user/helpers/user_installer.php @@ -98,25 +98,25 @@ class user_installer { DEFAULT CHARSET=utf8;"); $everybody = ORM::factory("group"); - $everybody->name = "Everybody"; + $everybody->name = t("Everybody", array("locale" => "root")); $everybody->special = true; $everybody->save(); $registered = ORM::factory("group"); - $registered->name = "Registered Users"; + $registered->name = t("Registered Users", array("locale" => "root")); $registered->special = true; $registered->save(); $guest = ORM::factory("user"); $guest->name = "guest"; - $guest->full_name = "Guest User"; + $guest->full_name = t("Guest User", array("locale" => "root")); $guest->password = ""; $guest->guest = true; $guest->save(); $admin = ORM::factory("user"); $admin->name = "admin"; - $admin->full_name = "Gallery Administrator"; + $admin->full_name = t("Gallery Administrator", array("locale" => "root")); $admin->password = "admin"; $admin->email = "unknown@unknown.com"; $admin->admin = true; diff --git a/modules/user/models/user.php b/modules/user/models/user.php index 4404ee63..aa752203 100644 --- a/modules/user/models/user.php +++ b/modules/user/models/user.php @@ -113,7 +113,7 @@ class User_Model extends ORM implements User_Definition { * @return string */ public function display_name() { - return empty($this->full_name) ? $this->name : $this->full_name; + return empty($this->full_name) ? $this->name : t($this->full_name); } /** diff --git a/modules/user/views/admin_users.html.php b/modules/user/views/admin_users.html.php index 270a7207..69d97547 100644 --- a/modules/user/views/admin_users.html.php +++ b/modules/user/views/admin_users.html.php @@ -78,7 +78,7 @@ name) ?> - full_name) ?> + full_name)) ?> email) ?> diff --git a/modules/user/views/admin_users_group.html.php b/modules/user/views/admin_users_group.html.php index 6c6c341e..8317d393 100644 --- a/modules/user/views/admin_users_group.html.php +++ b/modules/user/views/admin_users_group.html.php @@ -1,9 +1,9 @@

- name) ?> + name)) ?> special): ?> id") ?>" - title=" $group->name))->for_html_attr() ?>" + title=" t(html::clean($group->name))))->for_html_attr() ?>" class="g-dialog-link g-button g-right"> @@ -22,7 +22,7 @@ $user->name, "group" => $group->name))->for_html_attr() ?>"> + array("user" => $user->name, "group" => t(html::clean($group->name))))->for_html_attr() ?>"> -- cgit v1.2.3 From dcddc68f58dac2f0fe71f5a00ea4af32618efa13 Mon Sep 17 00:00:00 2001 From: Andy Staudacher Date: Mon, 15 Feb 2010 13:12:38 -0800 Subject: Never assign a SafeString instance to a Model member (or hell will break loose). --- modules/gallery/helpers/gallery_installer.php | 2 +- modules/user/helpers/user_installer.php | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'modules/user') diff --git a/modules/gallery/helpers/gallery_installer.php b/modules/gallery/helpers/gallery_installer.php index 45d991af..b594ddcf 100644 --- a/modules/gallery/helpers/gallery_installer.php +++ b/modules/gallery/helpers/gallery_installer.php @@ -287,7 +287,7 @@ class gallery_installer { // Mark string for translation $powered_by_string = t("Powered by %gallery_version", array("locale" => "root")); - module::set_var("gallery", "credits", $powered_by_string); + module::set_var("gallery", "credits", (string) $powered_by_string); module::set_var("gallery", "simultaneous_upload_limit", 5); module::set_var("gallery", "admin_area_timeout", 90 * 60); module::set_version("gallery", 29); diff --git a/modules/user/helpers/user_installer.php b/modules/user/helpers/user_installer.php index c57ad010..9e757ecd 100644 --- a/modules/user/helpers/user_installer.php +++ b/modules/user/helpers/user_installer.php @@ -98,25 +98,25 @@ class user_installer { DEFAULT CHARSET=utf8;"); $everybody = ORM::factory("group"); - $everybody->name = t("Everybody", array("locale" => "root")); + $everybody->name = (string) t("Everybody", array("locale" => "root")); $everybody->special = true; $everybody->save(); $registered = ORM::factory("group"); - $registered->name = t("Registered Users", array("locale" => "root")); + $registered->name = (string) t("Registered Users", array("locale" => "root")); $registered->special = true; $registered->save(); $guest = ORM::factory("user"); $guest->name = "guest"; - $guest->full_name = t("Guest User", array("locale" => "root")); + $guest->full_name = (string) t("Guest User", array("locale" => "root")); $guest->password = ""; $guest->guest = true; $guest->save(); $admin = ORM::factory("user"); $admin->name = "admin"; - $admin->full_name = t("Gallery Administrator", array("locale" => "root")); + $admin->full_name = (string) t("Gallery Administrator", array("locale" => "root")); $admin->password = "admin"; $admin->email = "unknown@unknown.com"; $admin->admin = true; -- cgit v1.2.3 From 99c131e845b5bbfa22b93fa783b5ce671bc27e40 Mon Sep 17 00:00:00 2001 From: Bharat Mediratta Date: Thu, 18 Feb 2010 16:20:23 -0800 Subject: Revert "Never assign a SafeString instance to a Model member (or hell will break loose)." This reverts commit dcddc68f58dac2f0fe71f5a00ea4af32618efa13. --- modules/gallery/helpers/gallery_installer.php | 2 +- modules/user/helpers/user_installer.php | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'modules/user') diff --git a/modules/gallery/helpers/gallery_installer.php b/modules/gallery/helpers/gallery_installer.php index b594ddcf..45d991af 100644 --- a/modules/gallery/helpers/gallery_installer.php +++ b/modules/gallery/helpers/gallery_installer.php @@ -287,7 +287,7 @@ class gallery_installer { // Mark string for translation $powered_by_string = t("Powered by %gallery_version", array("locale" => "root")); - module::set_var("gallery", "credits", (string) $powered_by_string); + module::set_var("gallery", "credits", $powered_by_string); module::set_var("gallery", "simultaneous_upload_limit", 5); module::set_var("gallery", "admin_area_timeout", 90 * 60); module::set_version("gallery", 29); diff --git a/modules/user/helpers/user_installer.php b/modules/user/helpers/user_installer.php index 9e757ecd..c57ad010 100644 --- a/modules/user/helpers/user_installer.php +++ b/modules/user/helpers/user_installer.php @@ -98,25 +98,25 @@ class user_installer { DEFAULT CHARSET=utf8;"); $everybody = ORM::factory("group"); - $everybody->name = (string) t("Everybody", array("locale" => "root")); + $everybody->name = t("Everybody", array("locale" => "root")); $everybody->special = true; $everybody->save(); $registered = ORM::factory("group"); - $registered->name = (string) t("Registered Users", array("locale" => "root")); + $registered->name = t("Registered Users", array("locale" => "root")); $registered->special = true; $registered->save(); $guest = ORM::factory("user"); $guest->name = "guest"; - $guest->full_name = (string) t("Guest User", array("locale" => "root")); + $guest->full_name = t("Guest User", array("locale" => "root")); $guest->password = ""; $guest->guest = true; $guest->save(); $admin = ORM::factory("user"); $admin->name = "admin"; - $admin->full_name = (string) t("Gallery Administrator", array("locale" => "root")); + $admin->full_name = t("Gallery Administrator", array("locale" => "root")); $admin->password = "admin"; $admin->email = "unknown@unknown.com"; $admin->admin = true; -- cgit v1.2.3 From 7d98d4b7b9d16f32ed98c8eeb051be4149468dc6 Mon Sep 17 00:00:00 2001 From: Bharat Mediratta Date: Thu, 18 Feb 2010 16:20:59 -0800 Subject: Revert "Fix for ticket #491: Make user and group names translatable." This reverts commit 409121942590e12692eaf4e6e9e8b71bfe5ed60c. --- modules/gallery/controllers/user_profile.php | 5 ++--- modules/gallery/helpers/gallery_event.php | 3 --- modules/gallery/views/permissions_form.html.php | 2 +- modules/user/helpers/user_installer.php | 8 ++++---- modules/user/models/user.php | 2 +- modules/user/views/admin_users.html.php | 2 +- modules/user/views/admin_users_group.html.php | 6 +++--- 7 files changed, 12 insertions(+), 16 deletions(-) (limited to 'modules/user') diff --git a/modules/gallery/controllers/user_profile.php b/modules/gallery/controllers/user_profile.php index 05373466..327d2ff1 100644 --- a/modules/gallery/controllers/user_profile.php +++ b/modules/gallery/controllers/user_profile.php @@ -23,8 +23,7 @@ class User_Profile_Controller extends Controller { $user = identity::lookup_user($id); $active_user = identity::active_user(); $is_current_active = $active_user->id == $id; - $can_edit = $is_current_active && !$active_user->guest; - $display_all = $active_user->admin || $can_edit; + $display_all = $active_user->admin || ($is_current_active && !$active_user->guest); $v = new Theme_View("page.html", "other", "profile"); $v->page_title = t("%name Profile", array("name" => $user->display_name())); @@ -33,7 +32,7 @@ class User_Profile_Controller extends Controller { // @todo modify user_home to supply a link to their album, $v->content->user = $user; $v->content->not_current = !$is_current_active; - $v->content->editable = identity::is_writable() && $can_edit; + $v->content->editable = identity::is_writable() && $display_all; $event_data = (object)array("user" => $user, "display_all" => $display_all, "content" => array()); module::event("show_user_profile", $event_data); diff --git a/modules/gallery/helpers/gallery_event.php b/modules/gallery/helpers/gallery_event.php index 3f77bc42..faf1c0c6 100644 --- a/modules/gallery/helpers/gallery_event.php +++ b/modules/gallery/helpers/gallery_event.php @@ -423,9 +423,6 @@ class gallery_event_Core { if ($field == "locale") { $value = locales::display_name($value); } - if ($field == "full_name") { - $value = t($value); - } $v->user_profile_data[(string) $label] = $value; } } diff --git a/modules/gallery/views/permissions_form.html.php b/modules/gallery/views/permissions_form.html.php index b486acb7..f1714119 100644 --- a/modules/gallery/views/permissions_form.html.php +++ b/modules/gallery/views/permissions_form.html.php @@ -5,7 +5,7 @@ - name)) ?> + name) ?> diff --git a/modules/user/helpers/user_installer.php b/modules/user/helpers/user_installer.php index c57ad010..729f087a 100644 --- a/modules/user/helpers/user_installer.php +++ b/modules/user/helpers/user_installer.php @@ -98,25 +98,25 @@ class user_installer { DEFAULT CHARSET=utf8;"); $everybody = ORM::factory("group"); - $everybody->name = t("Everybody", array("locale" => "root")); + $everybody->name = "Everybody"; $everybody->special = true; $everybody->save(); $registered = ORM::factory("group"); - $registered->name = t("Registered Users", array("locale" => "root")); + $registered->name = "Registered Users"; $registered->special = true; $registered->save(); $guest = ORM::factory("user"); $guest->name = "guest"; - $guest->full_name = t("Guest User", array("locale" => "root")); + $guest->full_name = "Guest User"; $guest->password = ""; $guest->guest = true; $guest->save(); $admin = ORM::factory("user"); $admin->name = "admin"; - $admin->full_name = t("Gallery Administrator", array("locale" => "root")); + $admin->full_name = "Gallery Administrator"; $admin->password = "admin"; $admin->email = "unknown@unknown.com"; $admin->admin = true; diff --git a/modules/user/models/user.php b/modules/user/models/user.php index aa752203..4404ee63 100644 --- a/modules/user/models/user.php +++ b/modules/user/models/user.php @@ -113,7 +113,7 @@ class User_Model extends ORM implements User_Definition { * @return string */ public function display_name() { - return empty($this->full_name) ? $this->name : t($this->full_name); + return empty($this->full_name) ? $this->name : $this->full_name; } /** diff --git a/modules/user/views/admin_users.html.php b/modules/user/views/admin_users.html.php index 69d97547..270a7207 100644 --- a/modules/user/views/admin_users.html.php +++ b/modules/user/views/admin_users.html.php @@ -78,7 +78,7 @@ name) ?> - full_name)) ?> + full_name) ?> email) ?> diff --git a/modules/user/views/admin_users_group.html.php b/modules/user/views/admin_users_group.html.php index 8317d393..6c6c341e 100644 --- a/modules/user/views/admin_users_group.html.php +++ b/modules/user/views/admin_users_group.html.php @@ -1,9 +1,9 @@

- name)) ?> + name) ?> special): ?> id") ?>" - title=" t(html::clean($group->name))))->for_html_attr() ?>" + title=" $group->name))->for_html_attr() ?>" class="g-dialog-link g-button g-right"> @@ -22,7 +22,7 @@ $user->name, "group" => t(html::clean($group->name))))->for_html_attr() ?>"> + array("user" => $user->name, "group" => $group->name))->for_html_attr() ?>"> -- cgit v1.2.3 From f4fc245603fc8ec1bb9536356c8d4ab017153c08 Mon Sep 17 00:00:00 2001 From: Chad Kieffer Date: Sat, 20 Feb 2010 10:48:27 -0700 Subject: Add link to edit user group names. Closes ticket #1028. --- modules/user/views/admin_users_group.html.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'modules/user') diff --git a/modules/user/views/admin_users_group.html.php b/modules/user/views/admin_users_group.html.php index 6c6c341e..2362e42b 100644 --- a/modules/user/views/admin_users_group.html.php +++ b/modules/user/views/admin_users_group.html.php @@ -1,6 +1,8 @@

- name) ?> + id") ?>" + title=" $group->name))->for_html_attr() ?>" + class="g-dialog-link">name) ?> special): ?> id") ?>" title=" $group->name))->for_html_attr() ?>" -- cgit v1.2.3