Author: jfthomps
Date: Fri Sep 30 16:56:45 2016
New Revision: 1762935

URL: http://svn.apache.org/viewvc?rev=1762935&view=rev
Log:
VCL-277 - Add support for images to join Active Directory domains
VCL-867 - Active Directory Authentication for Windows VM's

incorporated patches from Junaid Ali attached to VCL-867; the VCL resource code 
has been largely rewritten since the patches were generated, so that part 
needed to be rewritten as well; shortened some of the names of fields and tables

addomain.php: initial add; definition of ADdomain class which inherits from 
Resource class

image.php:
-modified fieldWidth: added os, addomain, baseOU, adauthenabled
-modified fieldDisplayName: added adauthenabled, addomain, baseOU
-modified addEditDialogHTML: added fieldset and fields for AD authentication; 
added tooltip for baseOU
-modified AJsaveResource: added section that inserts/deletes/updates 
imageaddomain table as appropriate
-modified addResource: added section to insert into imageaddomain table as 
appropriate
-modified validateResourceData: added array keys and validation for 
adauthendabled, addomainid, baseou

resource.php:
-modified resource: added case statement for addomain
-modified viewResources and fieldWidth: added conditional for Edge browser for 
setting widths (unrelated to these JIRAs)
-added checkExistingField 

states.php:
-added addomain to $actions["entry"]
-added addomain to $actions['mode'], $actions['args'], and $actions['pages']

utils.php:
-modified initGlobals: added case for addomain in section that require_once's 
resource.php
-modified getImages: added addomainid, addomain, and baseOU to query and 
returned data; added adauthenabled to returned data
-modified getResourceGroupMembers: added conditional for $type == addomain; 
added addomain to $names, $joins, and $orders
-added getADdomains
-modified labeledFormItem: added case for password to go along with text case; 
changed hard coded 'text' for input type to be $type so it matches the passed 
in type to be either text or password
-added validateHostname
-modified getNavMenuData: added AD Domains menu entry for users with 
addomainAdmin
-modified getDojoHTML: added addomain case statement to include addomain.js to 
switch statement in groupMapHTML, viewResources, and editConfigMap case 
statements

image.js:
-modified Image.prototype.colformatter: added adauthenabled for true/false 
part; added addomain and baseOU to (unset) part
-modified inlineEditResourceCB: added showing/hiding of imageadauthbox; added 
setting of adauthenable, addomainid, and baseou
-modified resetEditResource: added resets for adauthenable, addomainid, and 
baseou
-modified saveResource: added for validation of baseou; added adauthenabled, 
addomainid, and baseou to submitted data
-modified saveResourceCB: added setting for adauthenabled, addomainid, 
addomain, and baseOU fields in store object
-modified startImageCB: added resetting of adauthenable, addomainid, and baseou 
and showing/hiding of imageauthbox based on OS type
-added toggleADauth

vcl.css:
-added:
#addomaindlgcontent label
#addomaindlgcontent .labeledform

dropdownmenus/css/theme.css:
-added:
#renameDialog tbody tr:hover td
#renameDialog tbody tr td
div.dijitDialog h2
div.dijitDialog h3
#confdelcontent h3
#groupbyresourcediv table.dojoxGridRowTable tbody tr:hover td
#groupbyresourcediv div.dojoxGridRowSelected table.dojoxGridRowTable tbody tr td
#imageadauthbox label
#imageadauthbox .labeledform

Added:
    vcl/trunk/web/.ht-inc/addomain.php
    vcl/trunk/web/js/resources/addomain.js
Modified:
    vcl/trunk/web/.ht-inc/image.php
    vcl/trunk/web/.ht-inc/resource.php
    vcl/trunk/web/.ht-inc/states.php
    vcl/trunk/web/.ht-inc/utils.php
    vcl/trunk/web/css/vcl.css
    vcl/trunk/web/js/resources/image.js
    vcl/trunk/web/themes/dropdownmenus/css/theme.css

