Commit 8177e5eb authored by Andrey Filippov's avatar Andrey Filippov

Merge branch 'master' of github.com:Elphel/elphel-apps-camogm

parents 49435a6f 569ab463
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<projectDescription> <projectDescription>
<name>camogm</name> <name>elphel-apps-camogm</name>
<comment></comment> <comment></comment>
<projects> <projects>
</projects> </projects>
......
GUIDIR = camogmgui
PROGS = camogm PROGS = camogm
PHPSCRIPTS = camogmstate.php PHPSCRIPTS = camogmstate.php $(GUIDIR)/camogmgui.php $(GUIDIR)/camogmgui.css $(GUIDIR)/camogmgui.js $(GUIDIR)/camogm_interface.php \
$(GUIDIR)/SpryTabbedPanels.css $(GUIDIR)/SpryTabbedPanels.js $(GUIDIR)/xml_simple.php $(GUIDIR)/SpryCollapsiblePanel.css \
$(GUIDIR)/SpryCollapsiblePanel.js
CONFIGS = qt_source CONFIGS = qt_source
IMAGES = $(GUIDIR)/images/filebrowser-01.gif $(GUIDIR)/images/filebrowser-bottom-01.gif $(GUIDIR)/images/png_white_30.png \
$(GUIDIR)/images/record.gif $(GUIDIR)/images/reload.png $(GUIDIR)/images/stop.gif $(GUIDIR)/images/create_folder.png \
$(GUIDIR)/images/divider.png $(GUIDIR)/images/folder.gif $(GUIDIR)/images/help.png $(GUIDIR)/images/quicktime.png \
$(GUIDIR)/images/rec_folder.png $(GUIDIR)/images/up_folder.gif $(GUIDIR)/images/play_audio.png $(GUIDIR)/images/hdd.png
SRCS = camogm.c camogm_ogm.c camogm_jpeg.c camogm_mov.c camogm_kml.c camogm_read.c index_list.c SRCS = camogm.c camogm_ogm.c camogm_jpeg.c camogm_mov.c camogm_kml.c camogm_read.c index_list.c
OBJS = $(SRCS:.c=.o) OBJS = $(SRCS:.c=.o)
...@@ -16,6 +24,7 @@ OWN = -o root -g root ...@@ -16,6 +24,7 @@ OWN = -o root -g root
SYSCONFDIR = /etc/ SYSCONFDIR = /etc/
BINDIR = /usr/bin/ BINDIR = /usr/bin/
WWW_PAGES = /www/pages WWW_PAGES = /www/pages
IMAGEDIR = $(WWW_PAGES)/images
all: $(PROGS) all: $(PROGS)
...@@ -29,6 +38,9 @@ install: $(PROGS) $(PHPSCRIPTS) $(CONFIGS) ...@@ -29,6 +38,9 @@ install: $(PROGS) $(PHPSCRIPTS) $(CONFIGS)
$(INSTALL) $(OWN) -m $(INSTDOCS) $(CONFIGS) $(DESTDIR)$(SYSCONFDIR) $(INSTALL) $(OWN) -m $(INSTDOCS) $(CONFIGS) $(DESTDIR)$(SYSCONFDIR)
$(INSTALL) $(OWN) -d $(DESTDIR)$(WWW_PAGES) $(INSTALL) $(OWN) -d $(DESTDIR)$(WWW_PAGES)
$(INSTALL) $(OWN) -m $(INSTMODE) $(PHPSCRIPTS) $(DESTDIR)$(WWW_PAGES) $(INSTALL) $(OWN) -m $(INSTMODE) $(PHPSCRIPTS) $(DESTDIR)$(WWW_PAGES)
# install camogmgui
$(INSTALL) $(OWN) -d $(DESTDIR)$(IMAGEDIR)
$(INSTALL) $(OWN) -m $(INSTMODE) $(IMAGES) $(DESTDIR)$(IMAGEDIR)
clean: clean:
rm -rf $(PROGS) *.o *~ rm -rf $(PROGS) *.o *~
......
...@@ -1053,7 +1053,7 @@ void camogm_status(camogm_state *state, char * fn, int xml) ...@@ -1053,7 +1053,7 @@ void camogm_status(camogm_state *state, char * fn, int xml)
" <ignore_fps>\"%s\"</ignore_fps>\n" \ " <ignore_fps>\"%s\"</ignore_fps>\n" \
" <raw_device_path>\"%s\"</raw_device_path>\n" \ " <raw_device_path>\"%s\"</raw_device_path>\n" \
" <raw_device_overruns>%d</raw_device_overruns>\n" \ " <raw_device_overruns>%d</raw_device_overruns>\n" \
" <raw_device_pos_write>0x%llx</raw_dev_pos_write>\n" \ " <raw_device_pos_write>0x%llx</raw_device_pos_write>\n" \
" <raw_device_pos_read>0x%llx (%d%% done)</raw_device_pos_read>\n", " <raw_device_pos_read>0x%llx (%d%% done)</raw_device_pos_read>\n",
_state, state->path, state->frameno, state->start_after_timestamp, _dur, _udur, _len, \ _state, state->path, state->frameno, state->start_after_timestamp, _dur, _udur, _len, \
_frames_skip, _sec_skip, \ _frames_skip, _sec_skip, \
...@@ -1226,11 +1226,9 @@ int parse_cmd(camogm_state *state, FILE* npipe) ...@@ -1226,11 +1226,9 @@ int parse_cmd(camogm_state *state, FILE* npipe)
if (!cmd) return 0; // nothing in the pipe if (!cmd) return 0; // nothing in the pipe
D2(fprintf(debug_file, "Got command: '%s'\n", cmd)); D2(fprintf(debug_file, "Got command: '%s'\n", cmd));
#ifdef DISABLE_CODE
// Acknowledge received command by copying frame number to per-daemon parameter // Acknowledge received command by copying frame number to per-daemon parameter
// GLOBALPARS(state->port_num, G_DAEMON_ERR + lastDaemonBit[state->port_num]) = GLOBALPARS(state->port_num, G_THIS_FRAME); // GLOBALPARS(state->port_num, G_DAEMON_ERR + lastDaemonBit[state->port_num]) = GLOBALPARS(state->port_num, G_THIS_FRAME);
setGValue(state->port_num, G_DAEMON_ERR + lastDaemonBit[state->port_num], getGPValue(state->port_num, G_THIS_FRAME)); setGValue(state->port_num, G_DAEMON_ERR + lastDaemonBit[state->port_num], getGPValue(state->port_num, G_THIS_FRAME));
#endif /* DISABLE_CODE */
args = strpbrk(cmd, "= \t"); args = strpbrk(cmd, "= \t");
// is it just a single word command or does it have parameters? // is it just a single word command or does it have parameters?
if (args) { if (args) {
...@@ -1831,7 +1829,6 @@ int open_files(camogm_state *state) ...@@ -1831,7 +1829,6 @@ int open_files(camogm_state *state)
} }
// now open/mmap file to read sensor/compressor parameters (currently - just free memory in circbuf and compressor state) // now open/mmap file to read sensor/compressor parameters (currently - just free memory in circbuf and compressor state)
#ifdef DISABLE_CODE
state->fd_fparmsall[port] = open(ctlFileNames[port], O_RDWR); state->fd_fparmsall[port] = open(ctlFileNames[port], O_RDWR);
if (state->fd_fparmsall[port] < 0) { // check control OK if (state->fd_fparmsall[port] < 0) { // check control OK
D0(fprintf(debug_file, "%s:%d:%s: Error opening %s\n", __FILE__, __LINE__, __FUNCTION__, ctlFileNames[port])); D0(fprintf(debug_file, "%s:%d:%s: Error opening %s\n", __FILE__, __LINE__, __FUNCTION__, ctlFileNames[port]));
...@@ -1849,7 +1846,6 @@ int open_files(camogm_state *state) ...@@ -1849,7 +1846,6 @@ int open_files(camogm_state *state)
} }
framePars[port] = frameParsAll[port]->framePars; framePars[port] = frameParsAll[port]->framePars;
aglobalPars[port] = frameParsAll[port]->globalPars; aglobalPars[port] = frameParsAll[port]->globalPars;
#endif /* DISABLE_CODE */
} }
return ret; return ret;
...@@ -1928,12 +1924,9 @@ int main(int argc, char *argv[]) ...@@ -1928,12 +1924,9 @@ int main(int argc, char *argv[])
*/ */
unsigned long getGPValue(unsigned int port, unsigned long GPNumber) unsigned long getGPValue(unsigned int port, unsigned long GPNumber)
{ {
#ifdef DISABLE_CODE
return (GPNumber >= FRAMEPAR_GLOBALS) ? return (GPNumber >= FRAMEPAR_GLOBALS) ?
GLOBALPARS(port, GPNumber) : GLOBALPARS(port, GPNumber) :
framePars[port][GLOBALPARS(port, G_THIS_FRAME) & PARS_FRAMES_MASK].pars[GPNumber]; framePars[port][GLOBALPARS(port, G_THIS_FRAME) & PARS_FRAMES_MASK].pars[GPNumber];
#endif /* DESABLE_CODE */
return 0;
} }
/** /**
......
@charset "UTF-8";
/* SpryCollapsiblePanel.css - Revision: Spry Preview Release 1.4 */
/* Copyright (c) 2006. Adobe Systems Incorporated. All rights reserved. */
/* This is the selector for the main CollapsiblePanel container. For our
* default style, the CollapsiblePanel is responsible for drawing the borders
* around the widget.
*
* If you want to constrain the width of the CollapsiblePanel widget, set a width on
* the CollapsiblePanel container. By default, our CollapsiblePanel expands horizontally to fill
* up available space.
*
* The name of the class ("CollapsiblePanel") used in this selector is not necessary
* to make the widget function. You can use any class name you want to style the
* CollapsiblePanel container.
*/
.CollapsiblePanel {
margin: 0px;
padding: 0px;
border-left: solid 1px #CCC;
border-right: solid 1px #999;
border-top: solid 1px #999;
border-bottom: solid 1px #CCC;
}
/* This is the selector for the CollapsiblePanelTab. This container houses
* the title for the panel. This is also the container that the user clicks
* on to open or close the panel.
*
* The name of the class ("CollapsiblePanelTab") used in this selector is not necessary
* to make the widget function. You can use any class name you want to style an
* CollapsiblePanel panel tab container.
*/
.CollapsiblePanelTab {
font: bold 0.7em sans-serif;
background-color: #DDD;
border-bottom: solid 1px #CCC;
margin: 0px;
padding: 2px;
cursor: pointer;
-moz-user-select: none;
-khtml-user-select: none;
}
/* This is the selector for a CollapsiblePanel's Content area. It's important to note that
* you should never put any padding on the content area element if you plan to
* use the CollapsiblePanel's open/close animations. Placing a non-zero padding on the content
* element can cause the CollapsiblePanel to abruptly grow in height while the panels animate.
*
* The name of the class ("CollapsiblePanelContent") used in this selector is not necessary
* to make the widget function. You can use any class name you want to style a
* CollapsiblePanel content container.
*/
.CollapsiblePanelContent {
margin: 0px;
padding: 0px;
}
/* An anchor tag can be used inside of a CollapsiblePanelTab so that the
* keyboard focus ring appears *inside* the tab instead of around the tab.
* This is an example of how to make the text within the anchor tag look
* like non-anchor (normal) text.
*/
.CollapsiblePanelTab a {
color: black;
text-decoration: none;
}
/* This is an example of how to change the appearance of the panel tab that is
* currently open. The class "CollapsiblePanelOpen" is programatically added and removed
* from panels as the user clicks on the tabs within the CollapsiblePanel.
*/
.CollapsiblePanelOpen .CollapsiblePanelTab {
background-color: #EEE;
}
/* This is an example of how to change the appearance of the panel tab as the
* mouse hovers over it. The class "CollapsiblePanelTabHover" is programatically added
* and removed from panel tab containers as the mouse enters and exits the tab container.
*/
.CollapsiblePanelTabHover, .CollapsiblePanelOpen .CollapsiblePanelTabHover {
background-color: #CCC;
}
/* This is an example of how to change the appearance of all the panel tabs when the
* CollapsiblePanel has focus. The "CollapsiblePanelFocused" class is programatically added and removed
* whenever the CollapsiblePanel gains or loses keyboard focus.
*/
.CollapsiblePanelFocused .CollapsiblePanelTab {
background-color: #3399FF;
}
This diff is collapsed.
@charset "UTF-8";
/* SpryTabbedPanels.css - Revision: Spry Preview Release 1.4 */
/* Copyright (c) 2006. Adobe Systems Incorporated. All rights reserved. */
/* Horizontal Tabbed Panels
*
* The default style for a TabbedPanels widget places all tab buttons
* (left aligned) above the content panel.
*/
/* This is the selector for the main TabbedPanels container. For our
* default style, this container does not contribute anything visually,
* but it is floated left to make sure that any floating or clearing done
* with any of its child elements are contained completely within the
* TabbedPanels container, to minimize any impact or undesireable
* interaction with other floated elements on the page that may be used
* for layout.
*
* If you want to constrain the width of the TabbedPanels widget, set a
* width on the TabbedPanels container. By default, the TabbedPanels widget
* expands horizontally to fill up available space.
*
* The name of the class ("TabbedPanels") used in this selector is not
* necessary to make the widget function. You can use any class name you
* want to style the TabbedPanels container.
*/
.TabbedPanels {
margin: 0px;
padding: 0px;
float: left;
clear: none;
width: 100%; /* IE Hack to force proper layout when preceded by a paragraph. (hasLayout Bug)*/
}
/* This is the selector for the TabGroup. The TabGroup container houses
* all of the tab buttons for each tabbed panel in the widget. This container
* does not contribute anything visually to the look of the widget for our
* default style.
*
* The name of the class ("TabbedPanelsTabGroup") used in this selector is not
* necessary to make the widget function. You can use any class name you
* want to style the TabGroup container.
*/
.TabbedPanelsTabGroup {
margin: 0px;
padding: 0px;
}
/* This is the selector for the TabbedPanelsTab. This container houses
* the title for the panel. This is also the tab "button" that the user clicks
* on to activate the corresponding content panel so that it appears on top
* of the other tabbed panels contained in the widget.
*
* For our default style, each tab is positioned relatively 1 pixel down from
* where it wold normally render. This allows each tab to overlap the content
* panel that renders below it. Each tab is rendered with a 1 pixel bottom
* border that has a color that matches the top border of the current content
* panel. This gives the appearance that the tab is being drawn behind the
* content panel.
*
* The name of the class ("TabbedPanelsTab") used in this selector is not
* necessary to make the widget function. You can use any class name you want
* to style this tab container.
*/
.TabbedPanelsTab {
position: relative;
top: 1px;
float: left;
padding: 4px 10px;
margin: 0px 1px 0px 0px;
font: bold 0.7em sans-serif;
background-color: #DDD;
list-style: none;
border-left: solid 1px #CCC;
border-bottom: solid 1px #999;
border-top: solid 1px #999;
border-right: solid 1px #999;
-moz-user-select: none;
-khtml-user-select: none;
cursor: pointer;
}
.TabbedPanelsTabAlert {
position: relative;
top: 1px;
float: left;
padding: 4px 10px;
margin: 0px 1px 0px 0px;
font: bold 0.7em sans-serif;
color:#FF0000;
text-decoration:blink;
list-style: none;
border-left: solid 1px #CCC;
border-bottom: solid 1px #999;
border-top: solid 1px #999;
border-right: solid 1px #999;
-moz-user-select: none;
-khtml-user-select: none;
cursor: pointer;
}
/* This selector is an example of how to change the appearnce of a tab button
* container as the mouse enters it. The class "TabbedPanelsTabHover" is
* programatically added and removed from the tab element as the mouse enters
* and exits the container.
*/
.TabbedPanelsTabHover {
background-color: #CCC;
}
/* This selector is an example of how to change the appearance of a tab button
* container after the user has clicked on it to activate a content panel.
* The class "TabbedPanelsTabSelected" is programatically added and removed
* from the tab element as the user clicks on the tab button containers in
* the widget.
*
* As mentioned above, for our default style, tab buttons are positioned
* 1 pixel down from where it would normally render. When the tab button is
* selected, we change its bottom border to match the background color of the
* content panel so that it looks like the tab is part of the content panel.
*/
.TabbedPanelsTabSelected {
background-color: #EEE;
border-bottom: 1px solid #EEE;
}
/* This selector is an example of how to make a link inside of a tab button
* look like normal text. Users may want to use links inside of a tab button
* so that when it gets focus, the text *inside* the tab button gets a focus
* ring around it, instead of the focus ring around the entire tab.
*/
.TabbedPanelsTab a {
color: black;
text-decoration: none;
}
/* This is the selector for the ContentGroup. The ContentGroup container houses
* all of the content panels for each tabbed panel in the widget. For our
* default style, this container provides the background color and borders that
* surround the content.
*
* The name of the class ("TabbedPanelsContentGroup") used in this selector is
* not necessary to make the widget function. You can use any class name you
* want to style the ContentGroup container.
*/
.TabbedPanelsContentGroup {
clear: both;
border-left: solid 1px #CCC;
border-bottom: solid 1px #CCC;
border-top: solid 1px #999;
border-right: solid 1px #999;
background-color: #EEE;
}
/* This is the selector for the Content panel. The Content panel holds the
* content for a single tabbed panel. For our default style, this container
* provides some padding, so that the content is not pushed up against the
* widget borders.
*
* The name of the class ("TabbedPanelsContent") used in this selector is
* not necessary to make the widget function. You can use any class name you
* want to style the Content container.
*/
.TabbedPanelsContent {
padding: 4px;
margin:2px;
}
/* This selector is an example of how to change the appearnce of the currently
* active container panel. The class "TabbedPanelsContentVisible" is
* programatically added and removed from the content element as the panel
* is activated/deactivated.
*/
.TabbedPanelsContentVisible {
}
/* Vertical Tabbed Panels
*
* The following rules override some of the default rules above so that the
* TabbedPanels widget renders with its tab buttons along the left side of
* the currently active content panel.
*
* With the rules defined below, the only change that will have to be made
* to switch a horizontal tabbed panels widget to a vertical tabbed panels
* widget, is to use the "VTabbedPanels" class on the top-level widget
* container element, instead of "TabbedPanels".
*/
/* This selector floats the TabGroup so that the tab buttons it contains
* render to the left of the active content panel. A border is drawn around
* the group container to make it look like a list container.
*/
.VTabbedPanels .TabbedPanelsTabGroup {
float: left;
width: 10em;
height: 20em;
background-color: #EEE;
position: relative;
border-top: solid 1px #999;
border-right: solid 1px #999;
border-left: solid 1px #CCC;
border-bottom: solid 1px #CCC;
}
/* This selector disables the float property that is placed on each tab button
* by the default TabbedPanelsTab selector rule above. It also draws a bottom
* border for the tab. The tab button will get its left and right border from
* the TabGroup, and its top border from the TabGroup or tab button above it.
*/
.VTabbedPanels .TabbedPanelsTab {
float: none;
margin: 0px;
border-top: none;
border-left: none;
border-right: none;
}
/* This selector disables the float property that is placed on each tab button
* by the default TabbedPanelsTab selector rule above. It also draws a bottom
* border for the tab. The tab button will get its left and right border from
* the TabGroup, and its top border from the TabGroup or tab button above it.
*/
.VTabbedPanels .TabbedPanelsTabSelected {
background-color: #EEE;
border-bottom: solid 1px #999;
}
/* This selector floats the content panels for the widget so that they
* render to the right of the tabbed buttons.
*/
.VTabbedPanels .TabbedPanelsContentGroup {
clear: none;
float: left;
padding: 0px;
width: 30em;
height: 20em;
}
This diff is collapsed.
This diff is collapsed.
html {
font-family: Helvetica, Arial, sans-serif;
font-size: 12px;
font-style: normal;
text-decoration: none;
border: 0px;
background-color:#f9fcfc;
}
table td {
font-size: 12px;
}
body {
margin:10px;
}
a {
color:#09284a;
}
a:hover {
color:#09708a;
}
#help_link a{
float:right;
display:inline;
text-transform:capitalize;
letter-spacing:3px;
color:#000066;
margin-right:8px;
text-decoration:none;
font-weight:bold;
}
#sitecoloumn {
background-color:#F4F4F2;
border:1px solid #AFACAC;
margin-left:auto;
margin-right:auto;
position:relative;
padding-bottom:5px;
top:5px;
width:950px;
height:auto;
}
#header {
font-size:14px;
font-weight:bold;
color:#000;
margin:3px;
text-align:center;
}
.small {
font-size:10px;
color:#888;
}
img {
border:0;
}
#live-image {
text-align:center;
padding:2px;
margin:3px;
}
#live-image-header {
background-color:#efece7;
border:solid 1px #eee;
font-size:9px;
border-bottom:solid 1px #aaa;
}
#live-image-header td {
font-size:9px;
}
#live-image-header a {
color:#000;
text-decoration:none;
font-size:9px;
}
#live-image-header a:hover {
color:#000;
font-size:9px;
background-image:url(images/png_white_30.png);
background-repeat:repeat;
padding:2px;
left:-3px;
position:relative;
border:solid 1px #3A3A3A;
text-decoration:none;
}
#files {
border:1px;
border-style: solid;
padding:0px;
width:500px;
left:5px;
height:372px;
position:relative;
background-color:#f2f7fd;
}
#filelist {
width:500px;
top:26px;
height:320px;
position:absolute;
overflow:auto;
}
#files_header {
background-image:url(images/filebrowser-01.gif);
background-repeat:repeat-x;
height:25px;
color:#FFFFFF;
padding:3px;
}
#files_footer {
padding:5px;
height:25px;
bottom:-10px;
position:absolute;
width:490px;
color:#ffffff;
background-image:url(images/filebrowser-bottom-01.gif);
background-repeat:repeat-x;
}
#files_current_folder {
color:#ffffff;
right:10px;
position:absolute;
}
.file_row_even {
background-color:#EAEDF2;
}
.file_row_odd {
background-color:#D8DBE2;
}
#file_browser_commands {
position:absolute;
padding:2px;
right:-120px;
top:0px;
width:430px;
height:30px;
}
#file_browser_commands a {
color:#FFFFFF;
text-decoration:none;
}
#file_browser_commands a:hover {
color:#000;
background-image:url(images/png_white_30.png);
background-repeat:repeat;
padding:2px;
left:-3px;
position:relative;
border:solid 1px #3A3A3A;
text-decoration:none;
}
#TabbedPanels1 {
width:422px;
}
#record a{
position:absolute;
width:410px;
text-decoration:none;
font-weight:bold;
height:30px;
background:#b50000;
color:#FFFFFF;
text-align:center;
padding:5px;
border:2px outset #fff;
}
#record a:hover{
background:#980000;
}
.alert {
color: red;
}
.green {
color:#009900;
}
table.state_table {
color:#999999;
width:380px;
margin: 0px;
padding: 0px;
border-width: 0px;
border-spacing: 0px;
border-style: solid solid solid solid;
border-color: gray gray gray gray;
border-collapse:collapse;
}
table.state_table td {
border-width: 0px;
padding: 2px 2px 2px 2px;
border-style: solid solid solid solid;
border-color: black black black black;
-moz-border-radius: 0px 0px 0px 0px;
}
#advanced_name_panel {
}
#buffer_toggle {
position:absolute;
right:30px;
padding-right:40px;
}
#buffer_bar {
right:50px;
margin-right:8px;
width:340px;
height:15px;
border:1px solid #0066FF;
position:absolute;
padding:1px;
}
#buffer_free {
background-color:#009900;
margin-left:5px;
height:15px;
position:absolute;
width:260px;
display:inline;
float:left;
text-align:center;
color:#FFFFFF;
letter-spacing:3px;
}
#buffer_used {
background-color:#CC0000;
height:15px;
position:absolute;
width:40px;
display:inline;
float:right;
right:1px;
text-align:center;
color:#FFFFFF;
letter-spacing:3px;
}
#ajax_devices {
border:solid 1px #444;
background-color:white;
}
.sensor_ports * {
vertical-align: middle;
margin-left: 5px;
margin-right: 5px;
margin-top: 0px;
margin-bottom: 0px;
}
#live_image_auto_update_frequency {
height: 18px;
font-size: 9px;
margin: 0px;
padding: 0px;
}
#live_image_auto_update {
margin: 0px;
padding: 0px;
}
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
<?
/* xml-simple.php
Simple XML Parser for PHP by Rogers Cadenhead, derived from
original code by Jim Winstead Jr.
Version 1.01
Web: http://www.cadenhead.org/workbench/xml-simple
Copyright (C) 2005 Rogers Cadenhead
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
if (__FILE__ == $PATH_TRANSLATED) {
header("Status: 403 Forbidden");
exit();
}
// a PHP class library that parses XML data
class xml_simple {
/* an array that holds parsed XML data as either name-value pairs (for character data) or arrays (for subelements) */
var $tree = array();
var $force_to_array = array();
// a descriptive error message, if the class fails to execute successfully
var $error = null;
// Create the XML parser that will read XML data formatted with the specified encoding
function xml_simple($encoding = 'UTF-8') {
$this->parser = xml_parser_create($encoding);
xml_set_object($this->parser, $this);
xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, 0);
xml_parser_set_option($this->parser, XML_OPTION_SKIP_WHITE, 1);
xml_parser_set_option($this->parser, XML_OPTION_TARGET_ENCODING, 'UTF-8');
xml_set_element_handler($this->parser, "start_element", "stop_element");
xml_set_character_data_handler($this->parser, "char_data");
}
function force_to_array() {
for ($i = 0; $i < func_num_args(); $i++) {
$this->force_to_array[] = func_get_arg($i);
}
}
/* Parse XML data, storing it in the instance variable; returns false if the data cannot be parsed. */
function parse($data) {
$this->tree = array();
if (!xml_parse($this->parser, $data, 1)) {
$this->error = "xml parse error: " .
xml_error_string(xml_get_error_code($this->parser)) .
" on line ".xml_get_current_line_number($this->parser);
return false;
}
return $this->tree[0]["content"];
}
function parse_file($file) {
$fp = @fopen($file, "r");
if (!$fp) {
user_error("unable to open file: '$file'");
return false;
}
while ($data = fread($fp, 4096)) {
if (!xml_parse($this->parser, $data, feof($fp))) {
user_error("xml parse error: " .
xml_error_string(xml_get_error_code($this->parser)) .
" on line " . xml_get_current_line_number($this->parser));
}
}
fclose($fp);
return $this->tree[0]["content"];
}
function encode_as_xml($value) {
if (is_array($value)) {
reset($value); $out = '';
while (list($key,$val) = each($value)) {
if (is_array($val) && isset($val[0])) {
reset($val);
while (list(,$item) = each($val)) {
$out .= "<$key>".xml_simple::encode_as_xml($item)."</$key>";
}
} else {
$out .= "<$key>".xml_simple::encode_as_xml($val)."</$key>";
}
}
return $out;
} else {
return htmlspecialchars($value);
}
}
function start_element($parser, $name, $attrs) {
array_unshift($this->tree, array("name" => $name));
}
function stop_element($parser, $name) {
if ($name != $this->tree[0]["name"]) die("incorrect nesting");
if (count($this->tree) > 1) {
$elem = array_shift($this->tree);
if (isset($this->tree[0]["content"][$elem["name"]])) {
if (is_array($this->tree[0]["content"][$elem["name"]]) && isset($this->tree[0]["content"][$elem["name"]][0])) {
array_push($this->tree[0]["content"][$elem["name"]], $elem["content"]);
} else {
$this->tree[0]["content"][$elem["name"]] =
array($this->tree[0]["content"][$elem["name"]],$elem["content"]);
}
} else {
if (in_array($elem["name"],$this->force_to_array)) {
$this->tree[0]["content"][$elem["name"]] = array($elem["content"]);
} else {
if (!isset($elem["content"])) $elem["content"] = "";
$this->tree[0]["content"][$elem["name"]] = $elem["content"];
}
}
}
}
function char_data($parser, $data) {
# don't add a string to non-string data
if (!is_string($this->tree[0]["content"]) && !preg_match("/\\S/", $data)) return;
$this->tree[0]["content"] .= $data;
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment