1#!/usr/bin/env perl
2##############################################################################
3# RackMonkey - Know Your Racks - http://www.rackmonkey.org                   #
4# Version 1.2.5-1                                                            #
5# (C)2004-2009 Will Green (wgreen at users.sourceforge.net)                  #
6# Main RackMonkey CGI script                                                 #
7##############################################################################
8
9# This program is free software; you can redistribute it and/or modify it
10# under the terms of the GNU General Public License as published by the Free
11# Software Foundation; either version 2 of the License, or (at your option)
12# any later version.
13
14# This program is distributed in the hope that it will be useful, but WITHOUT
15# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
17# more details.
18
19# You should have received a copy of the GNU General Public License along
20# with this program; if not, write to the Free Software Foundation, Inc.,
21# 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
22
23use strict;
24use warnings;
25
26use 5.006_001;
27
28use HTML::Template;
29use HTML::Entities;
30use Time::Local;
31use FindBin;
32use lib "$FindBin::Bin/";
33
34use RackMonkey::CGI;
35use RackMonkey::Engine;
36use RackMonkey::Error;
37
38our $VERSION = '1.2.5-1';
39our $AUTHOR  = 'Will Green (wgreen at users.sourceforge.net)';
40
41our ($template, $cgi, $conf, $backend);
42
43$cgi = new RackMonkey::CGI;
44
45eval {
46    $backend = RackMonkey::Engine->new;
47    $conf    = $backend->getConfHash;
48
49    my $fullURL      = $cgi->url;
50    my $baseURL      = $cgi->baseUrl;
51    my $view         = $cgi->view($$conf{'defaultview'});
52    my $id           = $cgi->viewId;
53    my $viewType     = $cgi->viewType;
54    my $act          = $cgi->act;
55    my $filterBy     = $cgi->filterBy;
56    my $deviceSearch = $cgi->deviceSearch;
57
58    my $orderBy = $cgi->orderBy;
59
60    my $loggedInUser = $ENV{'REMOTE_USER'} || $ENV{'REMOTE_ADDR'};
61
62    if ($act) # perform act, and return status: 303 (See Other) to redirect to a view
63    {
64        die "RMERR: You are logged in as 'guest'. Guest users can't update RackMonkey." if (lc($loggedInUser) eq 'guest');
65
66        my $actData = $cgi->vars;
67
68        # Trim whitespace from the start and end of all submitted values
69        for (values %$actData)
70        {
71            s/^\s+//;
72            s/\s+$//;
73        }
74
75        # delete id, only act_ids should be used be used for acts, ids are used for views
76        delete $$actData{'id'};
77
78        # convert act_id into a normal id for use by the engine
79        if ($$actData{'act_id'})
80        {
81            $$actData{'id'} = $$actData{'act_id'};
82            delete $$actData{'act_id'};
83        }
84
85        my $lastCreatedId = $backend->performAct($cgi->actOn, $act, $loggedInUser, scalar($cgi->vars));
86        $id = $lastCreatedId if (!$id);    # use lastCreatedId if there isn't an id
87        my $redirectUrl = "$fullURL?view=$view&view_type=$viewType";
88        $redirectUrl .= "&id=$id"                      if ($id);
89        $redirectUrl .= "&last_created_id=$lastCreatedId";
90        $redirectUrl .= "&device_search=$deviceSearch" if ($deviceSearch);
91
92        $cgi->redirect303($redirectUrl);
93    }
94    else # display a view
95    {
96        unless ($view =~ /^(?:config|help|app|building|device|deviceApp|domain|hardware|network|power|org|os|rack|report|role|room|row|service|system)$/)
97        {
98            die "RMERR: '$view' is not a valid view. Did you type the URL manually? Note that view names are singular, for example device NOT devices.";
99        }
100
101        if ($view eq 'system') # check for this view first: it doesn't use templates
102        {
103            print $cgi->header('text/plain');
104            my %sys = %{$backend->{'sys'}};
105            print map "$_: $sys{$_}\n", sort keys %sys;
106            exit;
107        }
108
109        my $templatePath = $$conf{'tmplpath'} . "/${view}_${viewType}.tmpl";
110        $template = HTML::Template->new('filename' => $templatePath, 'die_on_bad_params' => 0, 'global_vars' => 1, 'case_sensitive' => 1, 'loop_context_vars' => 1);
111
112        if (($view eq 'config') || ($view eq 'help') || ($view eq 'network') || ($view eq 'power'))
113        {
114            # do nothing - pages are static content
115        }
116        elsif ($view eq 'app')
117        {
118            if ($viewType =~ /^default/)
119            {
120                my $apps = $backend->appList($orderBy);
121                for my $a (@$apps)
122                {
123                    $$a{'descript_short'} = shortStr($$a{'descript'});
124                    $$a{'notes'}          = formatNotes($$a{'notes'}, 1);
125                    $$a{'notes_short'}    = shortStr($$a{'notes'});
126                }
127                my $totalAppCount  = $backend->itemCount('app');
128                my $listedAppCount = @$apps;
129                $template->param('total_app_count'  => $totalAppCount);
130                $template->param('listed_app_count' => $listedAppCount);
131                $template->param('all_apps_listed'  => ($totalAppCount == $listedAppCount));
132                $template->param('apps'             => $apps);
133            }
134            elsif (($viewType =~ /^edit/) || ($viewType =~ /^single/))
135            {
136                my $app = $backend->app($id);
137
138                if ($viewType =~ /^single/)
139                {
140                    $$app{'notes'} = formatNotes($$app{'notes'});
141                }
142
143                my $devices = $backend->appDevicesUsedList($id);
144                $$app{'app_devices'} = $devices;
145                $template->param($app);
146            }
147        }
148        elsif ($view eq 'building')
149        {
150            if ($viewType =~ /^default/)
151            {
152                my $buildings = $backend->buildingList($orderBy);
153                for my $b (@$buildings)
154                {
155                    $$b{'notes'} = formatNotes($$b{'notes'}, 1);
156                    $$b{'notes_short'} = shortStr($$b{'notes'});
157                }
158                my $totalBuildingCount  = $backend->itemCount('building');
159                my $listedBuildingCount = @$buildings;
160                $template->param('total_building_count'  => $totalBuildingCount);
161                $template->param('listed_building_count' => $listedBuildingCount);
162                $template->param('all_buildings_listed'  => ($totalBuildingCount == $listedBuildingCount));
163                $template->param('buildings'             => $buildings);
164            }
165            elsif (($viewType =~ /^edit/) || ($viewType =~ /^single/))
166            {
167                my $building = $backend->building($id);
168                if ($viewType =~ /^single/)
169                {
170                    $$building{'rooms'} = $backend->roomListInBuilding($id);
171                    $$building{'notes'} = formatNotes($$building{'notes'});
172                }
173                $template->param($building);
174            }
175        }
176        elsif ($view eq 'device')
177        {
178            if ($viewType =~ /^default/)
179            {
180                my $devices;
181
182                if ($viewType =~ /^default_unracked/)
183                {
184                    $devices = $backend->deviceListUnracked($orderBy, $filterBy, $deviceSearch);
185                }
186                else
187                {
188                    $devices = $backend->deviceList($orderBy, $filterBy, $deviceSearch);
189                }
190
191                my $filterBy = $cgi->filterBy;
192
193                my $customers = $backend->customerWithDevice;
194                unshift @$customers, {'id' => '', name => 'All'};
195                $template->param('customerlist' => $cgi->selectItem($customers, $$filterBy{'device.customer'}));
196
197                my $roles = $backend->roleWithDevice;
198                unshift @$roles, {'id' => '', name => 'All'};
199                $template->param('rolelist' => $cgi->selectItem($roles, $$filterBy{'device.role'}));
200
201                my $hardware = $backend->hardwareWithDevice;
202                unshift @$hardware, {'id' => '', name => 'All'};
203                $template->param('hardwarelist' => $cgi->selectItem($hardware, $$filterBy{'device.hardware'}));
204
205                my $os = $backend->osWithDevice;
206                unshift @$os, {'id' => '', name => 'All'};
207                $template->param('oslist' => $cgi->selectItem($os, $$filterBy{'device.os'}));
208
209                for my $d (@$devices)
210                {
211                    $$d{'age'}         = calculateAge($$d{'purchased'});    # determine age in years from purchased date
212                    $$d{'notes'}       = formatNotes($$d{'notes'}, 1);
213                    $$d{'notes_short'} = shortStr($$d{'notes'});
214                }
215
216                $template->param('device_search' => $deviceSearch);
217                $template->param('devices'       => $devices);
218
219                my $totalDeviceCount  = $backend->itemCount('device');
220                my $listedDeviceCount = @$devices;
221                $template->param('total_device_count'  => $totalDeviceCount);
222                $template->param('listed_device_count' => $listedDeviceCount);
223                $template->param('all_devices_listed'  => ($totalDeviceCount == $listedDeviceCount));
224            }
225            else
226            {
227                my $selectedManufacturer  = $cgi->lastCreatedId;
228                my $selectedHardwareModel = $cgi->lastCreatedId;
229                my $selectedOs            = $cgi->lastCreatedId;
230                my $selectedRole          = $cgi->lastCreatedId;
231                my $selectedCustomer      = $cgi->lastCreatedId;
232                my $selectedService       = $cgi->lastCreatedId;
233                my $selectedRack          = $cgi->selectProperty('rack') || $cgi->lastCreatedId;
234                my $selectedDomain        = $cgi->lastCreatedId;
235
236                if (($viewType =~ /^edit/) || ($viewType =~ /^single/) || ($viewType =~ /^create/))
237                {
238                    my $device = {};
239
240                    if ($id)
241                    {
242                        $device          = $backend->device($id);
243                        $$device{'age'}  = calculateAge($$device{'purchased'});
244                        $$device{'apps'} = $backend->appOnDeviceList($id);
245                    }
246
247                    if ($viewType =~ /^single/)
248                    {
249                        $$device{'notes'} = formatNotes($$device{'notes'});
250
251                        if (lc($$device{'hardware_manufacturer_name'}) =~ /dell/)    # not very extensible
252                        {
253                            $template->param('dell_query' => $$conf{'dellquery'});
254                        }
255                    }
256
257                    if ($viewType !~ /^single/)
258                    {
259                        # Use database value for selected if none in CGI
260                        $selectedManufacturer  = $$device{'hardware_manufacturer_id'} if (!$selectedManufacturer);
261                        $selectedHardwareModel = $$device{'hardware'}                 if (!$selectedHardwareModel);
262                        $selectedOs            = $$device{'os'}                       if (!$selectedOs);
263                        $selectedRole          = $$device{'role'}                     if (!$selectedRole);
264                        $selectedCustomer      = $$device{'customer'}                 if (!$selectedCustomer);
265                        $selectedService       = $$device{'service'}                  if (!$selectedService);
266                        $selectedRack          = $$device{'rack'}                     if (!$selectedRack);
267                        $selectedDomain        = $$device{'domain'}                   if (!$selectedDomain);
268                    }
269
270                    # clear values unique to a device if we're copying an existing device
271                    if ($viewType =~ /^create/)
272                    {
273                        $$device{'name'}            = '';
274                        $$device{'rack_pos'}        = '';
275                        $$device{'asset_no'}        = '';
276                        $$device{'serial_no'}       = '';
277                        $$device{'in_service'}      = 1;    # default is in service
278                        $$device{'notes'}           = '';
279                        $$device{'os_licence_key'}  = '';
280                    }
281
282                    $template->param($device);
283                }
284                if (($viewType =~ /^edit/) || ($viewType =~ /^create/))
285                {
286                    $template->param('selected_manufacturer'   => $selectedManufacturer);
287                    $template->param('selected_hardware_model' => $selectedHardwareModel);
288                    # manufacturerlist: run selectItem to prefix - on meta_default items, should be separate sub from selectItem
289                    $template->param('manufacturerlist'        => $cgi->selectItem($backend->manufacturerWithHardwareList, 0));
290                    $template->param('modelList'               => $backend->hardwareByManufacturer); # Todo: Need to add '-' prefix to meta default items
291                    $template->param('oslist'                  => $cgi->selectItem($backend->simpleList('os', 1), $selectedOs));
292                    $template->param('rolelist'                => $cgi->selectItem($backend->simpleList('role', 1), $selectedRole));
293                    $template->param('customerlist'            => $cgi->selectItem($backend->simpleList('customer', 1), $selectedCustomer));
294                    $template->param('servicelist'             => $cgi->selectItem($backend->simpleList('service', 1), $selectedService));
295                    $template->param('racklist'                => $cgi->selectRack($backend->rackListBasic, $selectedRack));
296                    $template->param('domainlist'              => $cgi->selectItem($backend->simpleList('domain', 1), $selectedDomain));
297                    $template->param('rack_pos'                => $cgi->selectProperty('position'));
298                }
299            }
300        }
301        elsif ($view eq 'deviceApp')
302        {
303            if ($viewType =~ /^create/)
304            {
305                my $app = $backend->app($id);
306                $template->param($app);
307
308                my $devices = $backend->deviceList;
309                $template->param('devices' => $devices);
310
311                my $relations = $backend->simpleList('app_relation', 1);
312                $template->param('relations' => $relations);
313            }
314        }
315        elsif ($view eq 'domain')
316        {
317            if ($viewType =~ /^default/)
318            {
319                my $domains = $backend->domainList($orderBy);
320                for my $d (@$domains)
321                {
322                    $$d{'notes'}          = formatNotes($$d{'notes'}, 1);
323                    $$d{'notes_short'}    = shortStr($$d{'notes'});
324                    $$d{'descript_short'} = shortStr($$d{'descript'});
325                }
326                my $totalDomainCount  = $backend->itemCount('domain');
327                my $listedDomainCount = @$domains;
328                $template->param('total_domain_count'  => $totalDomainCount);
329                $template->param('listed_domain_count' => $listedDomainCount);
330                $template->param('all_domains_listed'  => ($totalDomainCount == $listedDomainCount));
331                $template->param('domains'             => $domains);
332            }
333            elsif (($viewType =~ /^edit/) || ($viewType =~ /^single/))
334            {
335                my $domain = $backend->domain($id);
336                if ($viewType =~ /^single/)
337                {
338                    $$domain{'notes'} = formatNotes($$domain{'notes'});
339                }
340                $template->param($domain);
341            }
342        }
343        elsif ($view eq 'hardware')
344        {
345            if ($viewType =~ /^default/)
346            {
347                my $hardware = $backend->hardwareList($orderBy);
348                for my $h (@$hardware)
349                {
350                    $$h{'notes'} = formatNotes($$h{'notes'}, 1);
351                    $$h{'notes_short'} = shortStr($$h{'notes'});
352                }
353                my $totalHardwareCount  = $backend->itemCount('hardware');
354                my $listedHardwareCount = @$hardware;
355                $template->param('total_hardware_count'  => $totalHardwareCount);
356                $template->param('listed_hardware_count' => $listedHardwareCount);
357                $template->param('all_hardware_listed'   => ($totalHardwareCount == $listedHardwareCount));
358                $template->param('hardware'              => $hardware);
359            }
360            else
361            {
362                my $selectedManufacturer = $cgi->lastCreatedId;    # need to sort out this mess of CGI vars and make clearer!
363
364                if (($viewType =~ /^edit/) || ($viewType =~ /^single/))
365                {
366                    my $hardware = $backend->hardware($id);
367                    if ($viewType =~ /^single/)
368                    {
369                        $$hardware{'notes'} = formatNotes($$hardware{'notes'});
370                    }
371                    $selectedManufacturer = $$hardware{'manufacturer'} if (!$selectedManufacturer);    # Use database value for selected if none in CGI
372                    $$hardware{'support_url_short'} = shortURL($$hardware{'support_url'});             # not actually needed by edit view
373                    $$hardware{'spec_url_short'}    = shortURL($$hardware{'spec_url'});                # not actually needed by edit view
374                    $template->param($hardware);
375                }
376
377                if (($viewType =~ /^edit/) || ($viewType =~ /^create/))
378                {
379                    $template->param('manufacturerlist' => $cgi->selectItem($backend->simpleList('hardware_manufacturer', 1), $selectedManufacturer));
380                }
381            }
382        }
383        elsif ($view eq 'org')
384        {
385            if ($viewType =~ /^default/)
386            {
387                my $orgs = $backend->orgList($orderBy);
388
389                my $totalOrgCount  = $backend->itemCount('org');
390                my $listedOrgCount = @$orgs;
391                $template->param('total_org_count'  => $totalOrgCount);
392                $template->param('listed_org_count' => $listedOrgCount);
393                $template->param('all_org_listed'   => ($totalOrgCount == $listedOrgCount));
394
395                for my $o (@$orgs)
396                {
397                    $$o{'notes'}          = formatNotes($$o{'notes'}, 1);
398                    $$o{'notes_short'}    = shortStr($$o{'notes'});
399                    $$o{'descript_short'} = shortStr($$o{'descript'});
400                }
401                $template->param('orgs' => $orgs);
402            }
403            elsif (($viewType =~ /^edit/) || ($viewType =~ /^single/))
404            {
405                my $org = $backend->org($id);
406                if ($viewType =~ /^single/)
407                {
408                    $$org{'notes'} = formatNotes($$org{'notes'});
409                }
410                $template->param($org);
411            }
412            elsif ($viewType =~ /^create/)
413            {
414                $template->param({'customer' => $cgi->customer, 'software' => $cgi->software, 'hardware' => $cgi->hardware});
415            }
416        }
417        elsif ($view eq 'os')
418        {
419            if ($viewType =~ /^default/)
420            {
421                my $os = $backend->osList($orderBy);
422                for my $o (@$os)
423                {
424                    $$o{'notes'} = formatNotes($$o{'notes'}, 1);
425                    $$o{'notes_short'} = shortStr($$o{'notes'});
426                }
427                my $totalOSCount  = $backend->itemCount('os');
428                my $listedOSCount = @$os;
429                $template->param('total_os_count'   => $totalOSCount);
430                $template->param('listed_os_count'  => $listedOSCount);
431                $template->param('all_os_listed'    => ($totalOSCount == $listedOSCount));
432                $template->param('operatingsystems' => $os);
433            }
434            else
435            {
436                my $selectedManufacturer = $cgi->lastCreatedId;
437
438                if (($viewType =~ /^edit/) || ($viewType =~ /^single/))
439                {
440                    my $operatingSystem = $backend->os($id);
441                    if ($viewType =~ /^single/)
442                    {
443                        $$operatingSystem{'notes'} = formatNotes($$operatingSystem{'notes'});
444                    }
445                    $template->param($operatingSystem);
446                    $selectedManufacturer = $$operatingSystem{'manufacturer'} if (!$selectedManufacturer);    # Use database value for selected if none in CGI
447                }
448
449                if (($viewType =~ /^edit/) || ($viewType =~ /^create/))
450                {
451                    $template->param('manufacturerlist' => $cgi->selectItem($backend->simpleList('software_manufacturer', 1), $selectedManufacturer));
452                }
453            }
454        }
455        elsif ($view eq 'rack')
456        {
457            if ($viewType =~ /^default/)
458            {
459                my $racks = $backend->rackList($orderBy);
460                for my $r (@$racks)
461                {
462                    $$r{'notes'} = formatNotes($$r{'notes'}, 1);
463                    $$r{'notes_short'} = shortStr($$r{'notes'});
464                }
465                my $totalRackCount  = $backend->itemCount('rack');
466                my $listedRackCount = @$racks;
467                $template->param('total_rack_count'  => $totalRackCount);
468                $template->param('listed_rack_count' => $listedRackCount);
469                $template->param('all_racks_listed'  => ($totalRackCount == $listedRackCount));
470                $template->param('racks'             => $racks);
471            }
472            elsif ($viewType =~ /^physical/)
473            {
474                my @rackIdList = $cgi->rackList;
475                push(@rackIdList, $id) if (scalar(@rackIdList) == 0);    # add current rack id if no list
476                die "RMERR: You need to select at least one rack to display. Use the checkboxes at the right of the rack table to select racks."
477                  unless $rackIdList[0];
478                my @racks;
479                my $selectDevice = $cgi->id('device');
480                for my $rackId (@rackIdList)
481                {
482                    my $rack = $backend->rack($rackId);
483                    $$rack{'rack_layout'} = $backend->rackPhysical($rackId, $selectDevice, 1);
484                    push @racks, $rack;
485                }
486                $template->param('rack_list' => \@racks);
487                $template->param('device_id' => $selectDevice);
488            }
489            else
490            {
491                my $selectedRoom = $cgi->lastCreatedId || $cgi->id('room');
492
493                if (($viewType =~ /^edit/) || ($viewType =~ /^single/) || ($viewType =~ /^create/))
494                {
495                    my $rack = {};
496                    if ($id)    # used if copying, editing or displaying single view, but not for a plain create
497                    {
498                        $rack = $backend->rack($id);
499                    }
500                    else
501                    {
502                        $$rack{'numbering_direction'} = $$conf{'number_from_top'};
503                    }
504
505                    $selectedRoom = $$rack{'room'} if (!$selectedRoom);    # Use database value for selected if none in CGI - not actually needed in single view
506
507                    if ($viewType !~ /^single/)
508                    {
509                        $template->param('roomlist' => $cgi->selectRoom($backend->roomListBasic, $selectedRoom));
510                    }
511                    else
512                    {
513                        $$rack{'notes'} = formatNotes($$rack{'notes'});
514                    }
515
516                    # clear rack notes and name if we're creating a new device (so copy works)
517                    if ($viewType =~ /^create/)
518                    {
519                        $$rack{'name'}  = '';
520                        $$rack{'notes'} = '';
521                    }
522
523                    $template->param($rack);
524                }
525            }
526        }
527        elsif ($view eq 'report')
528        {
529            if ($viewType =~ /^default/)
530            {
531                my $totalDevices    = $backend->itemCount('device');
532                my $unrackedDevices = $backend->deviceCountUnracked;
533                $template->param('device_count'          => $totalDevices);
534                $template->param('unracked_device_count' => $unrackedDevices);
535                $template->param('racked_device_count'   => $totalDevices - $unrackedDevices);
536                $template->param('rack_count'            => $backend->itemCount('rack'));
537                my $rackSize   = $backend->totalSizeRack;
538                my $deviceSize = $backend->totalSizeDevice;
539                $template->param('total_rack_space' => $rackSize);
540                $template->param('used_rack_space'  => $deviceSize);
541                $template->param('free_rack_space'  => $rackSize - $deviceSize);
542            }
543            elsif ($viewType =~ /^counts/)
544            {
545                $template->param('customer_device_count' => $backend->customerDeviceCount);
546                $template->param('role_device_count'     => $backend->roleDeviceCount);
547                $template->param('hardware_device_count' => $backend->hardwareDeviceCount);
548                $template->param('os_device_count'       => $backend->osDeviceCount);
549            }
550            elsif ($viewType =~ /^duplicates/)
551            {
552                $template->param('serials'   => $backend->duplicateSerials);
553                $template->param('assets'    => $backend->duplicateAssets);
554                $template->param('oslicence' => $backend->duplicateOSLicenceKey);
555            }
556        }
557        elsif ($view eq 'role')
558        {
559            if ($viewType =~ /^default/)
560            {
561                my $roles = $backend->roleList($orderBy);
562
563                my $totalRoleCount  = $backend->itemCount('role');
564                my $listedRoleCount = @$roles;
565                $template->param('total_role_count'  => $totalRoleCount);
566                $template->param('listed_role_count' => $listedRoleCount);
567                $template->param('all_role_listed'   => ($totalRoleCount == $listedRoleCount));
568
569                for my $r (@$roles)
570                {
571                    $$r{'notes'}          = formatNotes($$r{'notes'}, 1);
572                    $$r{'notes_short'}    = shortStr($$r{'notes'});
573                    $$r{'descript_short'} = shortStr($$r{'descript'});
574                }
575                $template->param('roles' => $roles);
576            }
577            elsif (($viewType =~ /^edit/) || ($viewType =~ /^single/))
578            {
579                my $role = $backend->role($id);
580                if ($viewType =~ /^single/)
581                {
582                    $$role{'notes'} = formatNotes($$role{'notes'});
583                }
584                $template->param($role);
585            }
586        }
587        elsif ($view eq 'room')
588        {
589            if ($viewType =~ /^default/)
590            {
591                my $rooms = $backend->roomList($orderBy);
592                for my $r (@$rooms)
593                {
594                    $$r{'notes'} = formatNotes($$r{'notes'}, 1);
595                    $$r{'notes_short'} = shortStr($$r{'notes'});
596                }
597                my $totalRoomCount  = $backend->itemCount('room');
598                my $listedRoomCount = @$rooms;
599                $template->param('total_room_count'  => $totalRoomCount);
600                $template->param('listed_room_count' => $listedRoomCount);
601                $template->param('all_rooms_listed'  => ($totalRoomCount == $listedRoomCount));
602                $template->param('rooms'             => $rooms);
603            }
604            else
605            {
606                my $selectedBuilding = $cgi->lastCreatedId || $cgi->id('building');
607
608                if (($viewType =~ /^edit/) || ($viewType =~ /^single/))
609                {
610                    my $room = $backend->room($id);
611                    if ($viewType =~ /^single/)
612                    {
613                        $$room{'notes'} = formatNotes($$room{'notes'});
614                    }
615                    $$room{'row_count'} = $backend->rowCountInRoom($id);
616                    $selectedBuilding = $$room{'building'} if (!$selectedBuilding);    # Use database value for selected if none in CGI - not actually needed in single view
617                    if ($viewType =~ /^single/)
618                    {
619                        $$room{'racks'} = $backend->rackListInRoom($id);               # fix method then use
620                    }
621                    $template->param($room);
622                }
623
624                if (($viewType =~ /^edit/) || ($viewType =~ /^create/))
625                {
626                    $template->param('buildinglist' => $cgi->selectItem($backend->simpleList('building'), $selectedBuilding));
627                }
628            }
629        }
630        elsif ($view eq 'row')
631        {
632            $template->param('rows' => $backend->rowListInRoom($cgi->id('room')));
633            $template->param($backend->room($cgi->id('room')));
634        }
635        elsif ($view eq 'service')
636        {
637            if ($viewType =~ /^default/)
638            {
639                my $serviceLevels = $backend->serviceList($orderBy);
640
641                my $totalServiceCount  = $backend->itemCount('service');
642                my $listedServiceCount = @$serviceLevels;
643                $template->param('total_service_count'  => $totalServiceCount);
644                $template->param('listed_service_count' => $listedServiceCount);
645                $template->param('all_service_listed'   => ($totalServiceCount == $listedServiceCount));
646
647                for my $s (@$serviceLevels)
648                {
649                    $$s{'notes'}          = formatNotes($$s{'notes'}, 1);
650                    $$s{'notes_short'}    = shortStr($$s{'notes'});
651                    $$s{'descript_short'} = shortStr($$s{'descript'});
652                }
653                $template->param('services' => $serviceLevels);
654            }
655            elsif (($viewType =~ /^edit/) || ($viewType =~ /^single/))
656            {
657                my $service = $backend->service($id);
658                if ($viewType =~ /^single/)
659                {
660                    $$service{'notes'} = formatNotes($$service{'notes'});
661                }
662                $template->param($service);
663            }
664        }
665        else
666        {
667            die "RMERR: No such view. This error should not occur. Please report to developers.";
668        }
669    }
670
671    # create rack dropdown
672    my $selectedRack = 0;
673    $selectedRack = $id if (($viewType =~ /^physical/) && ($view eq 'rack'));
674    $template->param('racknavlist' => $cgi->selectRack($backend->rackListBasic(1), $selectedRack));
675
676    # Get version, date and user for page footer
677    $template->param('version' => "$VERSION");
678    my ($minute, $hour, $day, $month, $year) = (gmtime)[1, 2, 3, 4, 5];
679    my $currentDate = sprintf("%04d-%02d-%02d %02d:%02d GMT", $year + 1900, $month + 1, $day, $hour, $minute);
680    $template->param('date'           => $currentDate);
681    $template->param('logged_in_user' => $ENV{'REMOTE_USER'});
682    $template->param('user_ip'        => $ENV{'REMOTE_ADDR'});
683
684    # Make the current view and view_type available in the template
685    $template->param('view'      => $cgi->view);
686    $template->param('view_type' => $cgi->viewType);
687
688    # Support overriding the next view of the template
689    $template->param('return_view'      => $cgi->returnView     || $view);
690    $template->param('return_view_type' => $cgi->returnViewType || '');
691    $template->param('return_view_id'   => $cgi->returnViewId   || 0);
692
693    # support hiding and showing of filters
694    $template->param('show_filters'  => $cgi->showFilters);
695    $template->param('filter_string' => $cgi->filterString);
696
697    # XLS Plugin
698    if ($$conf{'plugin_xls'})
699    {
700        my $rack2XLSURL = $baseURL;
701        my $rackXLSName = $$conf{'plugin_xls'};
702
703        if ($rack2XLSURL =~ /rackmonkey\.pl/)
704        {
705            $rack2XLSURL =~ s/\/(.*?)\.pl/$rackXLSName/;
706        }
707        else
708        {
709            $rack2XLSURL .= $rackXLSName;
710        }
711        $template->param('rack2xls_url' => $rack2XLSURL);
712    }
713
714    # DNS Plugin
715    if ($$conf{'plugin_dns'})
716    {
717        my $rackDNSURL = $baseURL;
718        my $rackDNSName = $$conf{'plugin_dns'};
719
720        if ($rackDNSURL =~ /rackmonkey\.pl/)
721        {
722            $rackDNSURL =~ s/\/(.*?)\.pl/$rackDNSName/;
723        }
724        else
725        {
726            $rackDNSURL .= $rackDNSName;
727        }
728        $template->param('rackdns_url' => $rackDNSURL);
729    }
730
731    $template->param('base_url' => $baseURL);
732    $template->param('web_root' => $$conf{'wwwpath'});
733    $template->param('size_of_u' => $$conf{'size_of_u'});
734
735    $template->param('order_by' => $orderBy);
736
737    print $cgi->header;
738    print $template->output;
739};
740if ($@)
741{
742    my $errMsg = $@;
743    print $cgi->header;
744    my $friendlyErrMsg = RackMonkey::Error::enlighten($errMsg);
745    RackMonkey::Error::display($errMsg, $friendlyErrMsg, $backend->{'sys'});
746}
747
748sub shortStr
749{
750    my $str = shift;
751    return unless defined $str;
752    if (length($str) > $$conf{'shorttextlen'})
753    {
754        return substr($str, 0, $$conf{'shorttextlen'}) . '...';
755    }
756    return '';
757}
758
759sub shortURL
760{
761    my $url = shift;
762    return unless defined $url;
763    if (length($url) > $$conf{'shorturllen'})
764    {
765        return substr($url, 0, $$conf{'shorturllen'}) . '...';
766    }
767    return '';
768}
769
770sub calculateAge
771{
772    my $date = shift;
773    return unless defined $date;
774    my ($year, $month, $day) = $date =~ /(\d{4})-(\d{2})-(\d{2})/;
775    if ($year)
776    {
777        $month--;    # perl months start at 0
778        my $startTime = timelocal(0, 0, 12, $day, $month, $year);
779        my $age = (time - $startTime) / (86400 * 365.24);    # Age in years
780        return sprintf("%.1f", $age);
781    }
782    return '';
783}
784
785sub formatNotes
786{
787    my $note = shift;
788    my $inline = shift || 0;
789    $note = encode_entities($note);                             # we don't use HTML::Template escape so have to encode here
790
791    unless ($inline)
792    {
793        $note =~ s/\n/<br>/sg;                                  # turn newlines into break tags
794        $note =~ s/\[(.*?)\|(.*?)\]/<a href="$1">$2<\/a>/sg;    # create hyperlinks
795        $note =~ s/\*\*\*(.*?)\*\*\*/<strong>$1<\/strong>/sg;   # strong using ***
796        $note =~ s/\*\*(.*?)\*\*/<em>$1<\/em>/sg;               # emphasis using **
797    }
798    else
799    {
800        $note =~ s/\[(.*?)\|(.*?)\]/$2 ($1)/sg;                 # can't make proper hyperlinks inline as they may be truncated
801        $note =~ s/\*\*\*(.*?)\*\*\*/$1/sg;                     # remove ***
802        $note =~ s/\*\*(.*?)\*\*/$1/sg;                         # remove **
803    }
804
805    return $note;
806}
807