diff --git a/include/class.export.php b/include/class.export.php
index b95a7d16d587541188d40d4cc6f45097b00b757f..862a2149664da21e9caa910975c5618824d337e6 100644
--- a/include/class.export.php
+++ b/include/class.export.php
@@ -99,6 +99,56 @@ class Export {
 
         return false;
     }
+
+    static function saveUsers($sql, $filename, $how='csv') {
+
+        $exclude = array('name', 'email');
+        $form = UserForm::getUserForm();
+        $fields = $form->getExportableFields($exclude);
+
+        // Field selection callback
+        $fname = function ($f) {
+            return 'cdata.`'.$f->getSelectName().'` AS __field_'.$f->get('id');
+        };
+
+        $sql = substr_replace($sql,
+                ','.implode(',', array_map($fname, $fields)).' ',
+                strpos($sql, 'FROM '), 0);
+
+        $sql = substr_replace($sql,
+                'LEFT JOIN ('.$form->getCrossTabQuery($form->type, 'user_id', $exclude).') cdata
+                    ON (cdata.user_id = user.id) ',
+                strpos($sql, 'WHERE '), 0);
+
+        $cdata = array_combine(array_keys($fields),
+                array_values(array_map(
+                        function ($f) { return $f->get('label'); }, $fields)));
+
+        ob_start();
+        echo self::dumpQuery($sql,
+                array(
+                    'name'  =>  'Name',
+                    'organization' => 'Organization',
+                    'email' =>  'Email'
+                    ) + $cdata,
+                $how,
+                array('modify' => function(&$record, $keys) use ($fields) {
+                    foreach ($fields as $k=>$f) {
+                        if ($f && ($i = array_search($k, $keys)) !== false) {
+                            $record[$i] = $f->export($f->to_php($record[$i]));
+                        }
+                    }
+                    return $record;
+                    })
+                );
+        $stuff = ob_get_contents();
+        ob_end_clean();
+
+        if ($stuff)
+            Http::download($filename, "text/$how", $stuff);
+
+        return false;
+    }
 }
 
 class ResultSetExporter {
diff --git a/include/class.forms.php b/include/class.forms.php
index 4eeed67e73c36e51ae944873698a701eb34b4a1e..00a885f3ab0f9d6493660141a81f2f8539237cb1 100644
--- a/include/class.forms.php
+++ b/include/class.forms.php
@@ -493,6 +493,14 @@ class FormField {
         }
         return $this->_widget;
     }
+
+    function getSelectName() {
+        $name = $this->get('name') ?: 'field_'.$this->get('id');
+        if ($this->hasIdValue())
+            $name .= '_id';
+
+        return $name;
+    }
 }
 
 class TextboxField extends FormField {
diff --git a/include/staff/users.inc.php b/include/staff/users.inc.php
index e02c9dbc8cd90fb1500265770e282fb1ee93e7ce..a9fd4f3b91067a3aee7017808eddfd0981072342 100644
--- a/include/staff/users.inc.php
+++ b/include/staff/users.inc.php
@@ -3,10 +3,12 @@ if(!defined('OSTSCPINC') || !$thisstaff) die('Access Denied');
 
 $qstr='';
 
-$select = 'SELECT user.*, email.address as email, account.id as account_id, account.status ';
+$select = 'SELECT user.*, email.address as email, org.name as organization
+          , account.id as account_id, account.status as account_status ';
 
 $from = 'FROM '.USER_TABLE.' user '
       . 'LEFT JOIN '.USER_EMAIL_TABLE.' email ON (user.id = email.user_id) '
+      . 'LEFT JOIN '.ORGANIZATION_TABLE.' org ON (user.org_id = org.id) '
       . 'LEFT JOIN '.USER_ACCOUNT_TABLE.' account ON (account.user_id = user.id) ';
 
 $where='WHERE 1 ';
@@ -23,6 +25,7 @@ if ($_REQUEST['query']) {
     $where .= ' AND (
                     email.address LIKE \'%'.$search.'%\'
                     OR user.name LIKE \'%'.$search.'%\'
+                    OR org.name LIKE \'%'.$search.'%\'
                     OR value.value LIKE \'%'.$search.'%\'
                 )';
 
@@ -66,6 +69,9 @@ $from .= ' LEFT JOIN '.TICKET_TABLE.' ticket ON (ticket.user_id = user.id) ';
 
 $query="$select $from $where GROUP BY user.id ORDER BY $order_by LIMIT ".$pageNav->getStart().",".$pageNav->getLimit();
 //echo $query;
+$qhash = md5($query);
+$_SESSION['users_qs_'.$qhash] = $query;
+
 ?>
 <h2>User Directory</h2>
 <div style="width:700px; float:left;">
@@ -123,7 +129,7 @@ else
 
                 // Account status
                 if ($row['account_id'])
-                    $status = new UserAccountStatus($row['status']);
+                    $status = new UserAccountStatus($row['account_status']);
                 else
                     $status = 'Guest';
 
@@ -152,7 +158,10 @@ else
 </table>
 <?php
 if($res && $num): //Show options..
-    echo '<div>&nbsp;Page:'.$pageNav->getPageLinks().'&nbsp;</div>';
+    echo sprintf('<div>&nbsp;Page: %s &nbsp; <a class="no-pjax"
+            href="users.php?a=export&qh=%s">Export</a></div>',
+            $pageNav->getPageLinks(),
+            $qhash);
 endif;
 ?>
 </form>
diff --git a/scp/users.php b/scp/users.php
index 547d278ac52e5b3d91e7edd06c6602805d25b725..d209e397b523c664dd7c123ceacc038155e69643 100644
--- a/scp/users.php
+++ b/scp/users.php
@@ -77,6 +77,15 @@ if ($_POST) {
             $errors['err'] = 'Unknown action/command';
             break;
     }
+} elseif($_REQUEST['a'] == 'export') {
+    require_once(INCLUDE_DIR.'class.export.php');
+    $ts = strftime('%Y%m%d');
+    if (!($token=$_REQUEST['qh']))
+        $errors['err'] = 'Query token required';
+    elseif (!($query=$_SESSION['users_qs_'.$token]))
+        $errors['err'] = 'Query token not found';
+    elseif (!Export::saveUsers($query, "users-$ts.csv", 'csv'))
+        $errors['err'] = 'Internal error: Unable to dump query results';
 }
 
 $page = $user? 'user-view.inc.php' : 'users.inc.php';