diff --git a/README.md b/README.md index da5517f27..e43da4ccc 100644 --- a/README.md +++ b/README.md @@ -105,29 +105,39 @@ root@host:~# gdebi /root/zoneminder_1.26.4-1_amd64.deb; Additional repositories must be added before one can build zoneminder on CentOS or RHEL: -1. RepoForge (formerly RPMForge) http://repoforge.org/use/ +1. Zmrepo [ZoneMinder WiKi](http://www.zoneminder.com/wiki/index.php/CentOS#Zmrepo_-_A_ZoneMinder_repository_for_RPM_based_distros) 2. EPEL https://fedoraproject.org/wiki/EPEL -3. Optional RPMFusion: http://rpmfusion.org/ [SEE NOTE] - -[NOTE]
-The RPMFusion repo contains significantly newer versions of ffmpeg and vlc. This leads to significantly better camera support. However, the RPMFusion repo contains packages that conflict with the other two repos. In order to resolve this, one must also install the yum priorities pacakge and use that to prioritize your repos in the following order: +3. RPMFusion: http://rpmfusion.org/ + +When adding third party repositories, it is highly recommended that the user also install and configure yum priorities as documented in the [CentOS WiKi](http://wiki.centos.org/PackageManagement/Yum/Priorities) + +Prioritize the repositories: 1. Base -2. RPMFusion -3. EPEL -4. RPMForge - -For instructions on yum priorities, visit this page: -http://wiki.centos.org/PackageManagement/Yum/Priorities +2. EPEL +3. RPMFusion +4. Zmrepo Once your repos are in order, install the following: ```bash -sudo yum install automake bzip2-devel ffmpeg ffmpeg-devel gnutls-devel httpd libjpeg-turbo libjpeg-turbo-devel mysql-devel mysql-server pcre-devel \ +sudo yum install cmake bzip2-devel ffmpeg ffmpeg-devel gnutls-devel httpd libjpeg-turbo libjpeg-turbo-devel mysql-devel mysql-server pcre-devel \ perl-Archive-Tar perl-Archive-Zip perl-Convert-BinHex perl-Date-Manip perl-DBD-MySQL perl-DBI perl-Device-SerialPort perl-Email-Date-Format perl-IO-stringy \ perl-IO-Zlib perl-MailTools perl-MIME-Lite perl-MIME-tools perl-MIME-Types perl-Module-Load perl-Package-Constants perl-Sys-Mmap perl-Time-HiRes \ -perl-TimeDate perl-YAML-Syck php php-cli php-mysql x264 vlc-devel vlc-core libcurl libcurl-devel +perl-TimeDate perl-YAML-Syck perl-X10 perl-URI-Encode php php-cli php-mysql x264 vlc-devel vlc-core \ +libcurl libcurl-devel polkit-devel git ``` +To build from the master branch: +```bash +git clone https://github.com/ZoneMinder/ZoneMinder.git +cd ZoneMinder +cmake . +make +sudo make install +``` + +IMPORTANT: Don't forget the trailing "." when calling cmake + #### Docker Docker is a system to run applications inside isolated containers. ZoneMinder, and the ZM webserver, will run using the @@ -159,4 +169,14 @@ the following steps. 6. Create new Pull Request 7. The team will then review, discuss and hopefully merge your changes. +### Package Maintainters +Many of the ZoneMinder configration variable default values are not configurable at build time through autotools or cmake. A new tool called *zmeditconfigdata.sh* has been added to allow package maintainers to manipulate any variable stored in ConfigData.pm without patching the source. + +For example, let's say I have created a new ZoneMinder package that contains the cambolzola javascript file. However, by default cambozola support is turned off. To fix that, add this to the pacakging script: +```bash +./utils/zmeditconfigdata.sh ZM_OPT_CAMBOZOLA yes +``` + +Note that zmeditconfigdata.sh is intended to be called, from the root build folder, prior to running cmake or configure. + [![Analytics](https://ga-beacon.appspot.com/UA-15147273-6/ZoneMinder/README.md)](https://github.com/igrigorik/ga-beacon) diff --git a/distros/debian/control b/distros/debian/control index da787a9d8..c4ab69918 100644 --- a/distros/debian/control +++ b/distros/debian/control @@ -7,7 +7,7 @@ Standards-Version: 3.9.2 Package: zoneminder Architecture: any -Depends: ${shlibs:Depends}, ${misc:Depends}, ${perl:Depends}, apache2 | httpd, libapache2-mod-php5 | libapache2-mod-fcgid | php5-fpm, php5, php5-mysql|php5-mysqlnd, libphp-serialization-perl, libdate-manip-perl, libmime-lite-perl, libmime-tools-perl, mariadb-client|mysql-client, libwww-perl, libarchive-tar-perl, libarchive-zip-perl, libdevice-serialport-perl, libpcre3, ffmpeg | libav-tools, rsyslog | system-log-daemon, libmodule-load-perl, libsys-mmap-perl, libjson-any-perl, netpbm, libavdevice53, libjpeg8, zip, libnet-sftp-foreign-perl, libio-pty-perl, libexpect-perl, libvlccore5 | libvlccore7, libvlc5, libcurl4-gnutls-dev | libcurl4-nss-dev | libcurl4-openssl-dev, libpolkit-gobject-1-0 +Depends: ${shlibs:Depends}, ${misc:Depends}, ${perl:Depends}, apache2, libapache2-mod-php5 | libapache2-mod-fcgid, php5, php5-mysql|php5-mysqlnd, libphp-serialization-perl, libdate-manip-perl, libmime-lite-perl, libmime-tools-perl, mariadb-client|mysql-client, libwww-perl, libarchive-tar-perl, libarchive-zip-perl, libdevice-serialport-perl, libpcre3, ffmpeg | libav-tools, rsyslog | system-log-daemon, libmodule-load-perl, libsys-mmap-perl, libjson-any-perl, netpbm, libavdevice53 | libavdevice55, libjpeg8, zip, libnet-sftp-foreign-perl, libio-pty-perl, libexpect-perl, libvlccore5 | libvlccore7 | libvlccore8, libvlc5, libcurl4-gnutls-dev | libcurl4-nss-dev | libcurl4-openssl-dev, libpolkit-gobject-1-0, liburi-encode-perl Recommends: mysql-server|mariadb-server Description: A video camera security and surveillance solution ZoneMinder is intended for use in single or multi-camera video security diff --git a/distros/fedora/zoneminder.cmake.f20.spec b/distros/fedora/zoneminder.cmake.f20.spec index 5eea7150c..cf5eb1fa6 100644 --- a/distros/fedora/zoneminder.cmake.f20.spec +++ b/distros/fedora/zoneminder.cmake.f20.spec @@ -22,8 +22,6 @@ URL: http://www.zoneminder.com/ #Source: https://github.com/ZoneMinder/ZoneMinder/archive/v%{version}.tar.gz Source: ZoneMinder-%{version}.tar.gz -Patch1: zoneminder-1.28.0-defaults.patch - BuildRequires: cmake gnutls-devel systemd-units bzip2-devel BuildRequires: community-mysql-devel pcre-devel libjpeg-turbo-devel BuildRequires: perl(Archive::Tar) perl(Archive::Zip) @@ -66,7 +64,13 @@ too much degradation of performance. %prep %setup -q -n ZoneMinder-%{version} -%patch1 -p0 -b .defaults +# Change the following default values +./utils/zmeditconfigdata.sh ZM_PATH_ZMS /cgi-bin/zm/nph-zms +./utils/zmeditconfigdata.sh ZM_OPT_CAMBOZOLA yes +./utils/zmeditconfigdata.sh ZM_PATH_SWAP /dev/shm +./utils/zmeditconfigdata.sh ZM_UPLOAD_FTP_LOC_DIR /var/spool/zoneminder-upload +./utils/zmeditconfigdata.sh ZM_OPT_CONTROL yes + %build %cmake \ diff --git a/distros/redhat/zoneminder.cmake.el6.spec b/distros/redhat/zoneminder.cmake.el6.spec index f40291faf..844282baa 100644 --- a/distros/redhat/zoneminder.cmake.el6.spec +++ b/distros/redhat/zoneminder.cmake.el6.spec @@ -17,8 +17,6 @@ URL: http://www.zoneminder.com/ #Source0: https://github.com/ZoneMinder/ZoneMinder/archive/v%{version}.tar.gz Source0: ZoneMinder-%{version}.tar.gz -Patch1: zoneminder-1.28.0-defaults.patch - BuildRequires: cmake gnutls-devel bzip2-devel BuildRequires: mysql-devel pcre-devel libjpeg-turbo-devel BuildRequires: perl(Archive::Tar) perl(Archive::Zip) @@ -63,7 +61,12 @@ too much degradation of performance. %prep %setup -q -n ZoneMinder-%{version} -%patch1 -p0 -b .defaults +# Change the following default values +./utils/zmeditconfigdata.sh ZM_PATH_ZMS /cgi-bin/zm/nph-zms +./utils/zmeditconfigdata.sh ZM_OPT_CAMBOZOLA yes +./utils/zmeditconfigdata.sh ZM_PATH_SWAP /dev/shm +./utils/zmeditconfigdata.sh ZM_UPLOAD_FTP_LOC_DIR /var/spool/zoneminder-upload +./utils/zmeditconfigdata.sh ZM_OPT_CONTROL yes %build # Have to override CMAKE_INSTALL_LIBDIR for cmake < 2.8.7 due to this bug: diff --git a/scripts/ZoneMinder/lib/ZoneMinder/Control/AxisV2.pm b/scripts/ZoneMinder/lib/ZoneMinder/Control/AxisV2.pm index e5a5882b9..2372a2d81 100644 --- a/scripts/ZoneMinder/lib/ZoneMinder/Control/AxisV2.pm +++ b/scripts/ZoneMinder/lib/ZoneMinder/Control/AxisV2.pm @@ -33,8 +33,6 @@ require ZoneMinder::Control; our @ISA = qw(ZoneMinder::Control); -our $VERSION = $ZoneMinder::Base::VERSION; - # ========================================================================== # # Axis V2 Control Protocol @@ -79,7 +77,7 @@ sub open use LWP::UserAgent; $self->{ua} = LWP::UserAgent->new; - $self->{ua}->agent( "ZoneMinder Control Agent/".ZM_VERSION ); + $self->{ua}->agent( "ZoneMinder Control Agent/".ZoneMinder::Base::ZM_VERSION ); $self->{state} = 'open'; } diff --git a/scripts/zmupdate.pl.in b/scripts/zmupdate.pl.in index 83502154c..41a081fc1 100644 --- a/scripts/zmupdate.pl.in +++ b/scripts/zmupdate.pl.in @@ -89,6 +89,8 @@ Parameters are :- -u, --user= - Alternate DB user with privileges to alter DB -p, --pass= - Password of alternate DB user with privileges to alter DB -d,--dir= - Directory containing update files if not in default build location +-interactive - interact with the user +-nointeractive - do not interact with the user "); exit( -1 ); } @@ -319,34 +321,37 @@ if ( $freshen ) saveConfigToDB(); } -# Now check for MyISAM Tables -my @MyISAM_Tables; -my $sql = "SELECT table_name FROM INFORMATION_SCHEMA.TABLES WHERE table_schema='zm' AND engine = 'MyISAM'"; -my $sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() ); -my $res = $sth->execute() or die( "Can't execute: ".$sth->errstr() ); +# Don't do innoDB upgrade if not interactive +if ( $interactive ) { + # Now check for MyISAM Tables + my @MyISAM_Tables; + my $sql = "SELECT table_name FROM INFORMATION_SCHEMA.TABLES WHERE table_schema='zm' AND engine = 'MyISAM'"; + my $sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() ); + my $res = $sth->execute() or die( "Can't execute: ".$sth->errstr() ); -while( my $dbTable = $sth->fetchrow() ) { - push @MyISAM_Tables, $dbTable; -} -$sth->finish(); + while( my $dbTable = $sth->fetchrow() ) { + push @MyISAM_Tables, $dbTable; + } + $sth->finish(); -if ( @MyISAM_Tables ) { - print( "\nPrevious versions of ZoneMinder used the MyISAM database engine.\nHowever, the recommended database engine is InnoDB.\n"); - print( "\nHint: InnoDB tables are much less likely to be corrupted during an unclean shutdown.\n\nPress 'y' to convert your tables to InnoDB or 'n' to skip : "); - my $response = ; - chomp( $response ); - if ( $response =~ /^[yY]$/ ) { - print "\nConverting MyISAM tables to InnoDB. Please wait.\n"; - foreach (@MyISAM_Tables) { + if ( @MyISAM_Tables ) { + print( "\nPrevious versions of ZoneMinder used the MyISAM database engine.\nHowever, the recommended database engine is InnoDB.\n"); + print( "\nHint: InnoDB tables are much less likely to be corrupted during an unclean shutdown.\n\nPress 'y' to convert your tables to InnoDB or 'n' to skip : "); + my $response = ; + chomp( $response ); + if ( $response =~ /^[yY]$/ ) { $dbh->do(q|SET sql_mode='traditional'|); # Elevate warnings to errors - my $sql = "ALTER TABLE $_ ENGINE = InnoDB"; - my $sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() ); - my $res = $sth->execute() or die( "Can't execute: ".$sth->errstr() ); - $sth->finish(); + print "\nConverting MyISAM tables to InnoDB. Please wait.\n"; + foreach (@MyISAM_Tables) { + my $sql = "ALTER TABLE $_ ENGINE = InnoDB"; + my $sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() ); + my $res = $sth->execute() or die( "Can't execute: ".$sth->errstr() ); + $sth->finish(); + } $dbh->do(q|SET sql_mode=''|); # Set mode back to default } } -} +} # end if interactive if ( $version ) { diff --git a/src/zm_monitor.cpp b/src/zm_monitor.cpp index dccf6d759..fa89874e6 100644 --- a/src/zm_monitor.cpp +++ b/src/zm_monitor.cpp @@ -463,12 +463,12 @@ Monitor::Monitor( { if ( purpose != QUERY ) { - Error( "Shared data not initialised by capture daemon" ); + Error( "Shared data not initialised by capture daemon for monitor %s", name ); exit( -1 ); } else { - Warning( "Shared data not initialised by capture daemon, some query functions may not be available or produce invalid results" ); + Warning( "Shared data not initialised by capture daemon, some query functions may not be available or produce invalid results for monitor %s", name ); } } diff --git a/src/zm_rtsp.cpp b/src/zm_rtsp.cpp index 384e1c80c..f157f4e4f 100644 --- a/src/zm_rtsp.cpp +++ b/src/zm_rtsp.cpp @@ -768,11 +768,10 @@ int RtspThread::run() if ( !recvResponse( response ) ) return( -1 ); #endif + // Send a teardown message but don't expect a response as this may not be implemented on the server when using TCP message = "TEARDOWN "+mUrl+" RTSP/1.0\r\nSession: "+session+"\r\n"; if ( !sendCommand( message ) ) return( -1 ); - if ( !recvResponse( response ) ) - return( -1 ); delete mSources[ssrc]; mSources.clear(); diff --git a/utils/zmeditconfigdata.sh b/utils/zmeditconfigdata.sh new file mode 100755 index 000000000..71b73bb6e --- /dev/null +++ b/utils/zmeditconfigdata.sh @@ -0,0 +1,100 @@ +#!/bin/bash +# This script allows the package maintainer to change the default value +# of any variable specified in ConfigData.pm without writing a patch. +# Run this script from your build folder, before running configure or cmake. + +usage() +{ +cat < /dev/null + + if [ $? -ne 0 ]; then + echo + echo "ERROR: The script cannot find the required command \"${CMD}\"." + echo + exit 1 + fi +done + +escape() +{ +escaped="" +local temp="$(printf %q "$1")" +escaped="$(echo $temp | sed 's/\//\\\//g')" +} + +# Assign variables once they are properly escaped +escape $1 +variable=$escaped +escape $2 +default=$escaped + +# Set the path to ConfigData +if [ -n "$3" ]; then + configdata="$3/ConfigData.pm.in" +else + configdata="./scripts/ZoneMinder/lib/ZoneMinder/ConfigData.pm.in" +fi + +# Check to make sure we can find ConfigData +if [ ! -e "$configdata" ]; then + echo "CONFIGDATA FILE NOT FOUND: $configdata" + exit 1 +fi + +# Now that we've found ConfidData, verify the supplied variable +# is defined inside the ConfigData file. +if [ -z "$(grep $variable $configdata)" ]; then + echo "ZONEMINDER VARIABLE NOT FOUND: $variable" + exit 1 +fi + +# Update the supplied variable with the new default value. +# Don't stare too closely. You will burn your eyes out. +sed -i '/.*'${variable}'.*/{ + $!{ N + s/\(.*'${variable}'.*\n.*\)\"\(.*\)\"/\1\"'${default}'\"/ + t yes + P + D + :yes + + } + }' $configdata + +if [ "$?" != "0" ]; then + echo "SED RETURNED FAILURE" + exit 1 +fi + + + diff --git a/web/api/app/Controller/Component/ConfigParserComponent.php b/web/api/app/Controller/Component/ConfigParserComponent.php new file mode 100644 index 000000000..18d06fba8 --- /dev/null +++ b/web/api/app/Controller/Component/ConfigParserComponent.php @@ -0,0 +1,80 @@ +$hint"; + } + return $string; + } + + public function getLabel($name) { + $width = 'col-md-4'; + + $string = '
'; + $string .= ''; + $label = sprintf($string, $name, $width, $name); + $label .= '
'; + + return $label; + } + + public function getInput($name, $type, $id) { + if ($type == 'checkbox') { + $string = '
'; + } elseif ($type == 'text') { + $string = '
'; + } elseif ($type == 'textarea') { + $string = ''; + } elseif ($type == 'select') { + $string = ' '; + } + break; + default: + $string .= $this->getInput($name, 'text', $id); + } + $string .= "\n"; + } + return $string; + } + + +} +?> diff --git a/web/api/app/Controller/ConfigsController.php b/web/api/app/Controller/ConfigsController.php index a6759a512..3198ae58e 100644 --- a/web/api/app/Controller/ConfigsController.php +++ b/web/api/app/Controller/ConfigsController.php @@ -88,4 +88,50 @@ class ConfigsController extends AppController { } else { return $this->flash(__('The config could not be deleted. Please, try again.'), array('action' => 'index')); } - }} + } + +/** + * categories method + * + * Either return a list of distinct categories + * Or all configs under a certain category + */ + + public function categories($category = null) { + if ($category != null) { + if (!$this->Config->find('first', array( 'conditions' => array('Config.Category' => $category)))) { + throw new NotFoundException(__('Invalid Config Category')); + } + + $config = $this->Config->find('all', array( + 'conditions' => array('Config.Category' => $category), + 'recursive' => 0 + )); + $this->set(array( + 'config' => $config, + '_serialize' => array('config') + )); + } else { + $categories = $this->Config->find('all', array( + 'fields' => array('DISTINCT Config.Category'), + 'conditions' => array('Config.Category !=' => 'hidden'), + 'recursive' => 0 + )); + $this->set(array( + 'categories' => $categories, + '_serialize' => array('categories') + )); + } + + } + + public function keyValue() { + $keyValues = $this->Config->find('list', array( + 'fields' => array('Config.Name', 'Config.Value') + )); + $this->set(array( + 'keyValues' => $keyValues, + '_serialize' => array('keyValues') + )); + } +} diff --git a/web/api/app/Controller/LogsController.php b/web/api/app/Controller/LogsController.php new file mode 100644 index 000000000..908c635e2 --- /dev/null +++ b/web/api/app/Controller/LogsController.php @@ -0,0 +1,96 @@ +Log->recursive = 0; + $this->set('logs', $this->Paginator->paginate()); + } + +/** + * view method + * + * @throws NotFoundException + * @param string $id + * @return void + */ + public function view($id = null) { + if (!$this->Log->exists($id)) { + throw new NotFoundException(__('Invalid log')); + } + $options = array('conditions' => array('Log.' . $this->Log->primaryKey => $id)); + $this->set('log', $this->Log->find('first', $options)); + } + +/** + * add method + * + * @return void + */ + public function add() { + if ($this->request->is('post')) { + $this->Log->create(); + if ($this->Log->save($this->request->data)) { + return $this->flash(__('The log has been saved.'), array('action' => 'index')); + } + } + } + +/** + * edit method + * + * @throws NotFoundException + * @param string $id + * @return void + */ + public function edit($id = null) { + if (!$this->Log->exists($id)) { + throw new NotFoundException(__('Invalid log')); + } + if ($this->request->is(array('post', 'put'))) { + if ($this->Log->save($this->request->data)) { + return $this->flash(__('The log has been saved.'), array('action' => 'index')); + } + } else { + $options = array('conditions' => array('Log.' . $this->Log->primaryKey => $id)); + $this->request->data = $this->Log->find('first', $options); + } + } + +/** + * delete method + * + * @throws NotFoundException + * @param string $id + * @return void + */ + public function delete($id = null) { + $this->Log->id = $id; + if (!$this->Log->exists()) { + throw new NotFoundException(__('Invalid log')); + } + $this->request->allowMethod('post', 'delete'); + if ($this->Log->delete()) { + return $this->flash(__('The log has been deleted.'), array('action' => 'index')); + } else { + return $this->flash(__('The log could not be deleted. Please, try again.'), array('action' => 'index')); + } + }} diff --git a/web/api/app/Controller/MonitorsController.php b/web/api/app/Controller/MonitorsController.php index 3e9556a19..da4339e8e 100644 --- a/web/api/app/Controller/MonitorsController.php +++ b/web/api/app/Controller/MonitorsController.php @@ -108,4 +108,21 @@ class MonitorsController extends AppController { } else { return $this->flash(__('The monitor could not be deleted. Please, try again.'), array('action' => 'index')); } - }} + } + + public function sourceTypes() { + $sourceTypes = $this->Monitor->query("describe Monitors Type;"); + + preg_match('/^enum\((.*)\)$/', $sourceTypes[0]['COLUMNS']['Type'], $matches); + foreach( explode(',', $matches[1]) as $value ) { + $enum[] = trim( $value, "'" ); + } + + $this->set(array( + 'sourceTypes' => $enum, + '_serialize' => array('sourceTypes') + )); + } + +} + diff --git a/web/api/app/Model/Log.php b/web/api/app/Model/Log.php new file mode 100644 index 000000000..4bbe69be9 --- /dev/null +++ b/web/api/app/Model/Log.php @@ -0,0 +1,23 @@ + +Form->create('Log'); ?> +
+ + Form->input('Component'); + echo $this->Form->input('Pid'); + echo $this->Form->input('Level'); + echo $this->Form->input('Code'); + echo $this->Form->input('Message'); + echo $this->Form->input('File'); + echo $this->Form->input('Line'); + ?> +
+Form->end(__('Submit')); ?> + +
+