Added: vcl/trunk/web/.ht-inc/addomain.php
URL: 
http://svn.apache.org/viewvc/vcl/trunk/web/.ht-inc/addomain.php?rev=1762935&view=auto
==============================================================================
--- vcl/trunk/web/.ht-inc/addomain.php (added)
+++ vcl/trunk/web/.ht-inc/addomain.php Fri Sep 30 16:56:45 2016
@@ -0,0 +1,653 @@
+<?php
+/*
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+*/
+
+////////////////////////////////////////////////////////////////////////////////
+///
+/// \class ADdomain
+///
+/// \brief extends Resource class to add things specific to resources of the
+/// addomain type
+///
+////////////////////////////////////////////////////////////////////////////////
+class ADdomain extends Resource {
+       
/////////////////////////////////////////////////////////////////////////////
+       ///
+       /// \fn __construct()
+       ///
+       /// \brief calls parent constructor; initializes things for Schedule 
class
+       ///
+       
/////////////////////////////////////////////////////////////////////////////
+       function __construct() {
+               parent::__construct();
+               $this->restype = 'addomain';
+               $this->restypename = 'AD Domain';
+               $this->namefield = 'name';
+               $this->basecdata['obj'] = $this;
+               $this->deletable = 1;
+               $this->deletetoggled = 0;
+               $this->defaultGetDataArgs = array('rscid' => 0);
+       }
+
+       
/////////////////////////////////////////////////////////////////////////////
+       ///
+       /// \fn getData($args)
+       ///
+       /// \param $args - array of arguments that determine what data gets 
returned;
+       /// must include:\n
+       /// \b rscid - only return data for resource with this id; pass 0 for 
all
+       /// (from addomain table)
+       ///
+       /// \return array of data as returned from getADdomains
+       ///
+       /// \brief wrapper for calling getADdomains
+       ///
+       
/////////////////////////////////////////////////////////////////////////////
+       function getData($args) {
+               return getADdomains($args['rscid']);
+       }
+
+       
/////////////////////////////////////////////////////////////////////////////
+       ///
+       /// \fn fieldWidth($field)
+       ///
+       /// \param $field - name of a resource field
+       ///
+       /// \return string for setting width of field (includes width= part)
+       ///
+       /// \brief generates the required width for the field; can return an 
empty
+       /// string if field should default to auto width
+       ///
+       
/////////////////////////////////////////////////////////////////////////////
+       function fieldWidth($field) {
+               switch($field) {
+                       case 'name':
+                               $w = 17;
+                               break;
+                       case 'owner':
+                               $w = 11;
+                               break;
+                       case 'domaindnsname':
+                               $w = 12;
+                               break;
+                       case 'domainnetbiosname':
+                               $w = 12;
+                               break;
+                       case 'username':
+                               $w = 9;
+                               break;
+                       case 'dnsservers':
+                               $w = 12;
+                               break;
+                       case 'domaincontrollers':
+                               $w = 17;
+                               break;
+                       case 'logindescription':
+                               $w = 12;
+                               break;
+                       default:
+                               return '';
+               }
+               if(preg_match('/MSIE/i', $_SERVER['HTTP_USER_AGENT']) ||
+                  preg_match('/Trident/i', $_SERVER['HTTP_USER_AGENT']) ||
+                  preg_match('/Edge/i', $_SERVER['HTTP_USER_AGENT']))
+                       $w = round($w * 11.5) . 'px';
+               else
+                       $w = "{$w}em";
+               return "width=\"$w\"";
+       }
+
+       
/////////////////////////////////////////////////////////////////////////////
+       ///
+       /// \fn fieldDisplayName($field)
+       ///
+       /// \param $field - name of a resource field
+       ///
+       /// \return display value for $field
+       ///
+       /// \brief generates the display value for $field
+       ///
+       
/////////////////////////////////////////////////////////////////////////////
+       function fieldDisplayName($field) {
+               switch($field) {
+                       case 'domaindnsname':
+                               return 'Domain DNS Name';
+                       case 'domainnetbiosname':
+                               return 'Domain NetBIOS Name';
+                       case 'dnsservers':
+                               return 'DNS Server(s)';
+                       case 'domaincontrollers':
+                               return 'Domain Controller(s)';
+                       case 'logindescription':
+                               return 'Login Description';
+               }
+               return ucfirst($field);
+       }
+
+       
/////////////////////////////////////////////////////////////////////////////
+       ///
+       /// \fn AJsaveResource()
+       ///
+       /// \brief saves changes to a resource; must be implemented by 
inheriting
+       /// class
+       ///
+       
/////////////////////////////////////////////////////////////////////////////
+       function AJsaveResource() {
+               global $user;
+               $add = getContinuationVar('add', 0);
+               $data = $this->validateResourceData();
+               if($data['error']) {
+                       $ret = array('status' => 'error', 'msg' => 
$data['errormsg']);
+                       sendJSON($ret);
+                       return;
+               }
+
+               if($add) {
+                       $esc_name = mysql_real_escape_string($data['name']);
+                       $query = "SELECT id FROM addomain WHERE name = 
'$esc_name'";
+                       $qh = doQuery($query);
+                       if($row = mysql_fetch_assoc($qh)) {
+                               sendJSON(array('status' => 'adderror',
+                                              'errormsg' => wordwrap(i('An AD 
Domain with this name already exists.'), 75, '<br>')));
+                               return;
+                       }
+                       if(! $data['rscid'] = $this->addResource($data)) {
+                               sendJSON(array('status' => 'adderror',
+                                              'errormsg' => wordwrap(i('Error 
encountered while trying to create new AD domain. Please contact an admin for 
assistance.'), 75, '<br>')));
+                               return;
+                       }
+               }
+               else {
+                       $olddata = getContinuationVar('olddata');
+                       $updates = array();
+                       # name
+                       if($data['name'] != $olddata['name'])
+                               $updates[] = "name = '{$data['name']}'";
+                       # ownerid
+                       $ownerid = getUserlistID($data['owner']);
+                       if($ownerid != $olddata['ownerid'])
+                               $updates[] = "ownerid = $ownerid";
+                       # domaindnsname
+                       if($data['domaindnsname'] != $olddata['domaindnsname'])
+                               $updates[] = "domainDNSName = 
'{$data['domaindnsname']}'";
+                       # domainnetbiosname
+                       if($data['domainnetbiosname'] != 
$olddata['domainnetbiosname'])
+                               $updates[] = "domainNetBIOSName = 
'{$data['domainnetbiosname']}'";
+                       # username
+                       if($data['username'] != $olddata['username'])
+                               $updates[] = "username = '{$data['username']}'";
+                       # password
+                       if(strlen($data['password'])) {
+                               $esc_pass = 
mysql_real_escape_string($data['password']);
+                               $updates[] = "password = '$esc_pass'";
+                       }
+                       # dnsservers
+                       if($data['dnsservers'] != $olddata['dnsservers'])
+                               $updates[] = "dnsServers = 
'{$data['dnsservers']}'";
+                       # domaincontrollers
+                       if($data['domaincontrollers'] != 
$olddata['domaincontrollers'])
+                               $updates[] = "domainControllers = 
'{$data['domaincontrollers']}'";
+                       # logindescription
+                       if($data['logindescription'] != 
$olddata['logindescription']) {
+                               $esc_desc = 
mysql_real_escape_string($data['logindescription']);
+                               $updates[] = "logindescription = '$esc_desc'";
+                       }
+                       if(count($updates)) {
+                               $query = "UPDATE addomain SET "
+                                      . implode(', ', $updates)
+                                      . " WHERE id = {$data['rscid']}";
+                               doQuery($query);
+                       }
+               }
+
+               # clear user resource cache for this type
+               $key = getKey(array(array($this->restype . "Admin"), 
array("administer"), 0, 1, 0, 0));
+               unset($_SESSION['userresources'][$key]);
+               $key = getKey(array(array($this->restype . "Admin"), 
array("administer"), 0, 0, 0, 0));
+               unset($_SESSION['userresources'][$key]);
+               $key = getKey(array(array($this->restype . "Admin"), 
array("manageGroup"), 0, 1, 0, 0));
+               unset($_SESSION['userresources'][$key]);
+               $key = getKey(array(array($this->restype . "Admin"), 
array("manageGroup"), 0, 0, 0, 0));
+               unset($_SESSION['userresources'][$key]);
+
+               $tmp = $this->getData(array('rscid' => $data['rscid']));
+               $data = $tmp[$data['rscid']];
+               $arr = array('status' => 'success');
+               $arr['data'] = $data;
+               if($add) {
+                       $arr['action'] = 'add';
+                       $arr['nogroups'] = 0;
+                       $groups = getUserResources(array($this->restype . 
'Admin'), array('manageGroup'), 1);
+                       if(count($groups[$this->restype]))
+                               $arr['groupingHTML'] = 
$this->groupByResourceHTML();
+                       else
+                               $arr['nogroups'] = 1;
+               }
+               else
+                       $arr['action'] = 'edit';
+               sendJSON($arr);
+       }
+
+       
/////////////////////////////////////////////////////////////////////////////
+       ///
+       /// \fn AJeditResource()
+       ///
+       /// \brief sends data for editing a resource
+       ///
+       
/////////////////////////////////////////////////////////////////////////////
+       function AJeditResource() {
+               $rscid = processInputVar('rscid', ARG_NUMERIC);
+               $resources = getUserResources(array($this->restype . 'Admin'), 
array('administer'), 0, 1);
+               if(! array_key_exists($rscid, $resources[$this->restype])) {
+                       $ret = array('status' => 'noaccess');
+                       sendJSON($ret);
+                       return;
+               }
+               $args = $this->defaultGetDataArgs;
+               $args['rscid'] = $rscid;
+               $tmp = $this->getData($args);
+               $data = $tmp[$rscid];
+               $login = preg_replace("/<br>/", "\n", 
$data['logindescription']);
+               $data['logindescription'] = htmlspecialchars_decode($login);
+               $cdata = $this->basecdata;
+               $cdata['rscid'] = $rscid;
+               $cdata['olddata'] = $data;
+
+               # save continuation
+               $cont = addContinuationsEntry('AJsaveResource', $cdata);
+
+               $ret = $this->jsondata;
+               $ret['title'] = "Edit {$this->restypename}";
+               $ret['cont'] = $cont;
+               $ret['resid'] = $rscid;
+               $ret['data'] = $data;
+               $ret['status'] = 'success';
+               sendJSON($ret);
+       }
+
+       
/////////////////////////////////////////////////////////////////////////////
+       ///
+       /// \fn addResource($data)
+       ///
+       /// \param $data - array of needed data for adding a new resource
+       ///
+       /// \return id of new resource
+       ///
+       /// \brief handles all parts of adding a new resource to the database; 
should
+       /// be implemented by inheriting class, but not required since it is 
only
+       /// called by functions in the inheriting class (nothing in this base 
class
+       /// calls it directly)
+       ///
+       
/////////////////////////////////////////////////////////////////////////////
+       function addResource($data) {
+               global $user;
+
+               $ownerid = getUserlistID($data['owner']);
+               $esc_pass = mysql_real_escape_string($data['password']);
+               $esc_desc = mysql_real_escape_string($data['logindescription']);
+       
+               $query = "INSERT INTO addomain"
+                               .       "(name,"
+                               .       "ownerid,"
+                               .       "domainDNSName,"
+                               .       "domainNetBIOSName,"
+                               .       "username,"
+                               .       "password,"
+                               .       "dnsServers,"
+                               .       "domainControllers,"
+                               .       "logindescription)"
+                               .       "VALUES ('{$data['name']}',"
+                               .       "$ownerid,"
+                               .       "'{$data['domaindnsname']}',"
+                               .       "'{$data['domainnetbiosname']}',"
+                               .       "'{$data['username']}',"
+                               .       "'$esc_pass',"
+                               .       "'{$data['dnsservers']}',"
+                               .       "'{$data['domaincontrollers']}',"
+                               .       "'$esc_desc')";
+               doQuery($query);
+
+               $rscid = dbLastInsertID();
+               if($rscid == 0) {
+                       return 0;
+               }
+               // add entry in resource table
+               $query = "INSERT INTO resource "
+                                .        "(resourcetypeid, "
+                                .        "subid) "
+                                . "VALUES (19, "
+                                .        "$rscid)";
+               doQuery($query);
+               return $rscid;
+       }
+
+       
/////////////////////////////////////////////////////////////////////////////
+       ///
+       /// \fn addEditDialogHTML($add)
+       ///
+       /// \param $add - unused for this class
+       ///
+       /// \brief handles generating HTML for dialog used to edit resource
+       ///
+       
/////////////////////////////////////////////////////////////////////////////
+       function addEditDialogHTML($add=0) {
+               global $user, $days;
+               # dialog for on page editing
+               $h = '';
+               $h .= "<div dojoType=dijit.Dialog\n";
+               $h .= "      id=\"addeditdlg\"\n";
+               $h .= "      title=\"Edit {$this->restypename}\"\n";
+               $h .= "      duration=250\n";
+               #$h .= "      style=\"width: 70%;\"\n";
+               $h .= "      draggable=true>\n";
+               $h .= "<div id=\"addeditdlgcontent\">\n";
+               $h .= "<div id=\"addomaindlgcontent\">\n";
+               # id
+               $h .= "<input type=\"hidden\" id=\"editresid\">\n";
+
+               # todo consider adding help icons with popups
+
+               $h .= "<div style=\"text-align: center;\">\n";
+               # name
+               $errmsg = i("Name cannot contain single (') or double (&quot;) 
quotes, less than (&lt;), or greater than (&gt;) and can be from 2 to 30 
characters long");
+               $h .= labeledFormItem('name', i('Name'), 'text', 
'^([A-Za-z0-9-!@#$%^&\*\(\)_=\+\[\]{}\\\|:;,\./\?~` ]){2,30}$',
+                                     1, '', $errmsg, '', '', '200px'); 
+               # owner
+               $extra = array('onKeyPress' => 'setOwnerChecking');
+               $h .= labeledFormItem('owner', i('Owner'), 'text', '', 1,
+                                     
"{$user['unityid']}@{$user['affiliation']}", i('Unknown user'),
+                                     'checkOwner', $extra, '200px');
+               $cont = addContinuationsEntry('AJvalidateUserid');
+               $h .= "<input type=\"hidden\" id=\"valuseridcont\" 
value=\"$cont\">\n";
+               # domain dns name
+               $hostbase = 
'([A-Za-z0-9]{1,63})(\.[A-Za-z0-9-_]+)*(\.?[A-Za-z0-9])';
+               $errmsg = i("Domain DNS Name should be in the format domain.tld 
and can only contain letters, numbers, dashes(-), periods(.), and 
underscores(_) (e.g. myuniversity.edu)");
+               $h .= labeledFormItem('domaindnsname', i('Domain DNS Name'), 
'text', "^$hostbase$",
+                                     1, '', $errmsg, '', '', '200px'); 
+               # domain netbios name
+               $errmsg = i("Domain NetBIOS Name can only contain letters, 
numbers, dashes(-), periods(.), and underscores(_) and can be up to 15 
characters long");
+               $h .= labeledFormItem('domainnetbiosname', i('Domain NetBIOS 
Name'), 'text', '^[a-zA-Z0-9_][-a-zA-Z0-9_\.]{0,14}$',
+                                     1, '', $errmsg, '', '', '200px'); 
+               $h .= "<br>\n";
+               # username
+               $errmsg = i("Username cannot contain single (') or double 
(&quot;) quotes, less than (&lt;), or greater than (&gt;) and can be from 2 to 
64 characters long");
+               $h .= labeledFormItem('username', i('Username'), 'text', 
'^([A-Za-z0-9-!@#$%^&\*\(\)_=\+\[\]{}\\\|:;,\./\?~` ]){2,30}$',
+                                     1, '', $errmsg, '', '', '200px'); 
+               # password
+               # todo make required for adding
+               $errmsg = i("Password must be at least 4 characters long");
+               $h .= labeledFormItem('password', i('Password'), 'password', 
'^.{4,256}$', 0, '', $errmsg, '', '', '200px'); 
+               # confirm password
+               $h .= labeledFormItem('password2', i('Confirm Password'), 
'password', '', 0, '', '', '', '', '200px'); 
+               $h .= "<br>\n";
+               # dns server list
+               $ipreg = 
'(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)';
+               $reg = "^($ipreg,)*($ipreg)$";
+               $errmsg = i("Invalid IP address specified - must be a valid 
IPV4 address");
+               $h .= labeledFormItem('dnsservers', i('DNS Server(s)'), 'text', 
$reg, 0, '', $errmsg,
+                                     '', '', '300px'); 
+               # domain controllers list
+               $reg = "$hostbase(,$hostbase){0,4}";
+               $errmsg = i("Invalid Domain Controller specified. Must be comma 
delimited list of hostnames or IP addresses, with up to 5 allowed");
+               $h .= labeledFormItem('domaincontrollers', i('Domain 
Controller(s)'), 'text', $reg, 0, '', $errmsg,
+                                     '', '', '300px'); 
+               # login description
+               $h .= labeledFormItem('logindescription', i('Login 
Description'), 'textarea', '',
+                                     1, '', '', '', '', '300px'); 
+
+               $h .= "</div>\n"; # center
+               $h .= "</div>\n"; # addomaindlgcontent
+               $h .= "</div>\n"; # addeditdlgcontent
+
+               $h .= "<div id=\"addeditdlgerrmsg\" 
class=\"nperrormsg\"></div>\n";
+               $h .= "<div id=\"editdlgbtns\" align=\"center\">\n";
+               $h .= dijitButton('addeditbtn', "Confirm", "saveResource();");
+               $h .= dijitButton('', "Cancel", 
"dijit.byId('addeditdlg').hide();");
+               $h .= "</div>\n"; # editdlgbtns
+               $h .= "</div>\n"; # addeditdlg
+
+               $h .= "<div dojoType=dijit.Dialog\n";
+               $h .= "      id=\"groupingnote\"\n";
+               $h .= "      title=\"AD Domain Grouping\"\n";
+               $h .= "      duration=250\n";
+               $h .= "      draggable=true>\n";
+               $msg = i("Each AD Domain should be a member of an AD Domain 
resource group. The following dialog will allow you to add the new AD Domain to 
a group.");
+               $h .= wordwrap($msg, 75, '<br>');
+               $h .= "<br><br>\n";
+               $h .= "<div align=\"center\">\n";
+               $h .= dijitButton('', "Close", 
"dijit.byId('groupingnote').hide();");
+               $h .= "</div>\n"; # btn div
+               $h .= "</div>\n"; # groupingnote
+
+               $h .= "<div dojoType=dijit.Dialog\n";
+               $h .= "      id=\"groupdlg\"\n";
+               $h .= "      title=\"AD Domain Grouping\"\n";
+               $h .= "      duration=250\n";
+               $h .= "      draggable=true>\n";
+               $h .= "<div id=\"groupdlgcontent\"></div>\n";
+               $h .= "<div align=\"center\">\n";
+               $script  = "    dijit.byId('groupdlg').hide();\n";
+               $script .= "    checkFirstAdd();\n";
+               $h .= dijitButton('', "Close", $script);
+               $h .= "</div>\n"; # btn div
+               $h .= "</div>\n"; # groupdlg
+
+               return $h;
+       }
+
+       
/////////////////////////////////////////////////////////////////////////////
+       ///
+       /// \fn validateResourceData()
+       ///
+       /// \return array with these fields:\n
+       /// \b rscid - id of resource (from addomain table)\n
+       /// \b name\n
+       /// \b owner\n
+       /// \b times - array of arrays, each having 2 keys: start and end, each 
in
+       ///    unix timestamp format\n
+       /// \b error - 0 if submitted data validates; 1 if anything is invalid\n
+       /// \b errormsg - if error = 1; string of error messages separated by 
html
+       ///    break tags
+       ///
+       /// \brief validates form input from editing or adding an AD domain
+       ///
+       
/////////////////////////////////////////////////////////////////////////////
+       function validateResourceData() {
+               global $user;
+
+               $return = array('error' => 0);
+               $errormsg = array();
+
+               $return['rscid'] = getContinuationVar('rscid', 0);
+               $return["name"] = processInputVar("name", ARG_STRING);
+               $return["owner"] = processInputVar("owner", ARG_STRING, 
"{$user["unityid"]}@{$user['affiliation']}");
+               $return["domaindnsname"] = processInputVar("domaindnsname", 
ARG_STRING);
+               $return["domainnetbiosname"] = 
processInputVar("domainnetbiosname", ARG_STRING);
+               $return["username"] = processInputVar("username", ARG_STRING);
+               $return["password"] = processInputVar("password", ARG_STRING);
+               $return["password2"] = processInputVar("password2", ARG_STRING);
+               $return["dnsservers"] = processInputVar("dnsservers", 
ARG_STRING);
+               $return["domaincontrollers"] = 
processInputVar("domaincontrollers", ARG_STRING);
+               $return["logindescription"] = 
processInputVar("logindescription", ARG_STRING);
+
+               $return['logindescription'] = preg_replace("/[\n\s]*$/", '', 
$return['logindescription']);
+               $return['logindescription'] = preg_replace("/\r/", '', 
$return['logindescription']);
+               $return['logindescription'] = 
htmlspecialchars($return['logindescription']);
+               $return['logindescription'] = preg_replace("/\n/", '<br>', 
$return['logindescription']);
+
+               if(! 
preg_match("/^([A-Za-z0-9-!@#$%^&\*\(\)_=\+\[\]{}\\\|:;,\.\/\?~` ]){2,30}$/", 
$return['name'])) {
+                       $return['error'] = 1;
+                       $errormsg[] = i("Name cannot contain single (') or 
double (&quot;) quotes, less than (&lt;), or greater than (&gt;) and can be 
from 2 to 30 characters long");
+               }
+               elseif($this->checkExistingField('name', $return['name'], 
$return['rscid'])) {
+                       $return['error'] = 1;
+                       $errormsg[] = i("An AD domain already exists with this 
name.");
+               }
+               if(! validateUserid($return['owner'])) {
+                       $return['error'] = 1;
+                       $errormsg[] = i("Submitted owner is not valid");
+               }
+
+               if(! 
preg_match('/^([A-Za-z0-9]{1,63})(\.[A-Za-z0-9-_]+)*(\.?[A-Za-z0-9])$/', 
$return['domaindnsname'])) {
+                       $return['error'] = 1;
+                       $errormsg[] = i("Domain DNS Name should be in the 
format domain.tld and can only contain letters, numbers, dashes(-), periods(.), 
and underscores(_) (e.g. myuniversity.edu)");
+               }
+               if(! preg_match('/^[a-zA-Z0-9_][-a-zA-Z0-9_\.]{0,14}$/', 
$return['domainnetbiosname'])) {
+                       $return['error'] = 1;
+                       $errormsg[] = i("Domain NetBIOS Name can only contain 
letters, numbers, dashes(-), periods(.), and underscores(_) and can be up to 15 
characters long");
+               }
+
+               if(! 
preg_match('/^([A-Za-z0-9-!@#$%^&\*\(\)_=\+\[\]{}\\\|:;,\.\/\?~` ]){2,30}$/', 
$return['username'])) {
+                       $return['error'] = 1;
+                       $errormsg[] = i("Username cannot contain single (') or 
double (&quot;) quotes, less than (&lt;), or greater than (&gt;) and can be 
from 2 to 64 characters long");
+               }
+
+               if((! empty($return['password']) ||
+                  ! empty($return['password2'])) &&
+                  ! preg_match('/^.{4,256}$/', $return['password'])) {
+                       $return['error'] = 1;
+                       $errormsg[] = i("Password must be at least 4 characters 
long");
+               }
+               elseif($return['password'] != $return['password2']) {
+                       $return['error'] = 1;
+                       $errormsg[] = i("Passwords do not match");
+               }
+
+               $ips = explode(',', $return['dnsservers']);
+               foreach($ips as $ip) {
+                       if(! validateIPv4addr($ip)) {
+                               $return['error'] = 1;
+                               $errormsg[] = i("Invalid IP address specified 
for DNS Server - must be a valid IPV4 address");
+                               break;
+                       }
+               }
+
+               $dcs = explode(',', $return['domaincontrollers']);
+               if(count($dcs) > 5) {
+                       $return['error'] = 1;
+                       $errormsg[] = i("Too many Domain Controllers specified, 
up to 5 are allowed");
+               }
+               else {
+                       foreach($dcs as $dc) {
+                               if(! validateHostname($dc) && ! 
validateIPv4addr($dc)) {
+                                       $return['error'] = 1;
+                                       $errormsg[] = i("Invalid Domain 
Controller specified. Must be comman delimited list of hostnames or IP 
addresses, with up to 5 allowed");
+                               }
+                       }
+               }
+
+               /*if(! preg_match('/^$/', $return['logindescription'])) {
+                       $return['error'] = 1;
+                       $errormsg[] = i("");
+               }*/
+
+               if($return['error'])
+                       $return['errormsg'] = implode('<br>', $errormsg);
+
+               return $return;
+       }
+
+       
/////////////////////////////////////////////////////////////////////////////
+       ///
+       /// \fn checkResourceInUse($rscid)
+       ///
+       /// \param $rscid - id of AD domain
+       ///
+       /// \return empty string if not being used; string of where resource is
+       /// being used if being used
+       ///
+       /// \brief checks to see if AD domain is being used
+       ///
+       
/////////////////////////////////////////////////////////////////////////////
+       function checkResourceInUse($rscid) {
+               $msg = '';
+
+               $query = "SELECT i.prettyname "
+                      . "FROM imageaddomain ia, "
+                      .      "image i "
+                      . "WHERE ia.addomainid = $rscid AND "
+                      .       "ia.imageid = i.id";
+               $qh = doQuery($query);
+               $images = array();
+               while($row = mysql_fetch_assoc($qh))
+                       $images[] = $row['prettyname'];
+               if(count($images))
+                       $msg = "This AD Domain cannot be deleted because the 
following <strong>images</strong> are using it:<br><br>\n" . implode("<br>\n", 
$images);
+
+               return $msg;
+       }
+
+       
/////////////////////////////////////////////////////////////////////////////
+       ///
+       /// \fn checkResourceInUse($rscid)
+       ///
+       /// \param $rscid - id of resource
+       ///
+       /// \return empty string if not being used; string of where resource is
+       /// being used if being used
+       ///
+       /// \brief checks to see if resource is being used
+       ///
+       
/////////////////////////////////////////////////////////////////////////////
+       function checkResourceInUse($rscid) {
+               $msgs = array();
+
+               /*
+               # check reservations
+               $query = "SELECT rq.end "
+                      . "FROM request rq, "
+                      .      "reservation rs "
+                      . "WHERE rs.requestid = rq.id AND "
+                      .       "rs.imageid = $rscid AND "
+                      .       "rq.stateid NOT IN (1, 12) AND "
+                      .       "rq.end > NOW() "
+                      . "ORDER BY rq.end DESC "
+                      . "LIMIT 1";
+               $qh = doQuery($query);
+               if($row = mysql_fetch_assoc($qh))
+                       $msgs[] = sprintf(i("There is at least one 
<strong>reservation</strong> for this image. The latest end time is %s."), 
prettyDatetime($row['end'], 1));;
+
+               # check blockComputers
+               $query = "SELECT br.name, "
+                      .        "bt.end " 
+                      . "FROM blockRequest br, " 
+                      .      "blockTimes bt, "
+                      .      "blockComputers bc "
+                      . "WHERE bc.imageid = $rscid AND "
+                      .       "bc.blockTimeid = bt.id AND "
+                      .       "bt.blockRequestid = br.id AND "
+                      .       "bt.end > NOW() AND "
+                      .       "bt.skip = 0 AND "
+                      .       "br.status = 'accepted' "
+                      . "ORDER BY bt.end DESC "
+                      . "LIMIT 1";
+               $qh = doQuery($query);
+               if($row = mysql_fetch_assoc($qh))
+                       $msgs[] = sprintf(i("There is at least one 
<strong>Block Allocation</strong> with computers currently allocated with this 
image. Block Allocation %s has the latest end time which is %s."), 
$row['name'], prettyDatetime($row['end'], 1));
+
+               if(empty($msgs))
+                       return '';
+
+               $msg = i("The selected AD Domain is currently being used in the 
following ways and cannot be deleted at this time.") . "<br><br>\n";
+               $msg .= implode("<br><br>\n", $msgs) . "<br><br>\n";
+               return $msg;
+               */
+               return '';
+       }
+}
+
+?>

Modified: vcl/trunk/web/.ht-inc/image.php
URL: 
http://svn.apache.org/viewvc/vcl/trunk/web/.ht-inc/image.php?rev=1762935&r1=1762934&r2=1762935&view=diff
==============================================================================
--- vcl/trunk/web/.ht-inc/image.php (original)
+++ vcl/trunk/web/.ht-inc/image.php Fri Sep 30 16:56:45 2016
@@ -87,13 +87,23 @@ class Image extends Resource {
                                $w = 12;
                                break;
                        case 'os':
-                               $w = 7;
+                               $w = 8;
+                               break;
+                       case 'addomain':
+                               $w = 10;
+                               break;
+                       case 'baseOU':
+                               $w = 12;
+                               break;
+                       case 'adauthenabled':
+                               $w = 9;
                                break;
                        default:
                                return '';
                }
                if(preg_match('/MSIE/i', $_SERVER['HTTP_USER_AGENT']) ||
-                  preg_match('/Trident/i', $_SERVER['HTTP_USER_AGENT']))
+                  preg_match('/Trident/i', $_SERVER['HTTP_USER_AGENT']) ||
+                  preg_match('/Edge/i', $_SERVER['HTTP_USER_AGENT']))
                        $w = round($w * 11.5) . 'px';
                else
                        $w = "{$w}em";
@@ -143,6 +153,12 @@ class Image extends Resource {
                                return i("Admin. Access");
                        case 'sethostname':
                                return i("Set Hostname");
+                       case 'adauthenabled':
+                               return i("Use AD Authentication");
+                       case 'addomain':
+                               return i("AD Domain");
+                       case 'baseOU':
+                               return i("Base OU");
                }
                return i(ucfirst($field));
        }
@@ -434,6 +450,25 @@ class Image extends Resource {
                        $h .= "id=\"connectmethodids\">\n";
                }
                $h .= "</div>\n"; #labeledform
+
+               # AD authentication
+               $h .= "<div class=\"boxedoptions hidden\" 
id=\"imageadauthbox\">\n";
+               # enable toggle
+               $vals = getUserResources(array('addomainAdmin'), 
array("manageGroup"));
+               $extra = array();
+               if(count($vals['addomain']) == 0)
+                       $extra['disabled'] = 'true';
+               $extra['onChange'] = 'toggleADauth();';
+               $h .= labeledFormItem('adauthenable', i('Use AD 
Authentication'), 'check', '', '', '', '', '', $extra);
+               # AD domain
+               $disabled = array('disabled' => 'true');
+               $h .= labeledFormItem('addomainid', i('AD Domain'), 'select', 
$vals['addomain'], '', '', '', '', $disabled);
+               # base OU
+               $reg = '^([Oo][Uu])=[^,]+(,([Oo][Uu])=[^,]+)*$';
+               $errmsg = i("Invalid base OU; do not include DC components");
+               $h .= labeledFormItem('baseou', i('Base OU'), 'text', $reg, 0, 
'', $errmsg, '', $disabled, '230px', helpIcon('baseouhelp')); 
+               $h .= "</div>\n"; # boxedoptions
+
                # subimages
                if(! $add) {
                        $h .= "<br>\n";
@@ -488,6 +523,8 @@ class Image extends Resource {
                $h .= dijitButton('', i("Cancel"), $script);
                $h .= "   </div>\n";
                $h .= "</div>\n"; # autoconfirmdlg
+
+               $h .= helpTooltip('baseouhelp', i('OU where nodes deployed with 
this image will be registered. Do not enter the domain component (ex 
OU=Computers,OU=VCL)'));
                return $h;
        }
 
@@ -758,6 +795,41 @@ class Image extends Resource {
                               . " WHERE id = {$data['imageid']}";
                        doQuery($query);
                }
+
+               # ad authentication
+               if($olddata['ostype'] == 'windows') {
+                       if($data['adauthenabled'] != $olddata['adauthenabled']) 
{
+                               if($data['adauthenabled']) {
+                                       $esc_baseou = 
mysql_real_escape_string($data['baseou']);
+                                       $query = "INSERT INTO imageaddomain "
+                                              .        "(imageid, "
+                                              .        "addomainid, "
+                                              .        "baseOU) "
+                                              . "VALUES "
+                                              .        "({$data['imageid']}, "
+                                              .        "{$data['addomainid']}, 
"
+                                              .        "'$esc_baseou')";
+                                       doQuery($query);
+                               }
+                               else {
+                                       $query = "DELETE FROM imageaddomain "
+                                              . "WHERE imageid = 
{$data['imageid']}";
+                                       doQuery($query);
+                               }
+                       }
+                       elseif($data['adauthenabled'] &&
+                              ($data['addomainid'] != $olddata['addomainid'] ||
+                              $data['baseou'] != $olddata['baseOU'])) {
+                               $esc_baseou = 
mysql_real_escape_string($data['baseou']);
+                               $query = "UPDATE imageaddomain "
+                                      . "SET addomainid = 
{$data['addomainid']}, "
+                                      .     "baseOU = '$esc_baseou' "
+                                      . "WHERE imageid = {$data['imageid']}";
+                               doQuery($query);
+                       }
+               }
+
+               # imagemeta
                if(empty($olddata['imagemetaid']) &&
                   ($data['checkuser'] == 0 || $data['rootaccess'] == 0 ||
                   ($olddata['ostype'] == 'windows' && $data['sethostname'] == 
1) ||
@@ -1148,6 +1220,20 @@ class Image extends Resource {
                       .         "{$data['basedoffrevisionid']})";
                doQuery($query, 205);
                $imageid = dbLastInsertID();
+
+               # ad authentication
+               if($data['adauthenabled']) {
+                       $esc_baseou = mysql_real_escape_string($data['baseou']);
+                       $query = "INSERT INTO imageaddomain "
+                              .        "(imageid, "
+                              .        "addomainid, "
+                              .        "baseOU) "
+                              . "VALUES "
+                              .        "($imageid, "
+                              .        "{$data['addomainid']}, "
+                              .        "'$esc_baseou')";
+                       doQuery($query);
+               }
        
                // possibly add entry to imagemeta table
                $imagemetaid = 0;
@@ -1530,6 +1616,9 @@ class Image extends Resource {
                $return["sethostname"] = processInputVar("sethostname", 
ARG_NUMERIC);
                $return["sysprep"] = processInputVar("sysprep", ARG_NUMERIC); # 
only in add
                $return["connectmethodids"] = 
processInputVar("connectmethodids", ARG_STRING); # only in add
+               $return["adauthenabled"] = processInputVar("adauthenabled", 
ARG_NUMERIC);
+               $return["addomainid"] = processInputVar("addomainid", 
ARG_NUMERIC);
+               $return["baseou"] = processInputVar("baseou", ARG_STRING);
 
                $return['requestid'] = getContinuationVar('requestid'); # only 
in add
                $return["imageid"] = getContinuationVar('imageid');
@@ -1636,6 +1725,27 @@ class Image extends Resource {
                        $return['error'] = 1;
                        $errormsg[] = i("Use Sysprep must be Yes or No");
                }
+               if($return['adauthenabled'] != 0 && $return['adauthenabled'] != 
1)
+                       $return['adauthenabled'] = 0;
+               if($return['adauthenabled'] == 1) {
+                       $vals = getUserResources(array('addomainAdmin'), 
array("manageGroup"));
+                       if(! array_key_exists($return['addomainid'], 
$vals['addomain'])) {
+                               $return['error'] = 1;
+                               $errormsg[] = i("Invalid AD Domain submitted");
+                       }
+                       if(! 
preg_match('/^([Oo][Uu])=[^,]+(,([Oo][Uu])=[^,]+)*$/', $return['baseou'])) {
+                               $return['error'] = 1;
+                               $errormsg[] = i("Invalid Base OU submitted, 
must start with OU=");
+                       }
+                       if(preg_match('/DC=.+(,DC=.+)*$/', $return['baseou'])) {
+                               $return['error'] = 1;
+                               $errormsg[] = i("Base OU must not contain DC= 
components");
+                       }
+               }
+               else {
+                       $return['addomainid'] = 0;
+                       $return['baseou'] = NULL;
+               }
                if(empty($return['desc'])) {
                        $return['error'] = 1;
                        $errormsg[] = i("You must include a description of the 
image") . "<br>";
@@ -1659,6 +1769,7 @@ class Image extends Resource {
                                $return['connectmethodids'] = implode(',', 
array_keys($ids));
                        }
                }
+
                if($return['error'])
                        $return['errormsg'] = implode('<br>', $errormsg);
                return $return;

Modified: vcl/trunk/web/.ht-inc/resource.php
URL: 
http://svn.apache.org/viewvc/vcl/trunk/web/.ht-inc/resource.php?rev=1762935&r1=1762934&r2=1762935&view=diff
==============================================================================
--- vcl/trunk/web/.ht-inc/resource.php (original)
+++ vcl/trunk/web/.ht-inc/resource.php Fri Sep 30 16:56:45 2016
@@ -43,6 +43,9 @@ function resource($type) {
                case 'schedule':
                        $obj = new Schedule();
                        break;
+               case 'addomain':
+                       $obj = new ADdomain();
+                       break;
        }
 
        $html = $obj->selectionText();
@@ -69,7 +72,7 @@ class Resource {
        var $deletetoggled;
        var $errmsg;
        var $namefield;
-       var $noadd;
+       var $addable;
        var $jsondata;
 
        
/////////////////////////////////////////////////////////////////////////////
@@ -288,7 +291,7 @@ class Resource {
                if($this->deletetoggled) {
                        $h .= "<label for=\"showdeleted\"><strong>";
                        $h .= i("Include Deleted {$this->restypename}s:");
-                       $h .= "</strong>:</label>\n";
+                       $h .= "</strong></label>\n";
                        $h .= "<input type=\"checkbox\" 
dojoType=\"dijit.form.CheckBox\" ";
                        $h .= "id=\"showdeleted\" 
onChange=\"resource.GridFilter();\">\n";
                }
@@ -306,7 +309,8 @@ class Resource {
                $h .= "<thead>\n";
                $h .= "<tr>\n";
                if(preg_match('/MSIE/i', $_SERVER['HTTP_USER_AGENT']) ||
-                  preg_match('/Trident/i', $_SERVER['HTTP_USER_AGENT']))
+                  preg_match('/Trident/i', $_SERVER['HTTP_USER_AGENT']) ||
+                  preg_match('/Edge/i', $_SERVER['HTTP_USER_AGENT']))
                        $w = array('64px', '38px', '200px');
                else
                        $w = array('5em', '3.5em', '17em');
@@ -442,7 +446,8 @@ class Resource {
                                return '';
                }
                if(preg_match('/MSIE/i', $_SERVER['HTTP_USER_AGENT']) ||
-                  preg_match('/Trident/i', $_SERVER['HTTP_USER_AGENT']))
+                  preg_match('/Trident/i', $_SERVER['HTTP_USER_AGENT']) ||
+                  preg_match('/Edge/i', $_SERVER['HTTP_USER_AGENT']))
                        $w = round($w * 11.5) . 'px';
                else
                        $w = "{$w}em";
@@ -1602,6 +1607,34 @@ class Resource {
 
        
/////////////////////////////////////////////////////////////////////////////
        ///
+       /// \fn checkExistingField($field, $value, $id=0)
+       ///
+       /// \param $field - database field name
+       /// \param $value - value for $field
+       /// \param $id - (optional, default=0) if nonzero, ignore resource with 
this
+       /// id
+       ///
+       /// \return 1 if existing resource with $field set to $value, 0 if not
+       ///
+       /// \brief checks to see if there is already a record in the database 
with
+       /// $field set to $value
+       ///
+       
/////////////////////////////////////////////////////////////////////////////
+       function checkExistingField($field, $value, $id=0) {
+               $query = "SELECT id FROM {$this->restype} "
+                      . "WHERE `$field` = '$value'";
+               if($this->deletetoggled)
+                       $query .= " AND deleted = 0";
+               if($id)
+                       $query .= " AND id != $id";
+               $qh = doQuery($query);
+               if(mysql_num_rows($qh))
+                       return 1;
+               return 0;
+       }
+
+       
/////////////////////////////////////////////////////////////////////////////
+       ///
        /// \fn extraSelectAdminOptions()
        ///
        /// \return html
@@ -1617,6 +1650,8 @@ class Resource {
        ///
        /// \fn checkResourceInUse($rscid)
        ///
+       /// \param $rscid - id of resource
+       ///
        /// \return empty string if not being used; string of where resource is
        /// being used if being used
        ///

Modified: vcl/trunk/web/.ht-inc/states.php
URL: 
http://svn.apache.org/viewvc/vcl/trunk/web/.ht-inc/states.php?rev=1762935&r1=1762934&r2=1762935&view=diff
==============================================================================
--- vcl/trunk/web/.ht-inc/states.php (original)
+++ vcl/trunk/web/.ht-inc/states.php Fri Sep 30 16:56:45 2016
@@ -56,6 +56,7 @@ $actions["entry"] = array('main',
                           'computer',
                           'managementnode',
                           'schedule',
+                          'addomain',
                           'RESTresourceBasic',
                           'RESTresourceDetail',
                           #'testDojoREST',
@@ -596,6 +597,8 @@ $actions['mode']['managementnode'] = "re
 $actions['args']['managementnode'] = 'managementnode';
 $actions['mode']['schedule'] = "resource";
 $actions['args']['schedule'] = 'schedule';
+$actions['mode']['addomain'] = "resource";
+$actions['args']['addomain'] = 'addomain';
 $actions['mode']['viewResources'] = "viewResources";
 $actions['mode']['jsonResourceStore'] = "jsonResourceStore";
 $actions['mode']['AJpromptToggleDeleteResource'] = 
"AJpromptToggleDeleteResource";
@@ -656,6 +659,7 @@ $actions['pages']['image'] = "image";
 $actions['pages']['computer'] = "computer";
 $actions['pages']['managementnode'] = "managementnode";
 $actions['pages']['schedule'] = "schedule";
+$actions['pages']['addomain'] = "addomain";
 $actions['pages']['viewResources'] = "resource";
 $actions['pages']['jsonResourceStore'] = "resource";
 $actions['pages']['AJpromptToggleDeleteResource'] = "resource";

Modified: vcl/trunk/web/.ht-inc/utils.php
URL: 
http://svn.apache.org/viewvc/vcl/trunk/web/.ht-inc/utils.php?rev=1762935&r1=1762934&r2=1762935&view=diff
==============================================================================
--- vcl/trunk/web/.ht-inc/utils.php (original)
+++ vcl/trunk/web/.ht-inc/utils.php Fri Sep 30 16:56:45 2016
@@ -300,6 +300,7 @@ function initGlobals() {
                case 'computer':
                case 'managementnode':
                case 'schedule':
+               case 'addomain':
                        require_once(".ht-inc/resource.php");
                        break;
                case 'storebackend':
@@ -1326,15 +1327,20 @@ function getImages($includedeleted=0, $i
               .        "i.lastupdate, "
               .        "i.forcheckout, "
               .        "i.maxinitialtime, "
-              .        "i.imagemetaid "
-              . "FROM image i, "
-              .      "platform p, "
+              .        "i.imagemetaid, "
+              .        "ad.id AS addomainid, "
+              .        "ad.name AS addomain, "
+              .        "iadd.baseOU "
+              . "FROM platform p, "
               .      "OS o, "
               .      "OStype ot, "
               .      "resource r, "
               .      "resourcetype t, "
               .      "user u, "
-              .      "affiliation a "
+              .      "affiliation a, "
+              .      "image i "
+              . "LEFT JOIN imageaddomain iadd ON (i.id = iadd.imageid) "
+              . "LEFT JOIN addomain ad ON (iadd.addomainid = ad.id) "
               . "WHERE i.platformid = p.id AND "
               .       "r.resourcetypeid = t.id AND "
               .       "t.name = 'image' AND "
@@ -1357,6 +1363,9 @@ function getImages($includedeleted=0, $i
                        $imagelist[$includedeleted][$row['id']]['sethostname'] 
= 0;
                else
                        $imagelist[$includedeleted][$row['id']]['sethostname'] 
= 1;
+               $imagelist[$includedeleted][$row['id']]['adauthenabled'] = 0;
+               if($row['addomainid'] != NULL)
+                       
$imagelist[$includedeleted][$row['id']]['adauthenabled'] = 1;
                if($row["imagemetaid"] != NULL) {
                        if(array_key_exists($row['imagemetaid'], $allmetadata)) 
{
                                $metaid = $row['imagemetaid'];
@@ -2998,22 +3007,31 @@ function getResourceGroupMembers($type="
                $orders = "m.hostname";
                $types = "'managementnode'";
        }
+       elseif($type == "addomain") {
+               $names = "ad.name AS addomain ";
+               $joins = "LEFT JOIN addomain ad ON (r.subid = ad.id AND 
r.resourcetypeid = 19) ";
+               $orders = "ad.name";
+               $types = "'addomain'";
+       }
        else {
                $names = "c.hostname AS computer, "
                       . "c.deleted, "
                       . "i.prettyname AS image, "
                       . "i.deleted AS deleted2, "
                       . "s.name AS schedule, "
-                      . "m.hostname AS managementnode ";
+                      . "m.hostname AS managementnode, "
+                      . "ad.name AS addomain ";
                $joins = "LEFT JOIN computer c ON (r.subid = c.id AND 
r.resourcetypeid = 12) "
                       . "LEFT JOIN image i ON (r.subid = i.id AND 
r.resourcetypeid = 13) "
                       . "LEFT JOIN schedule s ON (r.subid = s.id AND 
r.resourcetypeid = 15) "
-                      . "LEFT JOIN managementnode m ON (r.subid = m.id AND 
r.resourcetypeid = 16) ";
+                      . "LEFT JOIN managementnode m ON (r.subid = m.id AND 
r.resourcetypeid = 16) "
+                      . "LEFT JOIN addomain ad ON (r.subid = ad.id AND 
r.resourcetypeid = 19) ";
                $orders = "c.hostname, "
                        . "i.prettyname, "
                        . "s.name, "
-                       . "m.hostname";
-               $types = "'computer','image','schedule','managementnode'";
+                       . "m.hostname, "
+                       . "ad.name";
+               $types = 
"'computer','image','schedule','managementnode','addomain'";
        }
 
        $query = "SELECT rgm.resourcegroupid, "
@@ -8813,6 +8831,60 @@ function getNATports($resid) {
 
 
////////////////////////////////////////////////////////////////////////////////
 ///
+/// \fn getADdomains($addomainid=0)
+///
+/// \param $addomainid - (optional) id of an AD domain
+///
+/// \return array of available AD domains with the following keys:\n
+/// \b id\n
+/// \b resourceid\n
+/// \b name\n
+/// \b ownerid\n
+/// \b owner\n
+/// \b domaindnsname\n
+/// \b domainnetbiosname\n
+/// \b username\n
+/// \b dnsservers\n
+/// \b domaincontrollers\n
+/// \b logindescription
+///
+/// \brief builds an array of AD domains
+///
+////////////////////////////////////////////////////////////////////////////////
+function getADdomains($addomainid=0) {
+       $query = "SELECT ad.id, "
+              .        "r.id AS resourceid, "
+              .        "ad.name, "
+              .        "ad.ownerid, "
+              .        "CONCAT(u.unityid, '@', a.name) AS owner, "
+              .        "ad.domainDNSName AS domaindnsname, "
+              .        "ad.domainNetBIOSName AS domainnetbiosname, "
+              .        "ad.username, "
+              .        "ad.dnsServers AS dnsservers, "
+              .        "ad.domainControllers AS domaincontrollers, "
+              .        "ad.logindescription "
+              . "FROM addomain ad, "
+              .      "affiliation a, "
+              .      "user u, "
+              .      "resource r, "
+              .      "resourcetype rt "
+              . "WHERE ad.ownerid = u.id AND "
+              .       "u.affiliationid = a.id AND "
+              .       "r.subid = ad.id AND "
+              .       "r.resourcetypeid = rt.id AND "
+              .       "rt.name = 'addomain'";
+       if($addomainid)
+               $query .= " AND ad.id = $addomainid";
+
+       $qh = doQuery($query);
+       $addomainlist = array();
+       while($row = mysql_fetch_assoc($qh))
+               $addomainlist[$row['id']] = $row;
+       return $addomainlist;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+///
 /// \fn getBlockTimeData($start, $end)
 ///
 /// \param $start - (optional) start time of blockTimes to get in unix 
timestamp
@@ -9098,11 +9170,12 @@ function labeledFormItem($id, $label, $t
                $required = 'false';
        switch($type) {
                case 'text':
+               case 'password':
                        if($width == '')
                                $width = '300px';
                        $h .= "<label for=\"$id\">$label:</label>\n";
                        $h .= "<span class=\"labeledform\">\n";
-                       $h .= "<input type=\"text\" ";
+                       $h .= "<input type=\"$type\" ";
                        $h .=        "dojoType=\"dijit.form.ValidationTextBox\" 
";
                        $h .=        "required=\"$required\" ";
                        if($constraints != '')
@@ -11891,6 +11964,26 @@ function validateIPv4addr($ip) {
 
 
////////////////////////////////////////////////////////////////////////////////
 ///
+/// \fn validateHostname($name)
+///
+/// \param $name  the hostname to validate
+///
+/// \return 1 if valid hostname else 0
+///
+/// \brief validates a given hostname
+///
+////////////////////////////////////////////////////////////////////////////////
+function validateHostname($name) {
+       if(strlen($name) > 255)
+               return 0;
+       // return 0 if dotted numbers only
+       if(preg_match('/^[0-9]+(\.[0-9]+){3}$/', $name))
+               return 0;
+       return 
preg_match('/^([A-Za-z0-9]{1,63})(\.[A-Za-z0-9-_]+)*(\.?[A-Za-z0-9])$/', $name);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+///
 /// \fn validateEmailAddress($addr)
 ///
 /// \param $addr - an email address
@@ -12714,6 +12807,12 @@ function getNavMenuData($homeurl=HOMEURL
                $menudata['vm']['selected'] = checkMenuItemSelected('vm');
        }
 
+       if(in_array("addomainAdmin", $user["privileges"])) {
+               $menudata['addomain']['url'] = BASEURL . SCRIPT . 
"?mode=addomain";
+               $menudata['addomain']['title'] = i('AD Domains');
+               $menudata['addomain']['selected'] = 
checkMenuItemSelected('addomain');
+       }
+
        if(checkUserHasPerm('Schedule Site Maintenance')) {
                $menudata['sitemaintenance']['url'] = BASEURL . SCRIPT . 
"?mode=siteMaintenance";
                $menudata['sitemaintenance']['title'] = i('Site Maintenance');
@@ -13277,6 +13376,9 @@ function getDojoHTML($refresh) {
                                case 'computer':
                                        $jsfile = 'resources/computer.js';
                                        break;
+                               case 'addomain':
+                                       $jsfile = 'resources/addomain.js';
+                                       break;
                        }
                        if(isset($jsfile))
                                $rt .= "<script type=\"text/javascript\" 
src=\"js/$jsfile?v=$v\"></script>\n";
@@ -13366,6 +13468,9 @@ function getDojoHTML($refresh) {
                                case 'computer':
                                        $jsfile = 'resources/computer.js';
                                        break;
+                               case 'addomain':
+                                       $jsfile = 'resources/addomain.js';
+                                       break;
                        }
                        $rt .= "<script type=\"text/javascript\" 
src=\"js/resources.js?v=$v\"></script>\n";
                        if(isset($jsfile))

Modified: vcl/trunk/web/css/vcl.css
URL: 
http://svn.apache.org/viewvc/vcl/trunk/web/css/vcl.css?rev=1762935&r1=1762934&r2=1762935&view=diff
==============================================================================
--- vcl/trunk/web/css/vcl.css (original)
+++ vcl/trunk/web/css/vcl.css Fri Sep 30 16:56:45 2016
@@ -591,6 +591,14 @@ body {
        width: 16.5em;
 }
 
+#addomaindlgcontent label {
+       width: 14.5em;
+}
+
+#addomaindlgcontent .labeledform {
+       margin-left: 15em;
+}
+
 #cfgvartypelbl {
        margin-top: 6px;
 }

Added: vcl/trunk/web/js/resources/addomain.js
URL: 
http://svn.apache.org/viewvc/vcl/trunk/web/js/resources/addomain.js?rev=1762935&view=auto
==============================================================================
--- vcl/trunk/web/js/resources/addomain.js (added)
+++ vcl/trunk/web/js/resources/addomain.js Fri Sep 30 16:56:45 2016
@@ -0,0 +1,145 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements.  See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License.  You may obtain a copy of the License at
+*
+*     http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+function ADdomain() {
+       Resource.apply(this, Array.prototype.slice.call(arguments));
+       this.restype = 'addomain';
+}
+ADdomain.prototype = new Resource();
+
+ADdomain.prototype.colformatter = function(value, rowIndex, obj) {
+       if(obj.field == 'logindescription') {
+               var str = value.replace(/&lt;br>/g, '<br>'); 
+               str = str.replace(/&amp;/g, '&'); 
+               return str;
+       }
+       return value;
+}
+
+var resource = new ADdomain();
+
+function addNewResource(title) {
+       dijit.byId('addeditdlg').set('title', title);
+       dijit.byId('addeditbtn').set('label', title);
+       dojo.byId('editresid').value = 0;
+       resetEditResource();
+       dijit.byId('addeditdlg').show();
+}
+
+function inlineEditResourceCB(data, ioArgs) {
+       if(data.items.status == 'success') {
+               dojo.byId('saveresourcecont').value = data.items.cont;
+               dijit.byId('addeditdlg').set('title', data.items.title);
+               dijit.byId('addeditbtn').set('label', 'Save Changes');
+               dojo.byId('editresid').value = data.items.rscid;
+               dijit.byId('name').set('value', data.items.data.name);
+               dijit.byId('owner').set('value', data.items.data.owner);
+
+               dijit.byId('domaindnsname').set('value', 
data.items.data.domaindnsname);
+               dijit.byId('domainnetbiosname').set('value', 
data.items.data.domainnetbiosname);
+               dijit.byId('username').set('value', data.items.data.username);
+               dijit.byId('dnsservers').set('value', 
data.items.data.dnsservers);
+               dijit.byId('domaincontrollers').set('value', 
data.items.data.domaincontrollers);
+               dijit.byId('logindescription').set('value', 
data.items.data.logindescription);
+
+               dojo.byId('addeditdlgerrmsg').innerHTML = '';
+               dijit.byId('addeditdlg').show();
+       }
+       else if(data.items.status == 'noaccess') {
+               alert('Access denied to edit this item');
+       }
+}
+
+function resetEditResource() {
+       var fields = ['name', 'owner', 'domaindnsname', 'domainnetbiosname', 
'username', 'password', 'password2', 'dnsservers', 'domaincontrollers', 
'logindescription'];
+       for(var i = 0; i < fields.length; i++) {
+               dijit.byId(fields[i]).reset();
+       }
+       dojo.byId('addeditdlgerrmsg').innerHTML = '';
+}
+
+function saveResource() {
+       var errobj = dojo.byId('addeditdlgerrmsg');
+       var fields = ['name', 'owner', 'domaindnsname', 'domainnetbiosname', 
'username', 'password', 'password2', 'dnsservers', 'domaincontrollers', 
'logindescription'];
+
+       if(dojo.byId('editresid').value == 0)
+               var data = {continuation: dojo.byId('addresourcecont').value};
+       else
+               var data = {continuation: dojo.byId('saveresourcecont').value};
+
+       for(var i = 0; i < fields.length; i++) {
+               if(! checkValidatedObj(fields[i], errobj))
+                       return;
+               data[fields[i]] = dijit.byId(fields[i]).get('value');
+       }
+       if(dijit.byId('password').get('value') != 
dijit.byId('password2').get('value')) {
+               dojo.byId('addeditdlgerrmsg').innerHTML = _('Passwords do not 
match');
+               return;
+       }
+
+       dijit.byId('addeditbtn').set('disabled', true);
+       RPCwrapper(data, saveResourceCB, 1);
+}
+
+function saveResourceCB(data, ioArgs) {
+       if(data.items.status == 'error') {
+               dojo.byId('addeditdlgerrmsg').innerHTML = '<br>' + 
data.items.msg;
+               dijit.byId('addeditbtn').set('disabled', false);
+               return;
+       }
+       else if(data.items.status == 'adderror') {
+               alert(data.items.errormsg);
+       }
+       else if(data.items.status == 'success') {
+               if(data.items.action == 'add') {
+                       if(typeof resourcegrid !== 'undefined') {
+                               resourcegrid.store.newItem(data.items.data);
+                               resourcegrid.sort();
+                       }
+                       
dojo.forEach(dijit.findWidgets(dojo.byId('groupdlgcontent')), function(w) {
+                               w.destroyRecursive();
+                       });
+                       if(data.items.nogroups == 0) {
+                               dojo.byId('groupdlgcontent').innerHTML = 
data.items.groupingHTML;
+                               AJdojoCreate('groupdlgcontent');
+                               dojo.byId('resources').value = 
data.items.data.id;
+                               populateLists('resources', 'ingroups', 
'inresourcename', 'outresourcename', 'resgroupinggroupscont');
+                               dijit.byId('groupdlg').show();
+                               dijit.byId('groupingnote').show();
+                       }
+               }
+               else {
+                       resourcegrid.store.fetch({
+                               query: {id: data.items.data.id},
+                               onItem: function(item) {
+                                       var fields = ['name', 'owner', 
'domaindnsname', 'domainnetbiosname', 'username','dnsservers', 
'domaincontrollers', 'logindescription'];
+                                       for(var i = 0; i < fields.length; i++) {
+                                               dijit.byId(fields[i]).reset();
+                                               
resourcegrid.store.setValue(item, fields[i], data.items.data[fields[i]]);
+                                       }
+                               },
+                               onComplete: function(items, result) {
+                                       // when call resourcegrid.sort 
directly, the table contents disappear; not sure why
+                                       setTimeout(function() 
{resourcegrid.sort();}, 10);
+                               }
+                       });
+               }
+               dijit.byId('addeditdlg').hide();
+               resetEditResource();
+               setTimeout(function() {dijit.byId('addeditbtn').set('disabled', 
false);}, 250);
+       }
+}

Modified: vcl/trunk/web/js/resources/image.js
URL: 
http://svn.apache.org/viewvc/vcl/trunk/web/js/resources/image.js?rev=1762935&r1=1762934&r2=1762935&view=diff
==============================================================================
--- vcl/trunk/web/js/resources/image.js (original)
+++ vcl/trunk/web/js/resources/image.js Fri Sep 30 16:56:45 2016
@@ -29,13 +29,16 @@ Image.prototype.colformatter = function(
           obj.field == 'forcheckout' ||
           obj.field == 'checkuser' ||
           obj.field == 'rootaccess' ||
-          obj.field == 'sethostname') {
+          obj.field == 'sethostname' ||
+          obj.field == 'adauthenabled') {
                if(value == "0")
                        return '<span class="rederrormsg">' + _('false') + 
'</span>';
                if(value == "1")
                        return '<span class="ready">' + _('true') + '</span>';
        }
-       if(obj.field == 'maxinitialtime' && value == 0)
+       if((obj.field == 'maxinitialtime' && value == 0) ||
+          (obj.field == 'addomain' && value == null) ||
+          (obj.field == 'baseOU' && value == null))
                return '(unset)';
        return value;
 }
@@ -70,6 +73,25 @@ function inlineEditResourceCB(data, ioAr
                        dojo.addClass('sethostnamediv', 'hidden');
                dojo.byId('connectmethodlist').innerHTML = 
data.items.data.connectmethods.join('<br>');
                dijit.byId('connectmethodttd').set('href', 
data.items.data.connectmethodurl);
+               if(data.items.data.ostype == 'windows') {
+                       dojo.removeClass('imageadauthbox', 'hidden');
+                       if(data.items.data.adauthenabled) {
+                               dijit.byId('adauthenable').set('checked', true);
+                               dijit.byId('addomainid').set('value', 
data.items.data.addomainid);
+                               dijit.byId('baseou').set('value', 
data.items.data.baseOU);
+                       }
+                       else {
+                               dijit.byId('adauthenable').set('checked', 
false);
+                               dijit.byId('addomainid').reset();
+                               dijit.byId('baseou').reset();
+                       }
+               }
+               else {
+                       dojo.addClass('imageadauthbox', 'hidden');
+                       dijit.byId('adauthenable').set('checked', false);
+                       dijit.byId('addomainid').reset();
+                       dijit.byId('baseou').reset();
+               }
                dijit.byId('subimagedlg').set('href', 
data.items.data.subimageurl);
                dojo.byId('revisiondiv').innerHTML = 
data.items.data.revisionHTML;
                dojo.byId('addeditdlgerrmsg').innerHTML = '';
@@ -111,6 +133,9 @@ function resetEditResource() {
                dijit.byId('advancedoptions').toggle();
        dojo.byId('connectmethodlist').innerHTML = '';
        dojo.byId('addeditdlgerrmsg').innerHTML = '';
+       dijit.byId('adauthenable').reset();
+       dijit.byId('addomainid').reset();
+       dijit.byId('baseou').reset();
 }
 
 function saveResource() {
@@ -168,6 +193,12 @@ function saveResource() {
                setTimeout(function() {dijit.byId('reload').focus();}, 300);
                return;
        }
+       if(dijit.byId('adauthenable').checked && ! checkValidatedObj('baseou', 
errobj)) {
+               if(! dijit.byId('advancedoptions').open)
+                       dijit.byId('advancedoptions').toggle();
+               setTimeout(function() {dijit.byId('baseou').focus();}, 300);
+               return;
+       }
 
        if(dojo.byId('editresid').value == 0)
                var data = {continuation: dojo.byId('addresourcecont').value};
@@ -234,6 +265,16 @@ function saveResource() {
        data['cpuspeed'] = dijit.byId('cpuspeed').get('value');
        if(dijit.byId('reload'))
                data['reload'] = dijit.byId('reload').get('value');
+       if(dijit.byId('adauthenable').checked) {
+               data['adauthenabled'] = 1;
+               data['addomainid'] = dijit.byId('addomainid').get('value');
+               data['baseou'] = dijit.byId('baseou').get('value');
+       }
+       else {
+               data['adauthenabled'] = 0;
+               data['addomainid'] = 0;
+               data['baseou'] = '';
+       }
 
        submitbtn.set('disabled', true);
        RPCwrapper(data, saveResourceCB, 1);
@@ -287,6 +328,10 @@ function saveResourceCB(data, ioArgs) {
                                        resourcegrid.store.setValue(item, 
'rootaccess', parseInt(data.items.data.rootaccess));
                                        resourcegrid.store.setValue(item, 
'sethostname', parseInt(data.items.data.sethostname));
                                        resourcegrid.store.setValue(item, 
'reloadtime', data.items.data.reloadtime);
+                                       resourcegrid.store.setValue(item, 
'adauthenabled', data.items.data.adauthenabled);
+                                       resourcegrid.store.setValue(item, 
'addomainid', data.items.data.addomainid);
+                                       resourcegrid.store.setValue(item, 
'addomain', data.items.data.addomain);
+                                       resourcegrid.store.setValue(item, 
'baseOU', data.items.data.baseOU);
                                },
                                onComplete: function(items, result) {
                                        // when call resourcegrid.sort 
directly, the table contents disappear; not sure why
@@ -663,10 +708,17 @@ function startImageCB(data, ioArgs) {
        }
        else
                dojo.addClass('sethostnamediv', 'hidden');
-       if(data.items.ostype == 'windows')
+       dijit.byId('adauthenable').set('checked', false);
+       dijit.byId('addomainid').reset();
+       dijit.byId('baseou').reset();
+       if(data.items.ostype == 'windows') {
                dojo.removeClass('sysprepdiv', 'hidden');
-       else
+               dojo.removeClass('imageadauthbox', 'hidden');
+       }
+       else {
                dojo.addClass('sysprepdiv', 'hidden');
+               dojo.addClass('imageadauthbox', 'hidden');
+       }
 
        if(data.items.checkpoint) {
                dojo.addClass('imageendrescontent', 'hidden');
@@ -763,3 +815,14 @@ function submitUpdateImageClickthroughCB
        dijit.byId('clickthroughDlgBtn').set('disabled', false);
        resRefresh();
 }
+
+function toggleADauth() {
+       if(dijit.byId('adauthenable').checked) {
+               dijit.byId('addomainid').set('disabled', false);
+               dijit.byId('baseou').set('disabled', false);
+       }
+       else {
+               dijit.byId('addomainid').set('disabled', true);
+               dijit.byId('baseou').set('disabled', true);
+       }
+}

Modified: vcl/trunk/web/themes/dropdownmenus/css/theme.css
URL: 
http://svn.apache.org/viewvc/vcl/trunk/web/themes/dropdownmenus/css/theme.css?rev=1762935&r1=1762934&r2=1762935&view=diff
==============================================================================
--- vcl/trunk/web/themes/dropdownmenus/css/theme.css (original)
+++ vcl/trunk/web/themes/dropdownmenus/css/theme.css Fri Sep 30 16:56:45 2016
@@ -144,6 +144,27 @@ div.dijitDialog h3 {
        background-color: black;
        color: white;
 }
+#renameDialog tbody tr:hover td,
+#renameDialog tbody tr td {
+       background-color: transparent;
+       border-top: none;
+       padding: 0.2em;
+}
+div.dijitDialog h2,
+div.dijitDialog h3 {
+       margin-top: 0.1em;
+}
+#confdelcontent h3 {
+       font-size: 1.4em;
+       font-weight: bold;
+}
+#groupbyresourcediv table.dojoxGridRowTable tbody tr:hover td {
+       background-color: transparent;
+}
+#groupbyresourcediv div.dojoxGridRowSelected table.dojoxGridRowTable tbody tr 
td {
+       background-color: black;
+       color: white;
+}
 #addeditdlg tbody tr td.dijitButtonNode {
        border: 1px solid #c0c0c0;
 }
@@ -416,6 +437,12 @@ h1.site-title {
 #advancedoptions .labeledform {
     margin-left: 21.5em;
 }
+#imageadauthbox label {
+    width: 16em;
+}
+#imageadauthbox .labeledform {
+    margin-left: 16.5em;
+}
 #mgmtnodedlgcontent label {
     width: 24.5em;
 }


Reply via email to