+
    + +
  • Html->link(__('List Logs'), array('action' => 'index')); ?>
  • +
+
diff --git a/web/api/app/View/Logs/edit.ctp b/web/api/app/View/Logs/edit.ctp new file mode 100644 index 000000000..cdd5dab2b --- /dev/null +++ b/web/api/app/View/Logs/edit.ctp @@ -0,0 +1,25 @@ +
+Form->create('Log'); ?> +
+ + Form->input('TimeKey'); + echo $this->Form->input('Component'); + echo $this->Form->input('Pid'); + echo $this->Form->input('Level'); + echo $this->Form->input('Code'); + echo $this->Form->input('Message'); + echo $this->Form->input('File'); + echo $this->Form->input('Line'); + ?> +
+Form->end(__('Submit')); ?> +
+
+

+
    + +
  • Form->postLink(__('Delete'), array('action' => 'delete', $this->Form->value('Log.TimeKey')), null, __('Are you sure you want to delete # %s?', $this->Form->value('Log.TimeKey'))); ?>
  • +
  • Html->link(__('List Logs'), array('action' => 'index')); ?>
  • +
+
diff --git a/web/api/app/View/Logs/index.ctp b/web/api/app/View/Logs/index.ctp new file mode 100644 index 000000000..47cbeb57f --- /dev/null +++ b/web/api/app/View/Logs/index.ctp @@ -0,0 +1,52 @@ +
+

+ + + + + + + + + + + + + + + + + + + + + + + + + +
Paginator->sort('TimeKey'); ?>Paginator->sort('Component'); ?>Paginator->sort('Pid'); ?>Paginator->sort('Level'); ?>Paginator->sort('Code'); ?>Paginator->sort('Message'); ?>Paginator->sort('File'); ?>Paginator->sort('Line'); ?>
         + Html->link(__('View'), array('action' => 'view', $log['Log']['TimeKey'])); ?> + Html->link(__('Edit'), array('action' => 'edit', $log['Log']['TimeKey'])); ?> + Form->postLink(__('Delete'), array('action' => 'delete', $log['Log']['TimeKey']), array(), __('Are you sure you want to delete # %s?', $log['Log']['TimeKey'])); ?> +
+

+ Paginator->counter(array( + 'format' => __('Page {:page} of {:pages}, showing {:current} records out of {:count} total, starting on record {:start}, ending on {:end}') + )); + ?>

+
+ Paginator->prev('< ' . __('previous'), array(), null, array('class' => 'prev disabled')); + echo $this->Paginator->numbers(array('separator' => '')); + echo $this->Paginator->next(__('next') . ' >', array(), null, array('class' => 'next disabled')); + ?> +
+
+
+

+
    +
  • Html->link(__('New Log'), array('action' => 'add')); ?>
  • +
+
diff --git a/web/api/app/View/Logs/view.ctp b/web/api/app/View/Logs/view.ctp new file mode 100644 index 000000000..7f0b8f15a --- /dev/null +++ b/web/api/app/View/Logs/view.ctp @@ -0,0 +1,54 @@ +
+

+
+
+
+ +   +
+
+
+ +   +
+
+
+ +   +
+
+
+ +   +
+
+
+ +   +
+
+
+ +   +
+
+
+ +   +
+
+
+ +   +
+
+
+
+

+
    +
  • Html->link(__('Edit Log'), array('action' => 'edit', $log['Log']['TimeKey'])); ?>
  • +
  • Form->postLink(__('Delete Log'), array('action' => 'delete', $log['Log']['TimeKey']), null, __('Are you sure you want to delete # %s?', $log['Log']['TimeKey'])); ?>
  • +
  • Html->link(__('List Logs'), array('action' => 'index')); ?>
  • +
  • Html->link(__('New Log'), array('action' => 'add')); ?>
  • +
+