View | Details | Raw Unified | Return to bug 194859 | Differences between
and this patch

Collapse All | Expand All

(-)b/net-mgmt/pandorafms_agent/Makefile (+1 lines)
Lines 40-45 post-patch: Link Here
40
40
41
post-install:
41
post-install:
42
	@${RM} -f ${STAGEDIR}${LOGDIR}/pandora_agent.log
42
	@${RM} -f ${STAGEDIR}${LOGDIR}/pandora_agent.log
43
	@${RM} -f ${STAGEDIR}${DATADIR}/collections/.empty
43
	@${MKDIR} ${STAGEDIR}${DOCSDIR}
44
	@${MKDIR} ${STAGEDIR}${DOCSDIR}
44
.for x in ${PORTDOCS}
45
.for x in ${PORTDOCS}
45
	${INSTALL_DATA} ${WRKSRC}/${x} ${STAGEDIR}${DOCSDIR}
46
	${INSTALL_DATA} ${WRKSRC}/${x} ${STAGEDIR}${DOCSDIR}
(-)b/net-mgmt/pandorafms_agent/distinfo (-2 / +2 lines)
Lines 1-2 Link Here
1
SHA256 (pandora/pandorafms_agent_unix-5.1.tar.gz) = 9d487573716c088a5121fbb89456000bd39226dbb317ed2d88970f46d4b2bc34
1
SHA256 (pandora/pandorafms_agent_unix-5.1SP1.tar.gz) = b4e4363784a133d4679bdab22c977177ccebc9758e9b6f051d15a7a6a81a7a95
2
SIZE (pandora/pandorafms_agent_unix-5.1.tar.gz) = 86100
2
SIZE (pandora/pandorafms_agent_unix-5.1SP1.tar.gz) = 80277
(-)a/net-mgmt/pandorafms_agent/files/patch-update (-1288 lines)
Removed Link Here
1
Index: ChangeLog
2
===================================================================
3
--- ChangeLog	(revision 10314)
4
+++ ChangeLog	(working copy)
5
@@ -1,3 +1,33 @@
6
+2014-08-14  Koichiro Kikuchi <koichiro@rworks.jp>
7
+
8
+	* pandora_agent_installer: Fixed symlink source path.
9
+
10
+2014-08-13  Koichiro Kikuchi <koichiro@rworks.jp>
11
+
12
+	* FreeBSD/pandora_agent: Small fixes: use proper rc variables,
13
+	 remove obsolete function "set_rcvar" call and use "daemon" command
14
+	 to start pandora_agent.
15
+
16
+	* pandora_agent_installer: Refactored implementation and added
17
+	 "fakeroot" installation support.
18
+
19
+	* plugins/who.sh: Converted to bourne shell script.
20
+
21
+	* pandora_agent_daemon: Small bug fixes and refactorings.
22
+
23
+2014-08-12  Ramon Novoa  <rnovoa@artica.es>
24
+
25
+	* pandora_agent: Fixed to make the 'Command Snapshot' feature work.
26
+
27
+2014-08-12  Ramon Novoa  <rnovoa@artica.es>
28
+
29
+	* pandora_agent: Trim leading and trailing whitespaces from module names
30
+	  (like policies and windows agents do).
31
+
32
+2014-08-07  Ramon Novoa  <rnovoa@artica.es>
33
+
34
+	* pandora_agent_daemon: Fixes the ps call on HP-UX.
35
+
36
 2014-06-04  Koichiro KIKUCHI <koichiro@rworks.jp>
37
 
38
 	* pandora_agent: Allow spaces in module group names.
39
Index: pandora_agent_installer
40
===================================================================
41
--- pandora_agent_installer	(revision 10314)
42
+++ pandora_agent_installer	(working copy)
43
@@ -15,49 +15,79 @@
44
 
45
 FORCE=0
46
 LOG_TIMESTAMP=`date +"%Y/%m/%d %H:%M:%S"`
47
-PANDORA_HOME=/usr/share/pandora_agent
48
-PANDORA_BIN=/usr/bin/pandora_agent
49
-PANDORA_EXEC_BIN=/usr/bin/pandora_agent_exec
50
-PANDORA_REVENT_BIN=/usr/bin/pandora_revent
51
+
52
+PREFIX=/usr
53
+if [ "$OS_NAME" = "FreeBSD" ] || [ "$OS_NAME" = "NetBSD" ]
54
+then
55
+	PREFIX=/usr/local
56
+fi
57
+PANDORA_HOME=$PREFIX/share/pandora_agent
58
+PANDORA_BIN=$PREFIX/bin/pandora_agent
59
+PANDORA_EXEC_BIN=$PREFIX/bin/pandora_agent_exec
60
+PANDORA_REVENT_BIN=$PREFIX/bin/pandora_revent
61
 PANDORA_TEMP=/var/spool/pandora
62
 PANDORA_CFG=/etc/pandora
63
 PANDORA_LOG_DIR=/var/log/pandora
64
 PANDORA_LOG=pandora_agent.log
65
-TENTACLE=/usr/bin/tentacle_client
66
-TENTACLE_SERVER=/usr/bin/tentacle_server
67
-PANDORA_MAN=/usr/share/man
68
+TENTACLE=$PREFIX/bin/tentacle_client
69
+TENTACLE_SERVER=$PREFIX/bin/tentacle_server
70
+PANDORA_MAN=$PREFIX/share/man
71
+PANDORA_STARTUP=/etc/init.d/pandora_agent_daemon
72
+DAEMON_SCRIPT=pandora_agent_daemon
73
+PANDORA_USER="root"
74
+PANDORA_PERL_PATH="perl"
75
+WITHOUT_TENTACLE_SERVER=0
76
+FAKEROOT=0
77
 
78
+# defaults for each platforms
79
+case $OS_NAME in
80
+AIX)
81
+    PANDORA_STARTUP=/etc/rc.pandora_agent_daemon
82
+	;;
83
+HP-UX)
84
+	PANDORA_STARTUP=/sbin/init.d/pandora_agent_daemon
85
+	;;
86
+FreeBSD)
87
+	PANDORA_CFG=$PREFIX/etc/pandora
88
+	PANDORA_MAN=$PREFIX/man
89
+	PANDORA_STARTUP=$PREFIX/etc/rc.d/pandora_agent
90
+	DAEMON_SCRIPT=$OS_NAME/pandora_agent
91
+	PANDORA_PERL_PATH=/usr/local/bin/perl
92
+	;;
93
+NetBSD)
94
+	PANDORA_CFG=/usr/local/etc/pandora
95
+	PANDORA_STARTUP=/etc/rc.d/pandora_agent
96
+	DAEMON_SCRIPT=$OS_NAME/pandora_agent
97
+	PANDORA_PERL_PATH=/usr/pkg/bin/perl
98
+	;;
99
+esac
100
+
101
 MODE=$1
102
-PANDORA_BASE=`echo $2 | sed -e 's/\/$//'`
103
+
104
+# options
105
+while :
106
+do
107
+	case "$2" in 
108
+	"--no-tentacle-server") WITHOUT_TENTACLE_SERVER=1;;
109
+	"--fakeroot") FAKEROOT=1;;
110
+	*) break;;
111
+	esac
112
+	shift
113
+done
114
+
115
+PANDORA_BASE=`echo $2 | sed -e 's|/$||'`
116
 if [ "$3" != "" ]
117
 then
118
 	PANDORA_USER=$3
119
-	if [ "$PANDORA_BASE" = "" ]
120
+	if [ -z "$PANDORA_BASE" ]
121
 	then
122
 		echo "When specifying a custom user the agent must be installed to a custom location where that user has write permissions!"
123
 		exit 1
124
 	fi
125
-else
126
-	PANDORA_USER="root"
127
 fi
128
 
129
-if [ "$4" != "" ]
130
-then
131
-	PANDORA_PERL_PATH=$4
132
-	echo $PANDORA_PERL_PATH > PANDORA_PERL_PATH.temp
133
-        sed 's/\//\\\//g' PANDORA_PERL_PATH.temp > PANDORA_PERL_PATH.temp2
134
+[ "$4" ] && PANDORA_PERL_PATH=$4
135
 
136
-        PANDORA_PERL_DECODED_PATH=`cat PANDORA_PERL_PATH.temp2`
137
-        rm PANDORA_PERL_PATH.temp PANDORA_PERL_PATH.temp2
138
-	#PANDORA_PERL_DECODED_PATH=`echo $PANDORA_PERL_PATH | sed -e "s.\/.\\\\\/.g"`
139
-else
140
-	PANDORA_PERL_PATH="perl"
141
-	if [ "$OS_NAME" = "NetBSD" ]
142
-	then
143
-		PANDORA_PERL_DECODED_PATH="/usr/pkg/bin/perl"
144
-	fi
145
-fi
146
-
147
 # Check for Perl 5.6.x or higher available
148
 PERL_VERSION=`$PANDORA_PERL_PATH -v | egrep 'v5.6|v5.7|v5.8|v5.9|v5.1[0-9]' | grep perl`
149
 
150
@@ -69,17 +99,16 @@
151
 	exit 2
152
 fi
153
 
154
-UNIX_KIND=`uname -s`
155
-if [ -z "`echo Linux HP-UX SunOS AIX Solaris Darwin BSD bsd FreeBSD NetBSD | grep \"$UNIX_KIND\"`" ]
156
+if [ -z "`echo Linux HP-UX SunOS AIX Solaris Darwin BSD bsd FreeBSD NetBSD | grep \"$OS_NAME\"`" ]
157
 then
158
-	echo "This system: '$UNIX_KIND' is not supported by this script"
159
+	echo "This system: '$OS_NAME' is not supported by this script"
160
 	echo "Please make the install yourself as it's described in documentation"
161
 	exit 1
162
 fi
163
 
164
 
165
 # check for root to do the install
166
-if [ -z "`id | grep \"uid=0(root)\"`" ]
167
+if [ $FAKEROOT -ne 1 ] && [ -z "`id | grep \"uid=0(root)\"`" ]
168
 then
169
 	echo "You need to be root to do the install. Please made a manual install"
170
 	echo "if you want to install Pandora FMS agent without root"
171
@@ -91,7 +120,7 @@
172
 help () {
173
 	echo "Syntax":
174
 	echo " "
175
-	echo "    ./pandora_agent_installer < --mode > [ destination_path ] [ user_to_run_as ] [custom_perl_path]"
176
+	echo "    ./pandora_agent_installer < --mode > [ --option ] [ destination_path ] [ user_to_run_as ] [custom_perl_path]"
177
 	echo " "
178
 	echo "Modes:"
179
 	echo " "
180
@@ -99,6 +128,11 @@
181
 	echo "  --install            To install Pandora FMS Agent on this system"
182
 	echo "  --uninstall          To uninstall/remove Pandora FMS Agent on this System"
183
 	echo " "	
184
+	echo "Option:"
185
+	echo " "
186
+	echo "  --no-tentacle-server  Skip tentacle server installation (by default tentalce server installed)"
187
+	echo "  --fakeroot            treate \"destination_path\" as root directory"
188
+	echo " "
189
 	echo "Some exaples of how to use the installer:"
190
 	echo " "
191
 	echo "   ./pandora_agent_installer --install"
192
@@ -110,38 +144,12 @@
193
 }
194
 
195
 uninstall () {
196
-	OS_NAME=`uname -s`
197
-
198
 	if [ "$OS_NAME" = "Darwin" ]
199
         then
200
 		launchctl remove com.pandorafms.pandorafms 
201
 		rm /Library/LaunchDaemons/com.pandorafms.pandorafms.plist 2> /dev/null
202
 	fi
203
 
204
-
205
-	if [ "$OS_NAME" = "FreeBSD" ]
206
-	then
207
-		PANDORA_HOME=/usr/local/share/pandora_agent
208
-		PANDORA_BIN=/usr/local/bin/pandora_agent
209
-		PANDORA_EXEC_BIN=/usr/local/bin/pandora_agent_exec
210
-		PANDORA_REVENT_BIN=/usr/local/bin/pandora_revent
211
-		PANDORA_CFG=/usr/local/etc/pandora
212
-		TENTACLE=/usr/local/bin/tentacle_client
213
-		TENTACLE_SERVER=/usr/local/bin/tentacle_server
214
-		PANDORA_MAN=/usr/local/man
215
-	fi
216
-	if [ "$OS_NAME" = "NetBSD" ]
217
-	then
218
-		PANDORA_HOME=/usr/local/share/pandora_agent
219
-		PANDORA_BIN=/usr/local/bin/pandora_agent
220
-		PANDORA_EXEC_BIN=/usr/local/bin/pandora_agent_exec
221
-		PANDORA_REVENT_BIN=/usr/local/bin/pandora_revent
222
-		PANDORA_CFG=/usr/local/etc/pandora
223
-		TENTACLE=/usr/local/bin/tentacle_client
224
-		TENTACLE_SERVER=/usr/local/bin/tentacle_server
225
-		PANDORA_MAN=/usr/share/man
226
-	fi
227
-
228
 	echo "Removing Pandora FMS Agent..."
229
 	rm -Rf $PANDORA_BASE$PANDORA_BIN 2> /dev/null
230
 	rm -Rf $PANDORA_BASE$PANDORA_EXEC_BIN 2> /dev/null
231
@@ -168,16 +176,19 @@
232
 	rm -Rf $PANDORA_BASE/etc/rc.d/rc?.d/S90pandora_agent_daemon 2> /dev/null
233
 	rm -Rf $PANDORA_BASE/etc/rc.d/rc?.d/S90pandora_agent 2> /dev/null
234
 	rm -Rf $PANDORA_BASE/usr/local/etc/rc.d/pandora_agent 2> /dev/null
235
-	rm -Rf /etc/init.d/pandora_agent_daemon 2> /dev/null
236
-	rm -Rf /sbin/init.d/pandora_agent_daemon 2> /dev/null
237
-	rm -Rf /etc/rc.pandora_agent_daemon 2> /dev/null
238
-	rm -Rf /etc/rc?.d/S90pandora_agent_daemon 2> /dev/null
239
-	rm -Rf /sbin/rc?.d/S90pandora_agent_daemon 2> /dev/null
240
-	rm -Rf /etc/rc?.d/S90pandora_agent 2> /dev/null
241
-	rm -Rf /sbin/rc?.d/S90pandora_agent 2> /dev/null
242
-	rm -Rf /etc/rc.d/rc?.d/S90pandora_agent_daemon 2> /dev/null
243
-	rm -Rf /etc/rc.d/rc?.d/S90pandora_agent 2> /dev/null
244
-	rm -Rf /usr/local/etc/rc.d/pandora_agent 2> /dev/null
245
+	if [ $FAKEROOT -ne 1 ]
246
+	then
247
+		rm -Rf /etc/init.d/pandora_agent_daemon 2> /dev/null
248
+		rm -Rf /sbin/init.d/pandora_agent_daemon 2> /dev/null
249
+		rm -Rf /etc/rc.pandora_agent_daemon 2> /dev/null
250
+		rm -Rf /etc/rc?.d/S90pandora_agent_daemon 2> /dev/null
251
+		rm -Rf /sbin/rc?.d/S90pandora_agent_daemon 2> /dev/null
252
+		rm -Rf /etc/rc?.d/S90pandora_agent 2> /dev/null
253
+		rm -Rf /sbin/rc?.d/S90pandora_agent 2> /dev/null
254
+		rm -Rf /etc/rc.d/rc?.d/S90pandora_agent_daemon 2> /dev/null
255
+		rm -Rf /etc/rc.d/rc?.d/S90pandora_agent 2> /dev/null
256
+		rm -Rf /usr/local/etc/rc.d/pandora_agent 2> /dev/null
257
+	fi
258
 	
259
 	rm -Rf $PANDORA_BASE$PANDORA_HOME 2> /dev/null
260
 	rm -Rf $PANDORA_BASE$PANDORA_LOG_DIR 2> /dev/null
261
@@ -201,36 +212,48 @@
262
 	echo "Done"
263
 }
264
 
265
-install () {
266
+#
267
+# install_perl_script [OPTIONS] SRCFILE DESTFILE
268
+#	Install perl script. If PANDORA_PERL_DECODED_PATH is set, path of the perl
269
+#	in shebang line is replaced with PANDORA_PERL_DECODED_PATH value.
270
+#	OPTIONS:
271
+#		-o OWNER  owner of the installed script
272
+#		-g GROUP  group of the installed script
273
+#		-m PREM   mode of the installed script
274
+#
275
+install_perl_script () {
276
+	OWNER=""; GROUP=""; PERM=""
277
+	while :
278
+	do
279
+		case $1 in
280
+		-o) OWNER=$2;;
281
+		-g) GROUP=$2;;
282
+		-m) PERM=$2;;
283
+		*)  break;;
284
+		esac
285
+		shift;shift
286
+	done
287
+	SRC="$1"
288
+	DEST="$2"
289
 
290
-	OS_VERSION=`uname -r`
291
-	OS_NAME=`uname -s`
292
-	OLDFILENAMETMP=`date +"%Y-%m-%d"`
293
-
294
-	if [ "$OS_NAME" = "FreeBSD" ]
295
+	# do install
296
+	if echo $PANDORA_PERL_PATH | grep "/" > /dev/null && [ "$PANDORA_PERL_PATH" != "/usr/bin/perl" ]
297
 	then
298
-		PANDORA_HOME=/usr/local/share/pandora_agent
299
-		PANDORA_BIN=/usr/local/bin/pandora_agent
300
-		PANDORA_EXEC_BIN=/usr/local/bin/pandora_agent_exec
301
-		PANDORA_REVENT_BIN=/usr/local/bin/pandora_revent
302
-		PANDORA_CFG=/usr/local/etc/pandora
303
-		TENTACLE=/usr/local/bin/tentacle_client
304
-		TENTACLE_SERVER=/usr/local/bin/tentacle_server
305
-		PANDORA_MAN=/usr/local/man
306
+		sed -e "s:^#\!.*:#\!$PANDORA_PERL_PATH:g" $SRC > $DEST
307
+	else
308
+		cp $SRC $DEST
309
 	fi
310
 
311
-	if [ "$OS_NAME" = "NetBSD" ]
312
-	then
313
-		PANDORA_HOME=/usr/local/share/pandora_agent
314
-		PANDORA_BIN=/usr/local/bin/pandora_agent
315
-		PANDORA_EXEC_BIN=/usr/local/bin/pandora_agent_exec
316
-		PANDORA_REVENT_BIN=/usr/local/bin/pandora_revent
317
-		PANDORA_CFG=/usr/local/etc/pandora
318
-		TENTACLE=/usr/local/bin/tentacle_client
319
-		TENTACLE_SERVER=/usr/local/bin/tentacle_server
320
-		PANDORA_MAN=/usr/share/man
321
-	fi
322
+	# set owner, group and permissions
323
+	[ "$OWNER" ] && chown $OWNER $DEST 2>/dev/null
324
+	[ "$GROUP" ] && chgrp $GROUP $DEST 2>/dev/null
325
+	[ "$PERM"  ] && chmod $PERM  $DEST
326
+}
327
 
328
+install () {
329
+	OS_VERSION=`uname -r`
330
+	OLDFILENAMETMP=`date +"%Y-%m-%d"`
331
+
332
 	echo "Detecting Unix distribution: $OS_NAME version $OS_VERSION"
333
 	if [ -f $PANDORA_BASE$PANDORA_HOME ] && [ "$FORCE" = "0" ]
334
 	then
335
@@ -253,87 +276,49 @@
336
 
337
 	# Alter dynamically the daemon launcher and setup the new path 
338
 	# if PANDORA_BASE is customized.
339
-	if [ ! -z "$PANDORA_BASE" ]
340
+	if [ "$PANDORA_BASE" ] && [ $FAKEROOT -ne 1 ]
341
 	then
342
-		if [ "$OS_NAME" = "FreeBSD" ]
343
-		then
344
-			DAEMON_SCRIPT=FreeBSD/pandora_agent
345
-			DAEMON_TEMP=pandora_agent_daemon_temp
346
-		elif [ "$OS_NAME" = "NetBSD" ]
347
-		then
348
-			DAEMON_SCRIPT=NetBSD/pandora_agent
349
-			DAEMON_TEMP=pandora_agent_daemon_temp
350
-		else
351
-			DAEMON_SCRIPT=pandora_agent_daemon
352
-			DAEMON_TEMP=pandora_agent_daemon_temp
353
-		fi
354
+		DAEMON_TEMP=pandora_agent_daemon_temp
355
 
356
 		# Backup the daemon script
357
-		cp -f "$DAEMON_SCRIPT" "$DAEMON_SCRIPT.bak"
358
+		cp -f "$DAEMON_SCRIPT" "${DAEMON_SCRIPT}.bak"
359
 		
360
 		AGENT_CFG=$OS_NAME/pandora_agent.conf
361
 		AGENT_CFG_TEMP=$OS_NAME/pandora_agent.conf.temp
362
 
363
 		# Backup the configuration file
364
-		cp -f "$AGENT_CFG" "$AGENT_CFG.bak"
365
+		cp -f "$AGENT_CFG" "${AGENT_CFG}.bak"
366
 
367
-		echo $PANDORA_BASE > PANDORA_BASE.temp
368
-		sed 's/\//\\\//g' PANDORA_BASE.temp > PANDORA_BASE.temp2
369
-
370
-		PANDORA_BASE_DECODED=`cat PANDORA_BASE.temp2`
371
-		rm PANDORA_BASE.temp PANDORA_BASE.temp2
372
-
373
-		if [ "$OS_NAME" = "FreeBSD" -o "$OS_NAME" = "NetBSD" ]
374
+		if [ "$OS_NAME" = "FreeBSD" ] || [ "$OS_NAME" = "NetBSD" ]
375
 		then
376
-			sed -e "s/^PATH\=[.]*/PATH\=$PANDORA_BASE_DECODED\/usr\/local\/bin\:/g" $DAEMON_SCRIPT > $DAEMON_TEMP
377
+			sed -e "\|^PATH=|s|=|=$PANDORA_BASE$PREFIX/bin:|" \
378
+				-e "s|/usr/local/etc/pandora|$PANDORA_BASE$PANDORA_CFG|g" \
379
+				-e "s|/usr/local/bin/pandora_agent|$PANDORA_BASE$PANDORA_BIN|g" \
380
+				$DAEMON_SCRIPT > $DAEMON_TEMP
381
 			mv $DAEMON_TEMP $DAEMON_SCRIPT
382
-
383
-			sed -e "s/^command\=[.]*/command\=$PANDORA_BASE_DECODED/g" $DAEMON_SCRIPT > $DAEMON_TEMP
384
-			mv $DAEMON_TEMP $DAEMON_SCRIPT
385
-
386
-			sed -e 's/^command_args\=\"[.]*/command_args\=\"$PANDORA_BASE_DECODED/g' $DAEMON_SCRIPT > $DAEMON_TEMP
387
-			mv $DAEMON_TEMP $DAEMON_SCRIPT
388
-
389
-			sed -e 's/^required_files\=\"[.]*/required_files\=\"$PANDORA_BASE_DECODED/g' $DAEMON_SCRIPT > $DAEMON_TEMP
390
-			mv $DAEMON_TEMP $DAEMON_SCRIPT
391
 		else
392
-			sed -e "s/^PATH\=[.]*/PATH\=$PANDORA_BASE_DECODED\/usr\/bin\:/g" $DAEMON_SCRIPT > $DAEMON_TEMP
393
+			sed -e "\|^PATH=|s|=|=$PANDORA_BASE/usr/bin:|" \
394
+				-e "\|^PANDORA_PATH=|s|=|=$PANDORA_BASE|" \
395
+				-e "\|^LOGFILE=|s|=|=$PANDORA_BASE|" \
396
+				-e "\|^DAEMON=|s|=|=$PANDORA_BASE|" \
397
+				-e "\|^DAEMON_TENTACLE=|s|=|=$PANDORA_BASE|" \
398
+				-e "s/^PANDORA_USER=.*/PANDORA_USER=$PANDORA_USER/"  \
399
+				$DAEMON_SCRIPT > $DAEMON_TEMP
400
 			mv  $DAEMON_TEMP $DAEMON_SCRIPT
401
-
402
-			sed -e "s/^PANDORA_PATH\=[.]*/PANDORA_PATH\=$PANDORA_BASE_DECODED/g"  $DAEMON_SCRIPT > $DAEMON_TEMP
403
-			mv  $DAEMON_TEMP $DAEMON_SCRIPT
404
-
405
-			sed -e "s/^LOGFILE\=[.]*/LOGFILE\=$PANDORA_BASE_DECODED/g"  $DAEMON_SCRIPT > $DAEMON_TEMP
406
-			mv  $DAEMON_TEMP $DAEMON_SCRIPT
407
-
408
-			sed -e "s/^DAEMON\=[.]*/DAEMON\=$PANDORA_BASE_DECODED/g"  $DAEMON_SCRIPT > $DAEMON_TEMP
409
-			mv  $DAEMON_TEMP $DAEMON_SCRIPT
410
-
411
-			sed -e "s/^DAEMON_TENTACLE\=[.]*/DAEMON_TENTACLE\=$PANDORA_BASE_DECODED/g"  $DAEMON_SCRIPT > $DAEMON_TEMP
412
-                        mv  $DAEMON_TEMP $DAEMON_SCRIPT
413
- 
414
-			sed -e "s/^PANDORA_USER\=.*/PANDORA_USER\=$PANDORA_USER/g"  $DAEMON_SCRIPT > $DAEMON_TEMP
415
-			mv  $DAEMON_TEMP $DAEMON_SCRIPT
416
 		fi
417
 
418
-		sed -e "s/^temporal [.]*/temporal $PANDORA_BASE_DECODED/g" $AGENT_CFG > $AGENT_CFG_TEMP
419
+		sed -e "s|^temporal[ 	]*|temporal $PANDORA_BASE|" \
420
+			-e "s|^logfile[ 	]*|logfile $PANDORA_BASE|" \
421
+			$AGENT_CFG > $AGENT_CFG_TEMP
422
 		mv $AGENT_CFG_TEMP $AGENT_CFG
423
-
424
-		sed -e "s/^logfile [.]*/logfile $PANDORA_BASE_DECODED/g" $AGENT_CFG > $AGENT_CFG_TEMP
425
-		mv $AGENT_CFG_TEMP $AGENT_CFG
426
 	fi
427
 	echo "Creating Pandora FMS Agent home directory at $PANDORA_BASE$PANDORA_HOME"
428
-	if [ ! -z "$PANDORA_BASE" ]
429
+	if [ "$PANDORA_BASE" ]
430
 	then
431
 		mkdir -p $PANDORA_BASE 2> /dev/null
432
 		mkdir -p $PANDORA_BASE/var/log 2> /dev/null
433
 		mkdir -p $PANDORA_BASE/$PANDORA_MAN/man1 2> /dev/null
434
-		if [ "$OS_NAME" = "FreeBSD" -o "$OS_NAME" = "NetBSD" ]
435
-		then
436
-			mkdir -p $PANDORA_BASE/usr/local/bin 2> /dev/null
437
-		else
438
-			mkdir -p $PANDORA_BASE/usr/bin 2> /dev/null
439
-		fi
440
+		mkdir -p $PANDORA_BASE$PREFIX/bin 2> /dev/null
441
 	fi
442
 
443
 	mkdir -p $PANDORA_BASE$PANDORA_HOME 2> /dev/null
444
@@ -344,14 +329,14 @@
445
 	mkdir -p $PANDORA_BASE$PANDORA_TEMP/data_out 2> /dev/null
446
 	mkdir -p $PANDORA_BASE$PANDORA_CFG 2> /dev/null
447
 	mkdir -p $PANDORA_BASE$PANDORA_LOG_DIR 2> /dev/null
448
-
449
+	
450
 	# Set the user the agent will run as
451
 	if [ "$PANDORA_USER" != "root" ]
452
 	then
453
 		sed -e "s/.*pandora_user .*/pandora_user $PANDORA_USER/" $AGENT_CFG > $AGENT_CFG_TEMP 2> /dev/null && \
454
-		mv $AGENT_CFG_TEMP $AGENT_CFG
455
+			mv $AGENT_CFG_TEMP $AGENT_CFG
456
 		chmod 755 pandora_agent_daemon
457
-		chown -R $PANDORA_USER $PANDORA_BASE
458
+		chown -R $PANDORA_USER $PANDORA_BASE 2>/dev/null
459
 	fi
460
 
461
 	# Create logfile
462
@@ -365,32 +350,10 @@
463
 
464
 	# Copying agent and securing it
465
 	echo "Copying Pandora FMS Agent to $PANDORA_BASE$PANDORA_BIN..."
466
+	install_perl_script -m 755 -o $PANDORA_USER -g 0 pandora_agent $PANDORA_BASE$PANDORA_BIN
467
+	install_perl_script -m 755 -o $PANDORA_USER -g 0 pandora_agent_exec $PANDORA_BASE$PANDORA_EXEC_BIN
468
+	install_perl_script -m 755 -o $PANDORA_USER -g 0 pandora_revent $PANDORA_BASE$PANDORA_REVENT_BIN
469
 
470
-	if [ "$PANDORA_PERL_DECODED_PATH" != "" ]
471
-	then
472
-        	sed -e "s:^#\!.*:#\!$PANDORA_PERL_DECODED_PATH:g" pandora_agent > $PANDORA_BASE$PANDORA_BIN
473
-	else
474
-        	cp pandora_agent $PANDORA_BASE$PANDORA_BIN
475
-	fi
476
-	chmod 755 $PANDORA_BASE$PANDORA_BIN
477
-	if [ "$PANDORA_PERL_DECODED_PATH" != "" ]
478
-        then
479
-                sed -e "s:^#\!.*:#\!$PANDORA_PERL_DECODED_PATH:g" pandora_agent_exec > $PANDORA_BASE$PANDORA_EXEC_BIN
480
-        else
481
-                cp pandora_agent_exec $PANDORA_BASE$PANDORA_EXEC_BIN
482
-        fi
483
-	chmod 755 $PANDORA_BASE$PANDORA_EXEC_BIN
484
-	if [ "$PANDORA_PERL_DECODED_PATH" != "" ]
485
-        then
486
-                sed -e "s:^#\!.*:#\!$PANDORA_PERL_DECODED_PATH:g" pandora_revent > $PANDORA_BASE$PANDORA_REVENT_BIN
487
-        else
488
-                cp pandora_revent $PANDORA_BASE$PANDORA_REVENT_BIN
489
-        fi
490
-	chmod 755 $PANDORA_BASE$PANDORA_REVENT_BIN
491
-	chown $PANDORA_USER:0 $PANDORA_BASE$PANDORA_BIN
492
-	chown $PANDORA_USER:0 $PANDORA_BASE$PANDORA_EXEC_BIN
493
-	chown $PANDORA_USER:0 $PANDORA_BASE$PANDORA_REVENT_BIN
494
-
495
 	echo "Copying Pandora FMS Agent configuration file to $PANDORA_BASE$PANDORA_CFG/pandora_agent.conf..."
496
 	if [ -f $PANDORA_BASE/$PANDORA_CFG/pandora_agent.conf ]
497
 	then
498
@@ -400,49 +363,36 @@
499
 
500
 	echo "Copying Pandora FMS Agent plugins to $PANDORA_BASE$PANDORA_HOME/plugins..."
501
 
502
-	if [ "$OS_NAME" = "NetBSD" ]
503
-	then
504
-		if [ ! -d $PANDORA_BASE$PANDORA_HOME/plugins ]
505
+	[ -d $PANDORA_BASE$PANDORA_HOME/plugins ] || mkdir -p $PANDORA_BASE$PANDORA_HOME/plugins >/dev/null 2>&1
506
+	for PLUGIN in plugins/*
507
+	do
508
+		if grep '^#!.*/perl' $PLUGIN >/dev/null 2>&1
509
 		then
510
-			mkdir -p $PANDORA_BASE$PANDORA_HOME/plugins
511
+			install_perl_script $PLUGIN $PANDORA_BASE$PANDORA_HOME/$PLUGIN
512
+		else
513
+			cp $PLUGIN $PANDORA_BASE$PANDORA_HOME/plugins
514
 		fi
515
-		for i in `ls -1 plugins`
516
-		do 
517
-			sed s:/usr/bin/perl:/usr/pkg/bin/perl: plugins/$i > plugins/$i.tmp
518
-			cp plugins/$i.tmp $PANDORA_BASE$PANDORA_HOME/plugins/$i
519
-			rm plugins/$i.tmp
520
-		done
521
-	else
522
-		cp -r plugins $PANDORA_BASE$PANDORA_HOME
523
-	fi
524
-
525
+	done
526
 	chmod -R 700 $PANDORA_BASE$PANDORA_HOME/plugins
527
-	ln -s $PANDORA_BASE$PANDORA_HOME/plugins $PANDORA_BASE$PANDORA_CFG
528
 
529
+	PANDORA_BASE_REAL="$PANDORA_BASE"
530
+	[ $FAKEROOT -eq 1 ] && PANDORA_BASE_REAL=""
531
+
532
+	ln -s $PANDORA_BASE_REAL$PANDORA_HOME/plugins $PANDORA_BASE$PANDORA_CFG
533
+
534
 	echo "Copying Pandora FMS Agent collections to $PANDORA_BASE$PANDORA_HOME/collections..."
535
 	cp -r collections $PANDORA_BASE$PANDORA_HOME
536
 	chmod -R 700 $PANDORA_BASE$PANDORA_HOME/collections
537
-	ln -s $PANDORA_BASE$PANDORA_HOME/collections $PANDORA_BASE$PANDORA_CFG
538
+	ln -s $PANDORA_BASE_REAL$PANDORA_HOME/collections $PANDORA_BASE$PANDORA_CFG
539
 	
540
-	echo "Copying tentacle server to $PANDORA_BASE$TENTACLE_SERVER"
541
-	if [ "$PANDORA_PERL_DECODED_PATH" != "" ]
542
-        then
543
-                sed -e "s:^#\!.*:#\!$PANDORA_PERL_DECODED_PATH:g" tentacle_server > $PANDORA_BASE$TENTACLE_SERVER
544
-        else
545
-                cp tentacle_server $PANDORA_BASE$TENTACLE_SERVER
546
-        fi
547
-	chmod 755 $PANDORA_BASE$TENTACLE_SERVER	
548
-	chown $PANDORA_USER:0 $PANDORA_BASE$TENTACLE_SERVER
549
+	if [ $WITHOUT_TENTACLE_SERVER -eq 0 ]
550
+	then
551
+		echo "Copying tentacle server to $PANDORA_BASE$TENTACLE_SERVER"
552
+		install_perl_script -m 755 -o $PANDORA_USER -g 0 tentacle_server $PANDORA_BASE$TENTACLE_SERVER
553
+	fi
554
 	
555
 	echo "Copying tentacle client to $PANDORA_BASE$TENTACLE"
556
-	if [ "$PANDORA_PERL_DECODED_PATH" != "" ]
557
-        then
558
-                sed -e "s:^#\!.*:#\!$PANDORA_PERL_DECODED_PATH:g" tentacle_client > $PANDORA_BASE$TENTACLE
559
-        else
560
-                cp tentacle_client $PANDORA_BASE$TENTACLE
561
-        fi
562
-	chmod 755 $PANDORA_BASE$TENTACLE
563
-	chown $PANDORA_USER:0 $PANDORA_BASE$TENTACLE	
564
+	install_perl_script -m 755 -o $PANDORA_USER -g 0 tentacle_client $PANDORA_BASE$TENTACLE	
565
 
566
 	echo "Installing the Pandora Agent and Tentacle Client manuals"
567
 	cp man/man1/tentacle_client.1.gz $PANDORA_BASE/$PANDORA_MAN/man1
568
@@ -451,14 +401,14 @@
569
 	chmod 644 $PANDORA_BASE/$PANDORA_MAN/man1/pandora_agent.1.gz
570
 
571
 	echo "Setting secure permissions and ownership for all Pandora FMS Agent files..."
572
-	chown -R $PANDORA_USER $PANDORA_BASE$PANDORA_HOME
573
+	chown -R $PANDORA_USER $PANDORA_BASE$PANDORA_HOME  2>/dev/null
574
 	chmod -R 700 $PANDORA_BASE$PANDORA_TEMP/data_out
575
 	chmod 711 $PANDORA_BASE$PANDORA_LOG_DIR
576
 	chmod 640 $PANDORA_BASE$PANDORA_LOG_DIR/$PANDORA_LOG
577
-	chown $PANDORA_USER:0 $PANDORA_BASE$PANDORA_LOG_DIR/$PANDORA_LOG
578
-	if [ "$OS_NAME" = "FreeBSD" -o "$OS_NAME" = "NetBSD" ]
579
+	chown $PANDORA_USER:0 $PANDORA_BASE$PANDORA_LOG_DIR/$PANDORA_LOG  2>/dev/null
580
+	if [ "$OS_NAME" = "FreeBSD" ] || [ "$OS_NAME" = "NetBSD" ]
581
 	then
582
-		chown $PANDORA_USER:daemon $PANDORA_BASE$PANDORA_TEMP
583
+		chown $PANDORA_USER:daemon $PANDORA_BASE$PANDORA_TEMP 2>/dev/null
584
 		chmod -R 770 $PANDORA_BASE$PANDORA_TEMP
585
 		chmod 775 $PANDORA_BASE$PANDORA_TEMP
586
 	fi
587
@@ -467,85 +417,55 @@
588
 
589
 	cp $OS_NAME/pandora_agent.conf $PANDORA_BASE$PANDORA_CFG/pandora_agent.conf
590
 	chmod 600 $PANDORA_BASE$PANDORA_CFG/pandora_agent.conf
591
-	chown $PANDORA_USER $PANDORA_BASE$PANDORA_CFG/pandora_agent.conf
592
+	chown $PANDORA_USER $PANDORA_BASE$PANDORA_CFG/pandora_agent.conf 2>/dev/null
593
 
594
-	if [ "$OS_NAME" = "FreeBSD" -o "$OS_NAME" = "NetBSD" ]
595
+	echo "Linking start-up daemon script '$DAEMON_SCRIPT' on $OS_NAME";
596
+
597
+	if [ "$OS_NAME" = "Darwin" ]
598
 	then
599
-		echo "Linking start-up daemon script 'pandora_agent' on $OS_NAME";
600
+		# Specific service install on Darwin/macOSX
601
+		launchctl load -F Darwin/com.pandorafms.pandorafms.plist
602
+		echo "Start Pandora FMS service with 'launchctl start com.pandorafms.pandorafms'"
603
+		echo "This service has been scheduled to launch on each system startup"
604
 	else
605
-		echo "Linking start-up daemon script 'pandora_agent_daemon' on $OS_NAME";
606
-	fi
607
+		DESTDIR=""
608
+		[ "$PANDORA_BASE" ] && [ $FAKEROOT -eq 1 ] && DESTDIR=$PANDORA_BASE
609
 
610
-	if [ "$OS_NAME" = "Darwin" ]
611
-        then
612
-        	# Specific service install on Darwin/macOSX
613
-                launchctl load -F Darwin/com.pandorafms.pandorafms.plist
614
-                echo "Start Pandora FMS service with 'launchctl start com.pandorafms.pandorafms'"
615
-                echo "This service has been scheduled to launch on each system startup"
616
-        fi
617
+		cp $DAEMON_SCRIPT $DESTDIR$PANDORA_STARTUP
618
+		chmod 755 $DESTDIR$PANDORA_STARTUP
619
+		chown root:0 $DESTDIR$PANDORA_STARTUP 2>/dev/null
620
 
621
-	if [ "$OS_NAME" = "AIX" ]
622
-	then
623
-		cp pandora_agent_daemon /etc/rc.pandora_agent_daemon		
624
-		ln -s /etc/rc.pandora_agent_daemon /etc/rc.d/rc2.d/S90pandora_agent_daemon
625
-		chmod 755 $PANDORA_STARTUP
626
-		chown root:0 $PANDORA_STARTUP
627
-		echo "Pandora FMS agent has been included in /etc/rc.d/rc2.d/S90pandora_agent_daemon"
628
-	fi
629
-	
630
-	if [ $OS_NAME = "HP-UX" ]
631
-	then
632
-		PANDORA_STARTUP=/sbin/init.d/pandora_agent_daemon
633
-		cp pandora_agent_daemon $PANDORA_STARTUP
634
-		ln -s /sbin/init.d/pandora_agent_daemon /sbin/rc3.d/S90pandora_agent_daemon 2> /dev/null
635
-		ln -s /sbin/init.d/pandora_agent_daemon /sbin/rc2.d/S90pandora_agent_daemon 2> /dev/null
636
-		chmod 755 $PANDORA_STARTUP
637
-		chown root:0 $PANDORA_STARTUP
638
-		echo "Pandora FMS agent has been included in /sbin/rcX.d/S90pandora_agent_daemon"
639
-	fi
640
-	
641
-	if [ $OS_NAME = "SunOS" ]
642
-	then
643
-		PANDORA_STARTUP=/etc/init.d/pandora_agent_daemon
644
-		cp pandora_agent_daemon $PANDORA_STARTUP 
645
-		ln -s /etc/init.d/pandora_agent_daemon /etc/rc2.d/S90pandora_agent_daemon 2> /dev/null
646
-		chmod 755 $PANDORA_STARTUP
647
-		chown root:0 $PANDORA_STARTUP
648
-		echo "Pandora FMS agent has been included in /etc/rc2.d/S90pandora_agent_daemon"
649
-	fi
650
-	
651
-	if [ $OS_NAME = "Linux" ]
652
-	then
653
-		PANDORA_STARTUP=/etc/init.d/pandora_agent_daemon
654
-		cp pandora_agent_daemon $PANDORA_STARTUP
655
-		if [ -d /etc/rc.d/ ]
656
+		RCDIRS=""
657
+		MSG=""
658
+		if [ "$OS_NAME" = "AIX" ]
659
 		then
660
-			ln -s /etc/init.d/pandora_agent_daemon /etc/rc.d/rc2.d/S90pandora_agent 2> /dev/null
661
-			ln -s /etc/init.d/pandora_agent_daemon /etc/rc.d/rc3.d/S90pandora_agent 2> /dev/null
662
-		else
663
-			ln -s /etc/init.d/pandora_agent_daemon /etc/rc2.d/S90pandora_agent 2> /dev/null
664
-			ln -s /etc/init.d/pandora_agent_daemon /etc/rc2.d/S90pandora_agent 2> /dev/null
665
+			RCDIRS=/etc/rc.d/rc2.d
666
+			MSG="Pandora FMS agent has been included in $DESTDIR/etc/rc.d/rc2.d/S90pandora_agent_daemon"
667
+		elif [ "$OS_NAME" = "HP-UX" ]
668
+		then
669
+			RCDIRS="/sbin/rc2.d /sbin/rc3.d"
670
+			MSG="Pandora FMS agent has been included in $DESTDIR/sbin/rcX.d/S90pandora_agent_daemon"
671
+		elif [ "$OS_NAME" = "SunOS" ]
672
+		then
673
+			RCDIRS=/etc/rc2.d
674
+			MSG="Pandora FMS agent has been included in $DESTDIR/etc/rc2.d/S90pandora_agent_daemon"
675
+		elif [ "$OS_NAME" = "Linux" ]
676
+		then
677
+			if [ -d /etc/rc.d/ ]
678
+			then
679
+				RCDIRS="/etc/rc.d/rc2.d /etc/rc.d/rc3.d"
680
+			else
681
+				RCDIRS="/etc/rc2.d /etc/rc3.d"
682
+			fi
683
 		fi
684
-		chmod 755 $PANDORA_STARTUP
685
-		chown root:0 $PANDORA_STARTUP
686
+		[ "$RCDIRS" ] && for RCDIR in $RCDIRS
687
+		do
688
+			[ $FAKEROOT -eq 1 ] && [ ! -d $DESTDIR$RCDIR ] && mkdir -p $DESTDIR$RCDIR >/dev/null 2>&1
689
+			ln -s $PANDORA_STARTUP $DESTDIR$RCDIR/S90pandora_agent 2> /dev/null
690
+		done
691
+		[ "$MSG" ] && echo "$MSG"
692
 	fi
693
 
694
-	if [ "$OS_NAME" = "FreeBSD" ]
695
-	then
696
-		PANDORA_STARTUP=/usr/local/etc/rc.d/pandora_agent
697
-		cp FreeBSD/pandora_agent $PANDORA_STARTUP
698
-		chmod 555 $PANDORA_STARTUP
699
-		chown root:wheel $PANDORA_STARTUP
700
-	fi
701
-
702
-	if [ "$OS_NAME" = "NetBSD" ]
703
-	then
704
-		PANDORA_STARTUP=/etc/rc.d/pandora_agent
705
-		cp NetBSD/pandora_agent $PANDORA_STARTUP
706
-		chmod 555 $PANDORA_STARTUP
707
-		chown root:wheel $PANDORA_STARTUP
708
-	fi
709
-
710
 	echo "Done."
711
 	echo " "
712
 	echo "You have your startup script ready at $PANDORA_STARTUP"
713
Index: plugins/who.sh
714
===================================================================
715
--- plugins/who.sh	(revision 10314)
716
+++ plugins/who.sh	(working copy)
717
@@ -1,10 +1,10 @@
718
-#!/bin/bash
719
+#!/bin/sh
720
 echo "<module>";
721
 echo "<name>who</name>";
722
 echo "<type>async_string</type>";
723
 echo "<data><![CDATA["
724
 WHO=`who`
725
-if [ "$WHO" == "" ]; then
726
+if [ "$WHO" = "" ]; then
727
 	echo "None"
728
 else
729
 	echo $WHO
730
Index: tentacle_server
731
===================================================================
732
--- tentacle_server	(revision 10314)
733
+++ tentacle_server	(working copy)
734
@@ -60,9 +60,15 @@
735
 use warnings;
736
 use Getopt::Std;
737
 use IO::Select;
738
+use threads;
739
 use Thread::Semaphore;
740
 use POSIX ":sys_wait_h";
741
+use Time::HiRes qw(usleep);
742
 
743
+# Constants for Win32 services.
744
+use constant WIN32_SERVICE_STOPPED => 0x01;
745
+use constant WIN32_SERVICE_RUNNING => 0x04;
746
+
747
 my $t_libwrap_installed = eval { require Authen::Libwrap } ? 1 : 0;
748
 
749
 if ($t_libwrap_installed) {
750
@@ -77,9 +83,8 @@
751
       : eval { require IO::Socket::INET }  ? 'IO::Socket::INET'
752
       : die $@;
753
 
754
-if ($SOCKET_MODULE eq 'IO::Socket::INET') {
755
-	print_log ("IO::Socket::INET6 is not found. IPv6 is disabled.");
756
-}
757
+# Service name for Win32.
758
+my $SERVICE_NAME="Tentacle Server";
759
 
760
 # Program version
761
 our $VERSION = '0.4.0';
762
@@ -130,7 +135,7 @@
763
 my $t_select;
764
 
765
 # Semaphore
766
-my $t_sem;
767
+my $t_sem :shared;
768
 
769
 # Server socket
770
 my @t_server_sockets;
771
@@ -197,6 +202,7 @@
772
 	print ("\t-p port\t\tPort to listen on (default $t_port).\n");
773
 	print ("\t-q\t\tQuiet. Do now print error messages.\n");
774
 	print ("\t-r number\tNumber of retries for network opertions (default $t_retries).\n");
775
+	print ("\t-S (install|uninstall|run) Manage the win32 service.\n");
776
 	print ("\t-t time\t\tTime-out for network operations in seconds (default ${t_timeout}s).\n");
777
 	print ("\t-v\t\tBe verbose.\n");
778
 	print ("\t-w\t\tPrompt for OpenSSL private key password.\n");
779
@@ -241,27 +247,6 @@
780
 }
781
 
782
 ################################################################################
783
-## SUB start_win_service
784
-## Turn the current process into a Windows service.
785
-################################################################################
786
-#sub start_win_service {
787
-#	require Win32::Daemon;
788
-#
789
-#	# Tell the OS to start the service
790
-#	Win32::Daemon::StartService ();
791
-#
792
-#	# Wait until the service manager is ready
793
-#	while (SERVICE_START_PENDING != Win32::Daemon::State()) {
794
-#		sleep (1);
795
-#	}
796
-#
797
-#	# Tell the service manager we are running
798
-#	Win32::Daemon::State (SERVICE_RUNNING);
799
-#
800
-#	# Call Win32::Daemon::StopService() when done
801
-#}
802
-
803
-################################################################################
804
 ## SUB parse_options
805
 ## Parse command line options and initialize global variables.
806
 ################################################################################
807
@@ -271,7 +256,7 @@
808
 	my @t_addresses_tmp;
809
 
810
 	# Get options
811
-	if (getopts ('a:c:de:f:hi:k:m:op:qr:s:t:vwx:b:g:T', \%opts) == 0 || defined ($opts{'h'})) {
812
+	if (getopts ('a:b:c:de:f:g:hi:k:m:op:qr:s:S:t:Tvwx:', \%opts) == 0 || defined ($opts{'h'})) {
813
 		print_help ();
814
 		exit 1;
815
 	}
816
@@ -467,19 +452,33 @@
817
 			error ("Authen::Libwrap is not installed.");
818
 		}
819
 	}
820
-}
821
 
822
-################################################################################
823
-## SUB sigchld_handler
824
-## Handle child process termination.
825
-################################################################################
826
-sub sigchld_handler {
827
+	# Win32 service management
828
+	if (defined ($opts{'S'})) {
829
+		my $service_action = $opts{'S'};
830
+		if ($^O ne 'MSWin32') {
831
+			error ("Windows services are only available on Win32.");
832
+		} else {
833
+			eval "use Win32::Daemon";
834
+			die($@) if ($@);
835
 
836
-	while (waitpid(-1, &WNOHANG) > 0) {
837
-		$t_sem->up ();
838
+			if ($service_action eq 'install') {
839
+				install_service();
840
+			} elsif ($service_action eq 'uninstall') {
841
+				uninstall_service();
842
+			} elsif ($service_action eq 'run') {
843
+				Win32::Daemon::RegisterCallbacks({
844
+			        start       =>  \&callback_start,
845
+			        running     =>  \&callback_running,
846
+			        stop        =>  \&callback_stop,
847
+				});
848
+				Win32::Daemon::StartService();
849
+				exit 0;
850
+			} else {
851
+				error("Unknown action: $service_action");
852
+			}
853
+		}
854
 	}
855
-
856
-	$SIG{CHLD} = \&sigchld_handler;
857
 }
858
 
859
 ################################################################################
860
@@ -660,87 +659,86 @@
861
 }
862
 
863
 ################################################################################
864
-## SUB accept_connection
865
-## Accept an incoming connection and fork.
866
+## SUB accept_connections
867
+## Manage incoming connections.
868
 ################################################################################
869
-sub accept_connection {
870
+sub accept_connections {
871
 	my $pid;
872
 	my $t_server_socket;
873
 
874
-	my @ready = $select->can_read;
875
+	# Start server
876
+	start_server ();
877
 
878
-	foreach $t_server_socket (@ready) {
879
+	# Initialize semaphore
880
+	$t_sem = Thread::Semaphore->new ($t_max_conn);
881
 
882
-		# Accept connection
883
-		$t_client_socket = $t_server_socket->accept ();
884
+	while (1) {
885
+		my @ready = $select->can_read;
886
+		foreach $t_server_socket (@ready) {
887
 
888
-		if (! defined ($t_client_socket)) {
889
+			# Accept connection
890
+			$t_client_socket = $t_server_socket->accept ();
891
 
892
-			# EINTR
893
-			if ($! ne '') {
894
-				next;
895
+			if (! defined ($t_client_socket)) {
896
+				next if ($! ne ''); # EINTR
897
+				error ("accept: $!.");
898
 			}
899
 
900
-			error ("accept: $!.");
901
-		}
902
+			print_log ("Client connected from " . $t_client_socket->sockhost ());
903
 
904
-		print_log ("Client connected from " . $t_client_socket->sockhost ());
905
-
906
-		# Fork and serve the client
907
-		$pid = fork ();
908
-		if (! defined ($pid)) {
909
-			error ("Cannot fork: $!.");
910
+			# Create a new thread and serve the client
911
+			$t_sem->down();
912
+			my $thr = threads->create(\&serve_client);
913
+			if (! defined ($thr)) {
914
+				error ("Error creating thread: $!.");
915
+			}
916
+			$thr->detach();
917
 		}
918
-	
919
-		# Child
920
-		if ($pid == 0) {
921
-		
922
-			# We do not need the server socket
923
-			$t_server_socket->close ();
924
 
925
-			if ($t_use_libwrap) {
926
-				if (! hosts_ctl($t_program_name, $t_client_socket)) {
927
-					print_log ("Connection from " . $t_client_socket->sockhost() . " is closed by tcpwrappers.");
928
-					$t_client_socket->close ();
929
+		usleep (1000);
930
+	}
931
+}
932
 
933
-					exit;
934
-				}
935
-			}
936
-		
937
-			# Add client socket to select queue
938
-			$t_select = IO::Select->new ();
939
-			$t_select->add ($t_client_socket);
940
-		
941
-			# Start SSL
942
-			if ($t_ssl == 1) {
943
-				start_ssl ();
944
-			}
945
+################################################################################
946
+## SUB serve_client
947
+## Serve a connected client.
948
+################################################################################
949
+sub serve_client() {
950
 
951
-			# Authenticate client
952
-			if ($t_pwd ne '') {
953
-				auth_pwd ();
954
-			}
955
+	if ($t_use_libwrap) {
956
+		if (! hosts_ctl($t_program_name, $t_client_socket)) {
957
+			print_log ("Connection from " . $t_client_socket->sockhost() . " is closed by tcpwrappers.");
958
+			$t_client_socket->close ();
959
+			$t_sem->up();
960
+			return;
961
+		}
962
+	}
963
 
964
-			# Check if proxy mode is enable
965
-			if (defined ($t_proxy_ip)) {
966
-
967
-				serve_proxy_connection ();	
968
+	eval {		
969
+		# Add client socket to select queue
970
+		$t_select = IO::Select->new ();
971
+		$t_select->add ($t_client_socket);
972
 			
973
-			} else {
974
-			
975
-				serve_connection ();
976
-			}
977
-
978
-			$t_client_socket->close ();
979
-
980
-			# Must exit now
981
-			exit;
982
+		# Start SSL
983
+		if ($t_ssl == 1) {
984
+			start_ssl ();
985
 		}
986
+	
987
+		# Authenticate client
988
+		if ($t_pwd ne '') {
989
+			auth_pwd ();
990
+		}
991
+	
992
+		# Check if proxy mode is enable
993
+		if (defined ($t_proxy_ip)) {
994
+			serve_proxy_connection ();	
995
+		} else {
996
+			serve_connection ();
997
+		}
998
+	};
999
 
1000
-		# Parent
1001
-		$t_client_socket->close ();
1002
-
1003
-	}
1004
+	$t_client_socket->close ();
1005
+	$t_sem->up();
1006
 }
1007
 
1008
 ################################################################################
1009
@@ -1045,10 +1043,8 @@
1010
 sub error {
1011
 
1012
 	if ($t_quiet == 0) {
1013
-		print (STDERR "[err] $_[0]\n");
1014
+		die("[err] $_[0]\n\n");
1015
 	}
1016
-
1017
-	exit 1;
1018
 }
1019
 
1020
 ################################################################################
1021
@@ -1414,6 +1410,91 @@
1022
 }
1023
 
1024
 ################################################################################
1025
+## SUB install_service
1026
+## Install the Windows service.
1027
+################################################################################
1028
+sub install_service() {
1029
+
1030
+	my $service_path = $0;
1031
+	my $service_params = "-s \"$t_directory\" -S run";
1032
+
1033
+	my %service_hash = (
1034
+		machine =>  '',
1035
+		name	=>  'TENTACLESRV',
1036
+		display =>  $SERVICE_NAME,
1037
+		path	=>  $service_path,
1038
+		user	=>  '',
1039
+		pwd	 =>  '',
1040
+		description => 'Tentacle Server http://sourceforge.net/projects/tentacled/',
1041
+		parameters => $service_params
1042
+	);
1043
+	
1044
+	if (Win32::Daemon::CreateService(\%service_hash)) {
1045
+		print "Successfully added.\n";
1046
+		exit 0;
1047
+	} else {
1048
+		print "Failed to add service: " . Win32::FormatMessage(Win32::Daemon::GetLastError()) . "\n";
1049
+		exit 1;
1050
+	}
1051
+}
1052
+
1053
+################################################################################
1054
+## SUB uninstall_service
1055
+## Install the Windows service.
1056
+################################################################################
1057
+sub uninstall_service() {
1058
+	if (Win32::Daemon::DeleteService('', 'TENTACLESRV')) {
1059
+		print "Successfully deleted.\n";
1060
+		exit 0;
1061
+	} else {
1062
+		print "Failed to delete service: " . Win32::FormatMessage(Win32::Daemon::GetLastError()) . "\n";
1063
+		exit 1;
1064
+	}
1065
+}
1066
+
1067
+################################################################################
1068
+## SUB callback_running
1069
+## Windows service callback function for the running event.
1070
+################################################################################
1071
+sub callback_running {
1072
+
1073
+	if (Win32::Daemon::State() == WIN32_SERVICE_RUNNING) {
1074
+	}
1075
+}
1076
+
1077
+################################################################################
1078
+## SUB callback_start
1079
+## Windows service callback function for the start event.
1080
+################################################################################
1081
+sub callback_start {
1082
+
1083
+	# Accept_connections ();
1084
+	my $thr = threads->create(\&accept_connections);
1085
+	if (!defined($thr)) {
1086
+		Win32::Daemon::State(WIN32_SERVICE_STOPPED);
1087
+		Win32::Daemon::StopService();
1088
+		return;
1089
+	}
1090
+	$thr->detach();
1091
+
1092
+	Win32::Daemon::State(WIN32_SERVICE_RUNNING);
1093
+}
1094
+
1095
+################################################################################
1096
+## SUB callback_stop
1097
+## Windows service callback function for the stop event.
1098
+################################################################################
1099
+sub callback_stop {
1100
+
1101
+	foreach my $t_server_socket (@t_server_sockets) {
1102
+		$t_server_socket->close ();
1103
+	}
1104
+
1105
+	Win32::Daemon::State(WIN32_SERVICE_STOPPED);
1106
+	Win32::Daemon::StopService();
1107
+}
1108
+
1109
+################################################################################
1110
 # Main
1111
 ################################################################################
1112
 
1113
@@ -1444,25 +1525,16 @@
1114
 
1115
 # Handle ctr-c
1116
 if ($^O eq 'MSWin32') {
1117
+	no warnings;
1118
 	$SIG{INT2} = \&stop_server;
1119
+	use warnings;
1120
 }
1121
 else {
1122
 	$SIG{INT} = \&stop_server;
1123
 }
1124
 
1125
-# Handle SIGCHLD
1126
-$SIG{CHLD} = \&sigchld_handler;
1127
-
1128
-start_server ();
1129
-
1130
-# Initialize semaphore
1131
-$t_sem = Thread::Semaphore->new ($t_max_conn);
1132
-
1133
 # Accept connections
1134
-while (1) {
1135
-	$t_sem->down ();
1136
-	accept_connection ();
1137
-}
1138
+accept_connections();
1139
 
1140
 __END__
1141
 
1142
Index: pandora_agent_daemon
1143
===================================================================
1144
--- pandora_agent_daemon	(revision 10314)
1145
+++ pandora_agent_daemon	(working copy)
1146
@@ -34,38 +34,39 @@
1147
 	OS_NAME=`uname -s`
1148
 	if [ $OS_NAME = "HP-UX" ]
1149
 	then
1150
-		PANDORA_PID=`ps -ex | grep "$DAEMON $PANDORA_PATH" | grep -v grep | head -1 | awk '{ print $1 }'`
1151
-	else
1152
-		if [ "$OS_NAME" = "SunOS" ]
1153
+		PANDORA_PID=`ps -ef | grep "/usr/bin/perl $DAEMON" | grep -v grep | awk '{print $2}'`
1154
+	elif [ "$OS_NAME" = "SunOS" ]
1155
+	then
1156
+		ZONENAME_CMD="/bin/zonename"
1157
+		TRUNCATED_DAEMON=`echo "$DAEMON $PANDORA_PATH" | cut -c1-20`
1158
+		if [ -x $ZONENAME_CMD ]
1159
 		then
1160
-			ZONENAME_CMD="/bin/zonename"
1161
-			TRUNCATED_DAEMON=`echo "$DAEMON $PANDORA_PATH" | cut -c1-20`
1162
-			if [ -x $ZONENAME_CMD ]
1163
-			then
1164
-				ZONE=`$ZONENAME_CMD`
1165
-			else
1166
-				ZONE=
1167
-			fi
1168
-			if [ "$ZONE" = "global" ]
1169
-			then
1170
-				PANDORA_PID=`ps -f -z global | grep "$TRUNCATED_DAEMON" | grep -v grep | head -1 | awk '{ print $2 }'`
1171
-			else
1172
-				PANDORA_PID=`ps -Af | grep "$TRUNCATED_DAEMON" | grep -v grep | head -1 | awk '{ print $2 }'`
1173
-			fi
1174
-		elif [ "$OS_NAME" = "Linux" -a -x /usr/sbin/vzpid ]
1175
+			ZONE=`$ZONENAME_CMD`
1176
+		else
1177
+			ZONE=
1178
+		fi
1179
+		if [ "$ZONE" = "global" ]
1180
 		then
1181
-			for _pid in `ps -Af | grep "$DAEMON $PANDORA_PATH" | grep -v grep | awk '{ print $2 }'`
1182
-			do
1183
-				_ctid=`/usr/sbin/vzpid $_pid | awk '$1 == '$_pid' { print $2 }'`
1184
-				if [ "X$_ctid" = "X0" ]
1185
-				then
1186
-					PANDORA_PID=$_pid
1187
-					break
1188
-				fi
1189
-			done
1190
+			PANDORA_PID=`ps -f -z global | grep "$TRUNCATED_DAEMON" | grep -v grep | head -1 | awk '{ print $2 }'`
1191
 		else
1192
-			PANDORA_PID=`ps -Af | grep "$DAEMON $PANDORA_PATH" | grep -v grep | head -1 | awk '{ print $2 }'`
1193
+			PANDORA_PID=`ps -Af | grep "$TRUNCATED_DAEMON" | grep -v grep | head -1 | awk '{ print $2 }'`
1194
 		fi
1195
+	elif [ "$OS_NAME" = "Linux" ] && [ -x /usr/sbin/vzpid ]
1196
+	then
1197
+		# Virtuozzo/OpenVZ
1198
+		local _pid _ctid _pids
1199
+		_pids=`ps -Af | grep "$DAEMON $PANDORA_PATH" | grep -v grep | awk '{ print $2 }'`
1200
+		[ "$_pids" ] && for _pid in $_pids
1201
+		do
1202
+			_ctid=`/usr/sbin/vzpid $_pid | awk '$1 == '$_pid' { print $2 }'`
1203
+			if [ "X$_ctid" = "X0" ]
1204
+			then
1205
+				PANDORA_PID=$_pid
1206
+				break
1207
+			fi
1208
+		done
1209
+	else
1210
+		PANDORA_PID=`ps -Af | grep "$DAEMON $PANDORA_PATH" | grep -v grep | head -1 | awk '{ print $2 }'`
1211
 	fi
1212
 	
1213
 	echo $PANDORA_PID
1214
Index: pandora_agent
1215
===================================================================
1216
--- pandora_agent	(revision 10314)
1217
+++ pandora_agent	(working copy)
1218
@@ -343,6 +343,8 @@
1219
 			init_module ($module);
1220
 		} elsif ($line =~ /^\s*module_name\s+(.+)$/) {
1221
 			$module->{'name'} = $1;
1222
+			$module->{'name'} =~ s/\s+$//g;
1223
+			$module->{'name'} =~ s/^\s+//g;
1224
 		} elsif ($line =~ /^\s*module_description\s+(.+)$/) {
1225
 			$module->{'description'} = $1;
1226
 		} elsif ($line =~ /^\s*module_type\s+(\S+)\s*$/) {
1227
@@ -1727,12 +1729,7 @@
1228
 		
1229
 	# Data list
1230
 	if ($#data > 0) {
1231
-		$Xml .= "	<datalist>\n";
1232
-		foreach my $data_item (@data) {
1233
-			chomp ($data_item);
1234
-			$Xml .= "	<data><value><![CDATA[$data_item]]></value></data>\n";
1235
-		}
1236
-		$Xml .= "	</datalist>\n";
1237
+		$Xml .= "	<data><![CDATA[" . join('', @data) . "]]></data>\n";
1238
 	# Single data
1239
 	} else {
1240
 		chomp ($data[0]);
1241
Index: FreeBSD/pandora_agent
1242
===================================================================
1243
--- FreeBSD/pandora_agent	(revision 10314)
1244
+++ FreeBSD/pandora_agent	(working copy)
1245
@@ -3,6 +3,7 @@
1246
 # **********************************************************************
1247
 # Pandora FMS Agent Daemon launcher for FreeBSD
1248
 # (c) 2010 Junichi Satoh <junichi@rworks.jp>
1249
+# (c) 2014 Koichiro Kikuchi <koichiro@rworks.jp>
1250
 #
1251
 # **********************************************************************
1252
 
1253
@@ -18,7 +19,7 @@
1254
 . "/etc/rc.subr"
1255
 
1256
 name="pandora_agent"
1257
-rcvar=`set_rcvar`
1258
+rcvar=pandora_agent_enable
1259
 
1260
 # read configuration and set defaults
1261
 pandora_agent_enable=${pandora_agent_enable:-"NO"}
1262
@@ -26,22 +27,15 @@
1263
 
1264
 PATH=/bin:/usr/bin:/sbin:/usr/sbin:/usr/local/bin
1265
 
1266
-command=/usr/local/bin/pandora_agent
1267
-command_args="/usr/local/etc/pandora &"
1268
-
1269
 pidfile=/var/run/$name.pid
1270
 required_files="/usr/local/etc/pandora/pandora_agent.conf"
1271
-start_postcmd=start_postcmd
1272
 stop_postcmd=stop_postcmd
1273
 
1274
-procname="/usr/bin/perl"
1275
+command=/usr/sbin/daemon
1276
+command_interpreter=/usr/local/bin/perl
1277
+procname=/usr/local/bin/pandora_agent
1278
 
1279
-start_postcmd()
1280
-{
1281
-	sleep 1
1282
-	PANDORA_PID=`pgrep -f -j none $name`
1283
-	echo $PANDORA_PID > $pidfile
1284
-}
1285
+command_args="-cfp $pidfile $procname /usr/local/etc/pandora"
1286
 
1287
 stop_postcmd()
1288
 {
(-)b/net-mgmt/pandorafms_agent/pkg-plist (-4 / +2 lines)
Lines 27-37 man/man1/pandora_agent.1.gz Link Here
27
%%DATADIR%%/plugins/who.sh
27
%%DATADIR%%/plugins/who.sh
28
@owner pandora
28
@owner pandora
29
@mode 700
29
@mode 700
30
@dirrmtry %%DATADIR%%/collections
30
@dir %%DATADIR%%/collections
31
@dirrmtry %%DATADIR%%/plugins
31
@dir %%DATADIR%%/plugins
32
@owner
32
@owner
33
@mode
33
@mode
34
@dirrmtry %%DATADIR%%
35
%%ETCDIR%%/plugins
34
%%ETCDIR%%/plugins
36
%%ETCDIR%%/collections
35
%%ETCDIR%%/collections
37
@dirrmtry %%ETCDIR%%
(-)b/net-mgmt/pandorafms_console/Makefile (-4 / +5 lines)
Lines 50-65 post-install: Link Here
50
		&& ${RM} -rf pandora_console_install* *.spec \
50
		&& ${RM} -rf pandora_console_install* *.spec \
51
			extras/check_other_languages.sh.bak \
51
			extras/check_other_languages.sh.bak \
52
			include/languages/extract_newlines.sh.bak \
52
			include/languages/extract_newlines.sh.bak \
53
			*.sql.bak COPYING ${PORTDOCS} DEBIAN/
53
			*.sql.bak COPYING ${PORTDOCS} DEBIAN/ \
54
			attachment/collections/.empty attachment/downloads/.gitignore
54
	@cd ${STAGEDIR}${WWWDIR} && ${MV} install.php install.done
55
	@cd ${STAGEDIR}${WWWDIR} && ${MV} install.php install.done
55
.if ${PORT_OPTIONS:MDOCS}
56
.if ${PORT_OPTIONS:MDOCS}
56
	@${MKDIR} ${STAGEDIR}${DOCSDIR}
57
	@${MKDIR} ${STAGEDIR}${DOCSDIR}
57
.for x in ${PORTDOCS}
58
.for x in ${PORTDOCS}
58
	@${INSTALL_DATA} ${WRKSRC}/${x} ${STAGEDIR}${DOCSDIR}
59
	${INSTALL_DATA} ${WRKSRC}/${x} ${STAGEDIR}${DOCSDIR}
59
.endfor
60
.endfor
60
.endif
61
.endif
61
	@${MKDIR} -p ${STAGEDIR}${PREFIX}/${APACHEETCDIR}/Includes
62
	@${MKDIR} ${STAGEDIR}${PREFIX}/${APACHEETCDIR}/Includes
62
	@${INSTALL_DATA} ${WRKDIR}/pandora_console.conf \
63
	${INSTALL_DATA} ${WRKDIR}/pandora_console.conf \
63
		${STAGEDIR}${PREFIX}/${APACHEETCDIR}/Includes/pandora_console.conf.sample
64
		${STAGEDIR}${PREFIX}/${APACHEETCDIR}/Includes/pandora_console.conf.sample
64
	@${LN} -sf ${_LICENSE_DIR}/${LICENSE} ${STAGEDIR}${WWWDIR}/COPYING
65
	@${LN} -sf ${_LICENSE_DIR}/${LICENSE} ${STAGEDIR}${WWWDIR}/COPYING
65
66
(-)b/net-mgmt/pandorafms_console/distinfo (-2 / +2 lines)
Lines 1-2 Link Here
1
SHA256 (pandora/pandorafms_console-5.1.tar.gz) = 4f9624f4ddbe416929b3ce47a737073da2ff319f6121454b66140fb2a70c4638
1
SHA256 (pandora/pandorafms_console-5.1SP1.tar.gz) = 5696fef415db22fd0eaffb3d8286eddfe3d123c86bae9a8a4044b7937efb8742
2
SIZE (pandora/pandorafms_console-5.1.tar.gz) = 28264905
2
SIZE (pandora/pandorafms_console-5.1SP1.tar.gz) = 27900949
(-)b/net-mgmt/pandorafms_console/files/patch-WLB-2014110100 (+29 lines)
Added Link Here
1
diff --git a/pandora_console/general/header.php b/pandora_console/general/header.php
2
index 9b02b2c..9c1524a 100644
3
--- general/header.php
4
+++ general/header.php
5
@@ -375,15 +375,22 @@ config_check();
6
 		
7
 		<?php
8
 		if ($_GET["refr"]) {
9
+			$_get_refr = strip_tags($_GET["refr"]);
10
 		?>
11
+			refr_time = parseInt("<?php echo $_get_refr; ?>");
12
+			if (isNaN(refr_time)) {
13
+				refr_time = 0;
14
+			}
15
+			
16
 			t = new Date();
17
-			t.setTime (t.getTime () + <?php echo $config["refr"] * 1000; ?>);
18
+			t.setTime (t.getTime () +
19
+				parseInt(<?php echo $config["refr"] * 1000; ?>));
20
 			$("#refrcounter").countdown ({until: t, 
21
 				layout: '%M%nn%M:%S%nn%S',
22
 				labels: ['', '', '', '', '', '', ''],
23
 				onExpiry: function () {
24
 						href = $("a.autorefresh").attr ("href");
25
-						href = href + <?php echo $_GET["refr"]; ?>;
26
+						href = href + refr_time;
27
 						$(document).attr ("location", href);
28
 					}
29
 				});
<
(-)a/net-mgmt/pandorafms_console/files/patch-update (-9578 lines)
Removed Link Here
1
Index: pandoradb_data.sql
2
===================================================================
3
--- pandoradb_data.sql	(revision 10314)
4
+++ pandoradb_data.sql	(working copy)
5
@@ -283,7 +283,7 @@
6
 -- Dumping data for table `tnews`
7
 --
8
 
9
-INSERT INTO `tnews` (`id_news`, `author`, `subject`, `text`, `timestamp`) VALUES (1,'admin','Welcome to Pandora FMS 5.0!','This is the new Pandora FMS Console. A lot of new features have been added since last version. Please read the documentation about it, and feel free to test any option.\r\n\r\nThe Pandora FMS Team.',NOW());
10
+INSERT INTO `tnews` (`id_news`, `author`, `subject`, `text`, `timestamp`) VALUES (1,'admin','Welcome to Pandora FMS!','This is the Pandora FMS Console. A lot of new features have been added since last version. Please read the documentation about it, and feel free to test any option.\r\n\r\nThe Pandora FMS Team.',NOW());
11
 INSERT INTO `tnews` (`id_news`, `author`, `subject`, `text`, `timestamp`) VALUES (2,'admin','New Pandora FMS Agent Features','Feel free to test our new features for both Windows and Linux agents: Proxy and Broker modes.',NOW());
12
 
13
 INSERT INTO tmodule VALUES (1,'Agent&#x20;module');
14
Index: include/functions_clippy.php
15
===================================================================
16
--- include/functions_clippy.php	(revision 0)
17
+++ include/functions_clippy.php	(revision 10417)
18
@@ -0,0 +1,176 @@
19
+<?php
20
+
21
+// Pandora FMS - http://pandorafms.com
22
+// ==================================================
23
+// Copyright (c) 2005-2011 Artica Soluciones Tecnologicas
24
+// Please see http://pandorafms.org for full contribution list
25
+
26
+// This program is free software; you can redistribute it and/or
27
+// modify it under the terms of the  GNU Lesser General Public License
28
+// as published by the Free Software Foundation; version 2
29
+
30
+// This program is distributed in the hope that it will be useful,
31
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
32
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
33
+// GNU General Public License for more details.
34
+
35
+/**
36
+ * @package Include
37
+ * @subpackage Clippy
38
+ */
39
+
40
+function clippy_start($sec2) {
41
+	global $config;
42
+	
43
+	if ($sec2 === false) {
44
+		$sec2 = 'homepage';
45
+	}
46
+	
47
+	$sec2 = str_replace('/', '_', $sec2);
48
+	
49
+	if ($sec2 != 'homepage') {
50
+		if (is_file("include/help/clippy/" . $sec2 . ".php")) {
51
+			require("include/help/clippy/" . $sec2 . ".php");
52
+			
53
+			clippy_start_page();
54
+		}
55
+		
56
+		//Add homepage for all pages for to show the "task sugestions"
57
+		require("include/help/clippy/homepage.php");
58
+		clippy_start_page_homepage();
59
+	}
60
+	else {
61
+		require("include/help/clippy/homepage.php");
62
+		clippy_start_page_homepage();
63
+	}
64
+}
65
+
66
+function clippy_clean_help() {
67
+	set_cookie('clippy', null);
68
+}
69
+
70
+function clippy_write_javascript_helps_steps($helps,
71
+	$force_first_step_by_default = true) {
72
+	
73
+	global $config;
74
+	
75
+	$clippy = get_cookie('clippy', false);
76
+	set_cookie('clippy', null);
77
+	
78
+	
79
+	//Get the help steps from a task
80
+	$steps = $helps[$clippy]['steps'];
81
+	if ($force_first_step_by_default) {
82
+		if (empty($steps)) {
83
+			//Get the first by default
84
+			$temp = reset($helps);
85
+			$steps = $temp['steps'];
86
+		}
87
+	}
88
+	
89
+	$conf = $helps[$clippy]['conf'];
90
+	if ($force_first_step_by_default) {
91
+		if (empty($conf)) {
92
+			//Get the first by default
93
+			$temp = reset($helps);
94
+			$conf = $temp['conf'];
95
+		}
96
+	}
97
+	
98
+	if (!empty($steps)) {
99
+		$name_obj_tour = 'intro';
100
+		if (!empty($conf['name_obj_tour'])) {
101
+			$name_obj_tour = $conf['name_obj_tour'];
102
+		}
103
+		
104
+		$autostart = true;
105
+		if (!is_null($conf['autostart'])) {
106
+			$autostart = $conf['autostart'];
107
+		}
108
+		
109
+		$other_js = '';
110
+		if (!empty($conf['other_js'])) {
111
+			$other_js = $conf['other_js'];
112
+		}
113
+		
114
+		?>
115
+		<script type="text/javascript">
116
+			var <?php echo $name_obj_tour; ?> = null;
117
+			
118
+			$(document).ready(function() {
119
+				<?php echo $name_obj_tour; ?> = introJs();
120
+				
121
+				<?php echo $name_obj_tour; ?>.setOptions({
122
+					steps: <?php echo json_encode($steps); ?>,
123
+					showBullets: <?php echo json_encode($conf['showBullets']); ?>,
124
+					showStepNumbers: <?php echo json_encode($conf['showStepNumbers']); ?>,
125
+					nextLabel: "<?php echo __('Next &rarr;'); ?>",
126
+					prevLabel: "<?php echo __('&larr; Back'); ?>",
127
+					skipLabel: "<?php echo __('Skip'); ?>",
128
+					doneLabel: "<?php echo __('Done'); ?>",
129
+					exitOnOverlayClick: false,
130
+					exitOnEsc: true, //false,
131
+				})
132
+				.onexit(function(value) {
133
+						exit = confirm("<?php echo __("Do you want to exit the help tour?"); ?>");
134
+						return exit;
135
+					});
136
+				
137
+				<?php
138
+				if (!empty($conf['next_help'])) {
139
+				?>
140
+					clippy_set_help('<?php echo $conf['next_help']; ?>');
141
+				<?php
142
+				}
143
+				?>
144
+				
145
+				<?php
146
+				if ($autostart) {
147
+				?>
148
+					<?php echo $name_obj_tour; ?>.start();
149
+				<?php
150
+				}
151
+				?>
152
+			});
153
+			
154
+			<?php echo $other_js; ?>
155
+		</script>
156
+		<?php
157
+	}
158
+}
159
+
160
+function clippy_context_help($help = null) {
161
+	$id = uniqid("id_");
162
+	
163
+	$return = '';
164
+	
165
+	require_once("include/help/clippy/" . $help . ".php");
166
+	
167
+	ob_start();
168
+	$function = "clippy_" . $help;
169
+	$function();
170
+	$code = ob_get_clean();
171
+	
172
+	$code = str_replace('{clippy}', '#' . $id, $code); html_debug_print($code, true);
173
+	$code = str_replace('{clippy_obj}', 'intro_' . $id, $code); html_debug_print($code, true);
174
+	
175
+	$return = $code . 
176
+		'<div id="' . $id . '" style="display: inline;">' .
177
+		'<a onclick="intro_' .  $id . '.start();" href="javascript: return false;" >' .
178
+			html_print_image(
179
+				"images/clippy_icon.png",
180
+				true) .
181
+		'</a>' .
182
+		'</div>
183
+		<script type="text/javascript">
184
+		$(document).ready(function() {
185
+			$("#' . $id . ' img").pulsate ();
186
+		});
187
+		</script>
188
+		';
189
+	
190
+	
191
+	
192
+	return $return;
193
+}
194
+?>
195
\ No newline at end of file
196
Index: include/styles/menu.css
197
===================================================================
198
--- include/styles/menu.css	(revision 10314)
199
+++ include/styles/menu.css	(working copy)
200
@@ -81,7 +81,6 @@
201
 .submenu {
202
 	font-family: Georgia,"Times New Roman","Bitstream Charter",Times,serif;
203
 	margin: 0px 10px 0px 0;
204
-	width: 173px;
205
 }
206
 .submenu li a {
207
 	background-color: #222;
208
@@ -143,10 +142,6 @@
209
 	background-position: 4px 8px;
210
 }
211
 
212
-.menu {
213
-	width: 173px;
214
-
215
-}
216
 /* Icons specified here */
217
 #icon_oper-networkconsole {
218
  	background-image: url(../../images/op_network.png);
219
@@ -234,7 +229,6 @@
220
 #menu_container {
221
 	z-index: 3;
222
 	position: absolute;
223
-	left: -140px;
224
+	left: -80px;
225
 	background-color: #AAA;
226
-	height: 100%;
227
 }
228
Index: include/styles/pandora.css
229
===================================================================
230
--- include/styles/pandora.css	(revision 10314)
231
+++ include/styles/pandora.css	(working copy)
232
@@ -278,7 +278,7 @@
233
 }
234
 
235
 div#menu {
236
-	width: 165px;
237
+	width: 175px;
238
 	float: left;
239
 }
240
 
241
@@ -291,6 +291,14 @@
242
 	background-color: #274C00;
243
 }
244
 
245
+.fixed_header {
246
+	z-index: 9999;
247
+	position: fixed;
248
+	left: 0;
249
+	top: 0;
250
+	width: 100%;
251
+}
252
+
253
 div#foot {
254
 	font-size: 6pt !important;
255
 	border-top: solid 2px #222;
256
@@ -298,7 +306,6 @@
257
 	padding-bottom: 5px;
258
 	text-align: center;
259
 	background: #333333;
260
-	width: 960px;
261
 	height: 38px;
262
 	clear: both;
263
 	width: auto;
264
@@ -901,17 +908,10 @@
265
 	padding: 6px 0px;
266
 	height: 14px;
267
 }
268
-.titop {
269
-	-moz-border-top-right-radius: 6px;
270
-	-webkit-border-top-right-radius: 6px;
271
-	border-top-right-radius: 6px;
272
-	heigth: 100px;
273
-}
274
 .tit, .titb {
275
 	font-weight: bold;
276
 	color: #fff;
277
 	text-align: center;
278
-	width: 173px;
279
 }
280
 
281
 .suc * {
282
@@ -1863,12 +1863,10 @@
283
 div#main {
284
 	width: auto;
285
 	float: none;
286
-	padding-right: 0px;
287
-	padding-left: 0px;
288
-	padding-top: 0px;
289
-	padding-bottom: 20px;
290
-	margin-left: 182px;
291
-	margin-right: 20px;
292
+	margin-top: 10px;
293
+	margin-left: 185px;
294
+	margin-right: 10px;
295
+	padding-bottom: 10px;
296
 	background: #ECECEC;
297
 	min-width: 720px;
298
 }
299
@@ -2669,7 +2667,7 @@
300
 	margin: 0px !important;
301
 	bottom: 0px;
302
 	left: 0px;
303
-	z-index: 1020;
304
+	z-index: 9001;
305
 }
306
 
307
 #shortcut_bar {
308
@@ -2704,3 +2702,12 @@
309
 table#policy_modules td * {
310
 	display: inline;
311
 }
312
+
313
+
314
+.context_help_title {
315
+	font-weight: bolder;
316
+	text-align: left;
317
+}
318
+.context_help_body {
319
+	text-align: left;
320
+}
321
\ No newline at end of file
322
Index: include/functions_update_manager.php
323
===================================================================
324
--- include/functions_update_manager.php	(revision 10314)
325
+++ include/functions_update_manager.php	(working copy)
326
@@ -24,11 +24,17 @@
327
 	global $build_version;
328
 	global $pandora_version;
329
 	
330
-	$license = db_get_value('`value`', 'tupdate_settings', '`key`',
331
+	$license = db_get_value(
332
+		db_encapsule_fields_with_same_name_to_instructions('value'),
333
+		'tupdate_settings',
334
+		db_encapsule_fields_with_same_name_to_instructions('key'),
335
 		'customer_key');
336
 	
337
 	if (enterprise_installed()) {
338
-		$current_update = db_get_value('`value`', 'tupdate_settings', '`key`',
339
+		$current_update = db_get_value(
340
+			db_encapsule_fields_with_same_name_to_instructions('value'),
341
+			'tupdate_settings',
342
+			db_encapsule_fields_with_same_name_to_instructions('key'),
343
 			'current_package_enterprise');
344
 		
345
 		$current_update = 0;
346
@@ -36,7 +42,10 @@
347
 			$current_update = $config['current_package_enterprise'];
348
 	}
349
 	else {
350
-		$current_update = db_get_value('`value`', 'tupdate_settings', '`key`',
351
+		$current_update = db_get_value(
352
+			db_encapsule_fields_with_same_name_to_instructions('value'),
353
+			'tupdate_settings',
354
+			db_encapsule_fields_with_same_name_to_instructions('key'),
355
 			'current_package');
356
 		
357
 		$current_update = 0;
358
@@ -64,10 +73,12 @@
359
 function rrmdir($dir) {
360
 	if (is_dir($dir)) {
361
 		$objects = scandir($dir);
362
+		
363
 		foreach ($objects as $object) {
364
 			if ($object != "." && $object != "..") {
365
-				if (filetype($dir."/".$object) == "dir")
366
-					rrmdir($dir."/".$object); else unlink($dir."/".$object);
367
+				if (filetype($dir . "/" . $object) == "dir")
368
+					rrmdir($dir . "/" . $object);
369
+				else unlink($dir . "/" . $object);
370
 			}
371
 		}
372
 		reset($objects);
373
@@ -264,11 +275,13 @@
374
 		return false;
375
 	}
376
 	else {
377
-		if ($is_ajax) {
378
-			return true;
379
+		$result = json_decode($result, true);
380
+		
381
+		if (empty($result)) {
382
+			return false;
383
 		}
384
 		else {
385
-			return false;
386
+			return true;
387
 		}
388
 	}
389
 }
390
@@ -362,8 +375,10 @@
391
 		"/downloads/last_package.tgz";
392
 	
393
 	try {
394
+		rrmdir($config['attachment_store'] .
395
+			"/downloads/temp_update/pandora_console");
396
+		
397
 		$phar = new PharData($path_package);
398
-		rrmdir($config['attachment_store'] . "/downloads/temp_update/pandora_console");
399
 		$phar->extractTo($config['attachment_store'] . "/downloads/temp_update");
400
 	}
401
 	catch (Exception $e) {
402
@@ -384,7 +399,14 @@
403
 		array('value' => 50),
404
 		array('token' => 'progress_update'));
405
 	
406
-	$full_path = $config['attachment_store'] . "/downloads/temp_update/pandora_console";
407
+	$path_array = array('downloads', 'temp_update', 'pandora_console');
408
+	$full_path = $config['attachment_store'];
409
+	foreach ($path_array as $directory) {
410
+		$full_path = $full_path . '/' . $directory;
411
+		if (!is_dir($full_path)) {
412
+			mkdir($full_path);
413
+		}
414
+	}
415
 	
416
 	$homedir = $config['homedir'];
417
 	
418
Index: include/functions_groups.php
419
===================================================================
420
--- include/functions_groups.php	(revision 10314)
421
+++ include/functions_groups.php	(working copy)
422
@@ -236,7 +236,7 @@
423
  * @param integer $parent The id_group parent to search the childrens.
424
  * @param array $groups The groups, its for optimize the querys to DB.
425
  */
426
-function groups_get_childrens($parent, $groups = null) {
427
+function groups_get_childrens($parent, $groups = null, $onlyPropagate = false) {
428
 	if (empty($groups)) {
429
 		$groups = db_get_all_rows_in_table('tgrupo');
430
 	}
431
@@ -248,7 +248,7 @@
432
 			continue;
433
 		}
434
 		
435
-		if ($group['propagate']) {
436
+		if ($group['propagate'] || $onlyPropagate) {
437
 			if ($group['parent'] == $parent) {
438
 				$return = $return + array($group['id_grupo'] => $group) + groups_get_childrens($group['id_grupo'], $groups);
439
 			}
440
@@ -1531,4 +1531,42 @@
441
 		}
442
 	}
443
 }
444
+
445
+/**
446
+ * Return an array with the groups hierarchy (Recursive)
447
+ *
448
+ * @param array Groups array passed by reference
449
+ * @param mixed The id of the parent to search or false to begin the search from the first hierarchy level
450
+ * 
451
+ * @return array The groups reordered by its hierarchy
452
+ */
453
+function groups_get_tree(&$groups, $parent = false) {
454
+	$return = array();
455
+	
456
+	foreach ($groups as $id => $group) {
457
+		if ($parent === false && (!isset($group['parent']) || $group['parent'] == 0)) {
458
+			$return[$id] = $group;
459
+			unset($groups[$id]);
460
+			$children = groups_get_tree($groups, $id);
461
+
462
+			if (!empty($children)) {
463
+				$return[$id]['children'] = $children;
464
+			}
465
+		}
466
+		else if ($parent && isset($group['parent']) && $group['parent'] == $parent) {
467
+			$return[$id] = $group;
468
+			unset($groups[$id]);
469
+			$children = groups_get_tree($groups, $id);
470
+
471
+			if (!empty($children)) {
472
+				$return[$id]['children'] = $children;
473
+			}
474
+		}
475
+		else {
476
+			continue;
477
+		}
478
+	}
479
+	
480
+	return $return;
481
+}
482
 ?>
483
Index: include/functions_visual_map.php
484
===================================================================
485
--- include/functions_visual_map.php	(revision 10314)
486
+++ include/functions_visual_map.php	(working copy)
487
@@ -114,9 +114,11 @@
488
 			echo '<div id="' . $id . '" class="item static_graph" style="z-index: 1; text-align: center; color: ' . $color . '; position: absolute; display: inline-block; ' . $sizeStyle . ' top: ' . $top . 'px; left: ' . $left . 'px;">';
489
 			if ($layoutData['image'] != null) {
490
 				if (($width != 0) && ($height != 0)) 
491
-					echo html_print_image($img, true, array("class" => "image", "id" => "image_" . $id, "width" => "$width", "height" => "$height", "style" => $borderStyle));
492
+					echo html_print_image($img, true,
493
+						array("class" => "image", "id" => "image_" . $id, "width" => "$width", "height" => "$height", "style" => $borderStyle));
494
 				else
495
-					echo html_print_image($img, true, array("class" => "image", "id" => "image_" . $id, "style" => $borderStyle));
496
+					echo html_print_image($img, true,
497
+						array("class" => "image", "id" => "image_" . $id, "style" => $borderStyle));
498
 				echo '<br />';
499
 			}
500
 			echo io_safe_output($text);
501
@@ -1299,8 +1301,28 @@
502
 				}
503
 				
504
 				$img_style = array ();
505
+				
506
 				$img_style["title"] = strip_tags($layout_data["label"]);
507
+				if ($layout_data['type'] == STATIC_GRAPH) {
508
+					if ($layout_data['id_agente_modulo'] != 0) {
509
+						$unit_text = trim(io_safe_output(
510
+							modules_get_unit($layout_data['id_agente_modulo'])));
511
+						
512
+						$value = modules_get_last_value($layout_data['id_agente_modulo']);
513
+						
514
+						if (!is_string($value)) {
515
+							$value = format_for_graph($value, 2);
516
+						}
517
+						
518
+						if (!empty($unit_text))
519
+							$value .= " " . $unit_text;
520
+						
521
+						$img_style["title"] .= " <br>" . __("Last value: ") .
522
+							$value;
523
+					}
524
+				}
525
 				
526
+				
527
 				if (!empty ($layout_data["width"])) {
528
 					$img_style["width"] = $layout_data["width"];
529
 				} 
530
Index: include/ajax/events.php
531
===================================================================
532
--- include/ajax/events.php	(revision 10314)
533
+++ include/ajax/events.php	(working copy)
534
@@ -349,7 +349,13 @@
535
 	}
536
 	
537
 	$details = events_page_details($event, $server);
538
-	
539
+
540
+	// Juanma (09/05/2014) Fix: Needs to reconnect to node, in previous funct node connection was lost
541
+	if ($meta) {
542
+		$server = metaconsole_get_connection_by_id ($server_id);
543
+                metaconsole_connect($server);
544
+	}
545
+
546
 	$custom_fields = events_page_custom_fields($event);
547
 	
548
 	$custom_data = events_page_custom_data($event);
549
Index: include/ajax/module.php
550
===================================================================
551
--- include/ajax/module.php	(revision 10314)
552
+++ include/ajax/module.php	(working copy)
553
@@ -23,6 +23,14 @@
554
 enterprise_include_once ('include/functions_metaconsole.php');
555
 
556
 $get_plugin_macros = get_parameter('get_plugin_macros');
557
+$search_modules = get_parameter('search_modules');
558
+$get_module_detail = get_parameter ('get_module_detail', 0);
559
+$get_module_autocomplete_input = (bool) get_parameter('get_module_autocomplete_input');
560
+$add_module_relation = (bool) get_parameter('add_module_relation');
561
+$remove_module_relation = (bool) get_parameter('remove_module_relation');
562
+$change_module_relation_updates = (bool) get_parameter('change_module_relation_updates');
563
+$get_id_tag = (bool) get_parameter('get_id_tag', 0);
564
+
565
 if ($get_plugin_macros) {
566
 	$id_plugin = get_parameter('id_plugin', 0);
567
 	
568
@@ -37,7 +45,7 @@
569
 	return;
570
 }
571
 
572
-$search_modules = get_parameter('search_modules');
573
+
574
 if ($search_modules) {
575
 	$id_agents = json_decode(io_safe_output(get_parameter('id_agents')));
576
 	$filter = get_parameter('q', '') . '%';
577
@@ -56,10 +64,9 @@
578
 	return;
579
 }
580
 
581
-$get_module_detail = get_parameter ('get_module_detail', 0);
582
 
583
 if ($get_module_detail) {
584
-
585
+	
586
 	ui_include_time_picker();
587
 	
588
 	ui_require_jquery_file("ui.datepicker-" . get_user_language(), "include/javascript/i18n/");
589
@@ -82,6 +89,9 @@
590
 		$conexion = mysql_connect ($server['dbhost'], $server['dbuser'], $server['dbpass']);
591
 		$select_db = mysql_select_db ($server['dbname'], $conexion);
592
 	}
593
+	else {
594
+		$conexion = false;
595
+	}
596
 	
597
 	$selection_mode = get_parameter('selection_mode', 'fromnow');
598
 	$date_from = (string) get_parameter ('date_from', date ('Y-m-j'));
599
@@ -131,15 +141,16 @@
600
 	
601
 	html_print_table($formtable);
602
 	
603
-	$moduletype_name = modules_get_moduletype_name (modules_get_agentmodule_type ($module_id));
604
+	$moduletype_name = modules_get_moduletype_name(
605
+		modules_get_agentmodule_type($module_id));
606
 	
607
 	$offset = (int) get_parameter("offset");
608
 	$block_size = (int) $config["block_size"];
609
 	
610
 	$columns = array ();
611
 	
612
-	$datetime_from = strtotime ($date_from.' '.$time_from);
613
-	$datetime_to = strtotime ($date_to.' '.$time_to);
614
+	$datetime_from = strtotime ($date_from . ' ' . $time_from);
615
+	$datetime_to = strtotime ($date_to . ' ' . $time_to);
616
 	
617
 	if ($moduletype_name == "log4x") {
618
 		$table->width = "100%";
619
@@ -222,14 +233,30 @@
620
 		);
621
 	}
622
 	
623
+	
624
 	$sql_body = io_safe_output($sql_body);
625
 	// Clean all codification characters
626
 	
627
 	$sql = "SELECT * " . $sql_body;
628
-	$sql_count = "SELECT count(*) " . $sql_body;
629
 	
630
+	switch ($config['dbtype']) {
631
+		case "mysql":
632
+			$sql_count = "SELECT count(*) " . $sql_body;
633
+			break;
634
+		case "postgresql":
635
+			$sql_body = str_replace("ORDER BY utimestamp DESC",
636
+				"GROUP BY utimestamp ORDER BY utimestamp DESC",
637
+				$sql_body);
638
+			$sql_count = "SELECT count(DISTINCT utimestamp) " . $sql_body;
639
+			break;
640
+		case "oracle":
641
+			$sql_count = "SELECT count(*) " . $sql_body;
642
+			break;
643
+	}
644
+	
645
 	$count = db_get_value_sql ($sql_count, $conexion);
646
 	
647
+	
648
 	switch ($config["dbtype"]) {
649
 		case "mysql":
650
 			$sql .= " LIMIT " . $offset . "," . $block_size;
651
@@ -337,10 +364,10 @@
652
 	return;
653
 }
654
 
655
-$get_module_autocomplete_input = (bool) get_parameter('get_module_autocomplete_input');
656
+
657
 if ($get_module_autocomplete_input) {
658
 	$id_agent = (int) get_parameter("id_agent");
659
-
660
+	
661
 	ob_clean();
662
 	if ($id_agent > 0) {
663
 		html_print_autocomplete_modules(
664
@@ -350,7 +377,7 @@
665
 	return;
666
 }
667
 
668
-$add_module_relation = (bool) get_parameter('add_module_relation');
669
+
670
 if ($add_module_relation) {
671
 	$result = false;
672
 	$id_module_a = (int) get_parameter("id_module_a");
673
@@ -384,7 +411,7 @@
674
 	return;
675
 }
676
 
677
-$remove_module_relation = (bool) get_parameter('remove_module_relation');
678
+
679
 if ($remove_module_relation) {
680
 	$id_relation = (int) get_parameter("id_relation");
681
 	if ($id_relation > 0) {
682
@@ -395,23 +422,25 @@
683
 	return;
684
 }
685
 
686
-$change_module_relation_updates = (bool) get_parameter('change_module_relation_updates');
687
+
688
 if ($change_module_relation_updates) {
689
 	$id_relation = (int) get_parameter("id_relation");
690
 	if ($id_relation > 0) {
691
 		$result = (bool) modules_change_relation_lock($id_relation);
692
 	}
693
+	
694
 	echo json_encode($result);
695
 	return;
696
 }
697
 
698
-$get_id_tag = (bool) get_parameter('get_id_tag', 0);
699
+
700
 if ($get_id_tag) {
701
 	$tag_name = get_parameter('tag_name');
702
-
703
+	
704
 	if ($tag_name) {
705
 		$tag_id = db_get_value('id_tag', 'ttag', 'name', $tag_name);
706
-	} else {
707
+	}
708
+	else {
709
 		$tag_id = 0;
710
 	}
711
 	
712
Index: include/functions_api.php
713
===================================================================
714
--- include/functions_api.php	(revision 10314)
715
+++ include/functions_api.php	(working copy)
716
@@ -757,7 +757,7 @@
717
 	$cascadeProtection = $other['data'][4];
718
 	$intervalSeconds = $other['data'][5];
719
 	$idOS = $other['data'][6];
720
-	$idServer = $other['data'][7];
721
+	$nameServer = $other['data'][7];
722
 	$customId = $other['data'][8];
723
 	$learningMode = $other['data'][9];
724
 	$disabled = $other['data'][10];
725
@@ -806,7 +806,8 @@
726
 	$cascadeProtection = $other['data'][4];
727
 	$intervalSeconds = $other['data'][5];
728
 	$idOS = $other['data'][6];
729
-	$idServer = $other['data'][7];
730
+	//$idServer = $other['data'][7];
731
+	$nameServer = $other['data'][7];
732
 	$customId = $other['data'][8];
733
 	$learningMode = $other['data'][9];
734
 	$disabled = $other['data'][10];
735
@@ -815,12 +816,12 @@
736
 	switch ($config["dbtype"]) {
737
 		case "mysql":
738
 			$sql1 = 'SELECT name
739
-				FROM tserver WHERE id_server =' . $idServer;
740
+				FROM tserver WHERE name LIKE "' . $nameServer . '"';
741
 			break;
742
 		case "postgresql":
743
 		case "oracle":
744
 			$sql1 = 'SELECT name
745
-				FROM tserver WHERE id_server =' . $idServer;
746
+				FROM tserver WHERE name LIKE \'' . $nameServer . '\'';
747
 			break;
748
 	}
749
 	
750
@@ -2476,7 +2477,7 @@
751
 	if (!$module_values) {
752
 		returnError('error_get_module_value_all_agents', 'Error getting module values from all agents.');
753
 	}
754
-	else{
755
+	else {
756
 		$data = array('type' => 'array', 'data' => $module_values);
757
 		
758
 		returnData('csv', $data, ';');
759
@@ -4856,7 +4857,7 @@
760
 		else {
761
 			$return = true;
762
 		}
763
-
764
+		
765
 		$data['type'] = 'string';
766
 		if ($return === false) {
767
 			$data['data'] = 0;
768
@@ -4865,7 +4866,7 @@
769
 			$data['data'] = $return;
770
 		}
771
 		returnData('string', $data);
772
-		return;		
773
+		return;
774
 	}
775
 	else {
776
 		returnError('error_parameter', 'Error in the parameters.');
777
@@ -4900,20 +4901,20 @@
778
 						<data><![CDATA[%s]]></data>
779
 					</module>
780
 				</agent_data>";
781
-		
782
+			
783
 			$xml = sprintf($xmlTemplate, io_safe_output(get_os_name($agent['id_os'])),
784
 				io_safe_output($agent['os_version']), $agent['intervalo'],
785
 				io_safe_output($agent['agent_version']), date('Y/m/d H:i:s', $time),
786
 				io_safe_output($agent['nombre']), $agent['timezone_offset'],
787
 				io_safe_output($agentModule['nombre']), io_safe_output($agentModule['descripcion']), modules_get_type_name($agentModule['id_tipo_modulo']), $data);
788
-		
789
-				
790
+			
791
+			
792
 			if (false === @file_put_contents($config['remote_config'] . '/' . io_safe_output($agent['nombre']) . '.' . $time . '.data', $xml)) {
793
 				returnError('error_file', 'Can save agent data xml.');
794
 			}
795
 			else {
796
 				returnData('string', array('type' => 'string', 'data' => $xml));
797
-				return;		
798
+				return;
799
 			}
800
 		}
801
 	}
802
@@ -6064,7 +6065,7 @@
803
 	$id_agent = agents_get_agent_id($agent_name);
804
 	$id_agent_module = db_get_value_filter('id_agente_modulo', 'tagente_modulo', array('id_agente' => $id_agent, 'nombre' => $module_name));
805
 	
806
-	$result = modules_change_disabled($id_agent_module, 1);
807
+	$result = modules_change_disabled($id_agent_module, 0);
808
 	
809
 	if ($result === NOERR) {
810
 		returnData('string', array('type' => 'string', 'data' => __('Correct module enable')));
811
@@ -6665,7 +6666,8 @@
812
 			'module_lag' => $server["module_lag"],
813
 			'threads' => $server["threads"],
814
 			'queued_modules' => $server["queued_modules"],
815
-			'keepalive' => $server['keepalive']
816
+			'keepalive' => $server['keepalive'],
817
+			'id_server' => $server['id_server']
818
 		);
819
 		
820
 		// servers_get_info() returns "<a http:....>servername</a>" for recon server's name.
821
Index: include/functions_ui.php
822
===================================================================
823
--- include/functions_ui.php	(revision 10314)
824
+++ include/functions_ui.php	(working copy)
825
@@ -1245,7 +1245,13 @@
826
 	}
827
 	$output .= "\n\t";
828
 	
829
+	
830
+	
831
+	
832
+	
833
+	////////////////////////////////////////////////////////////////////
834
 	//Load CSS
835
+	////////////////////////////////////////////////////////////////////
836
 	if (empty ($config['css'])) {
837
 		$config['css'] = array ();
838
 	}
839
@@ -1270,7 +1276,8 @@
840
 		}
841
 	}
842
 	
843
-	//First, if user has assigned a skin then try to use css files of skin subdirectory
844
+	//First, if user has assigned a skin then try to use css files of
845
+	//skin subdirectory
846
 	$isFunctionSkins = enterprise_include_once ('include/functions_skins.php');
847
 	if (!$login_ok) {
848
 		if ($isFunctionSkins !== ENTERPRISE_NOT_HOOK) {
849
@@ -1278,6 +1285,7 @@
850
 		}
851
 	}
852
 	
853
+	
854
 	$exists_css = false;
855
 	if ($login_ok and $isFunctionSkins !== ENTERPRISE_NOT_HOOK) {
856
 		//Checks if user's skin is available 
857
@@ -1305,12 +1313,17 @@
858
 			$config['css']);
859
 	}
860
 	
861
+	
862
+	
863
 	// Add the jquery UI styles CSS
864
 	$config['css']['jquery-UI'] = "include/styles/jquery-ui-1.10.0.custom.css";
865
-	
866
 	// Add the dialog styles CSS
867
 	$config['css']['dialog'] = "include/styles/dialog.css";
868
+	// Add the dialog styles CSS
869
+	$config['css']['dialog'] = "include/javascript/introjs.css";
870
 	
871
+	
872
+	
873
 	//We can't load empty and we loaded (conditionally) ie
874
 	$loaded = array ('', 'ie');
875
 	
876
@@ -1333,25 +1346,34 @@
877
 			$output .= '<link rel="stylesheet" href="' . $url_css . '" type="text/css" />'."\n\t";
878
 		}
879
 	}
880
+	////////////////////////////////////////////////////////////////////
881
 	//End load CSS
882
+	////////////////////////////////////////////////////////////////////
883
 	
884
+	
885
+	
886
+	
887
+	////////////////////////////////////////////////////////////////////
888
 	//Load JS
889
+	////////////////////////////////////////////////////////////////////
890
 	if (empty ($config['js'])) {
891
 		$config['js'] = array (); //If it's empty, false or not init set array to empty just in case
892
 	}
893
 	
894
+	
895
 	//Pandora specific JavaScript should go first
896
 	$config['js'] = array_merge (array ("pandora" => "include/javascript/pandora.js"), $config['js']);
897
-	
898
 	//Load base64 javascript library
899
 	$config['js']['base64'] = "include/javascript/encode_decode_base64.js";
900
-	
901
 	//Load webchat javascript library
902
 	$config['js']['webchat'] = "include/javascript/webchat.js";
903
-	
904
 	//Load qrcode library
905
 	$config['js']['qrcode'] = "include/javascript/qrcode.js";
906
+	//Load intro.js library (for bubbles and clippy)
907
+	$config['js']['intro'] = "include/javascript/intro.js";
908
+	$config['js']['clippy'] = "include/javascript/clippy.js";
909
 	
910
+	
911
 	//Load other javascript
912
 	//We can't load empty
913
 	$loaded = array ('');
914
@@ -1370,9 +1392,15 @@
915
 			$output .= '<script type="text/javascript" src="' . $url_js . '"></script>'."\n\t";
916
 		}
917
 	}
918
+	////////////////////////////////////////////////////////////////////
919
 	//End load JS
920
+	////////////////////////////////////////////////////////////////////
921
 	
922
+	
923
+	
924
+	////////////////////////////////////////////////////////////////////
925
 	//Load jQuery
926
+	////////////////////////////////////////////////////////////////////
927
 	if (empty ($config['jquery'])) {
928
 		$config['jquery'] = array (); //If it's empty, false or not init set array to empty just in case
929
 	}
930
@@ -1422,8 +1450,13 @@
931
 			$output .= '<script type="text/javascript" src="' . $url_js . '"></script>'."\n\t";
932
 		}
933
 	}
934
+	////////////////////////////////////////////////////////////////////
935
+	//End load JQuery
936
+	////////////////////////////////////////////////////////////////////
937
 	
938
 	
939
+	
940
+	
941
 	if ($config['flash_charts']) {
942
 		//Include the javascript for the js charts library
943
 		include_once($config["homedir"] . '/include/graphs/functions_flot.php');
944
@@ -1576,9 +1609,9 @@
945
 	
946
 	// Show GOTO FIRST button
947
 	if ($other_class == '') {
948
-		$output .= '<a class="pagination go_first" href="'.$url.'&amp;'.$offset_name.'=0">'.html_print_image ("images/go_first.png", true, array ("class" => "bot")).'</a>&nbsp;';
949
+		$output .= '<a class="pagination offset_0" href="'.$url.'&amp;' .$offset_name.'=0">'.html_print_image ("images/go_first.png", true, array ("class" => "bot")).'</a>&nbsp;';
950
 	} else {
951
-		$output .= "<a class='pagination $other_class go_first' href='$url.&amp;$offset_name=0'>".html_print_image ("images/go_first.png", true, array ("class" => "bot"))."</a>&nbsp;";
952
+		$output .= "<a class='pagination $other_class offset_0' href='$url.&amp;$offset_name=0'>".html_print_image ("images/go_first.png", true, array ("class" => "bot"))."</a>&nbsp;";
953
 	}
954
 
955
 	// Show PREVIOUS button
956
@@ -1588,9 +1621,9 @@
957
 			$index_page_prev = 0;
958
 			
959
 		if ($other_class == '') {
960
-				$output .= '<a class="pagination go_rewind" href="'.$url.'&amp;'.$offset_name.'='.$index_page_prev.'">'.html_print_image ("images/go_previous.png", true, array ("class" => "bot")).'</a>';
961
+			$output .= '<a class="pagination offset_' . $index_page_prev . '" href="'.$url.'&amp;'.$offset_name.'='.$index_page_prev.'">'.html_print_image ("images/go_previous.png", true, array ("class" => "bot")).'</a>';
962
 		} else {
963
-			$output .= "<a class='pagination $other_class go_rewind' href='$url &amp;$offset_name = $index_page_prev'>".html_print_image ("images/go_previous.png", true, array ("class" => "bot"))."</a>";
964
+			$output .= "<a class='pagination $other_class offset_$index_page_prev' href='$url &amp;$offset_name = $index_page_prev'>".html_print_image ("images/go_previous.png", true, array ("class" => "bot"))."</a>";
965
 		}
966
 	}
967
 	
968
@@ -1629,13 +1662,12 @@
969
 	// Index_counter stores max of blocks
970
 	if (($paginacion_maxima == 1) AND (($index_counter - $i) > 0)) {
971
 		$prox_bloque = ($i + ceil ($block_limit / 2)) * $pagination;
972
-		if ($prox_bloque > $count)
973
-			$prox_bloque = ($count -1) - $pagination;
974
-			
975
+		if ($prox_bloque >= $count)
976
+			$prox_bloque = (int) (($count - 1) / $pagination) * $pagination;
977
 		if ($other_class == '') {
978
-				$output .= '<a class="pagination go_fastforward" href="'.$url.'&amp;'.$offset_name.'='.$prox_bloque.'">'.html_print_image ("images/go_next.png", true, array ("class" => "bot")).'</a>';
979
+			$output .= '<a class="pagination offset_' . $prox_bloque . '" href="'.$url.'&amp;'.$offset_name.'='.$prox_bloque.'">'.html_print_image ("images/go_next.png", true, array ("class" => "bot")).'</a>';
980
 		} else {
981
-			$output .= "<a class='pagination $other_class go_fastforward' href='$url&amp;$offset_name=$prox_bloque'>".html_print_image ("images/go_next.png", true, array ("class" => "bot"))."</a>";
982
+			$output .= "<a class='pagination $other_class offset_$prox_bloque' href='$url&amp;$offset_name=$prox_bloque'>".html_print_image ("images/go_next.png", true, array ("class" => "bot"))."</a>";
983
 		}
984
 		$i = $index_counter;
985
 	}
986
@@ -1647,9 +1679,9 @@
987
 		$myoffset = floor (($count - 1) / $pagination) * $pagination;
988
 		
989
 		if ($other_class == '') {
990
-			$output .= '<a class="pagination go_last" href="'.$url.'&amp;'.$offset_name.'='.$myoffset.'">'.html_print_image ("images/go_last.png", true, array ("class" => "bot")).'</a>';
991
+			$output .= '<a class="pagination offset_' . $myoffset . '" href="'.$url. '&amp;'.$offset_name.'='.$myoffset.'">'.html_print_image ("images/go_last.png", true, array ("class" => "bot")).'</a>';
992
 		} else {
993
-			$output .= "<a class='pagination $other_class go_last' href='$url&amp;$offset_name=$myoffset'>".html_print_image ("images/go_last.png", true, array ("class" => "bot"))."</a>";
994
+			$output .= "<a class='pagination $other_class offset_$myoffset' href='$url&amp;$offset_name=$myoffset'>".html_print_image ("images/go_last.png", true, array ("class" => "bot"))."</a>";
995
 		}
996
 	}
997
 	
998
@@ -2268,7 +2300,8 @@
999
 	$buffer .= '<span style="display: inline-block; vertical-align: top; margin-top: 2px;">' . 
1000
 		ui_print_truncate_text($title, 38);
1001
 	if ($help != "")
1002
-		$buffer .= "<div class='head_help' style='float: right; margin-top: -3px !important; margin-left: 2px !important;'>" . ui_print_help_icon ($help, true, '', 'images/help_w.png') . "</div>";
1003
+		$buffer .= "<div class='head_help' style='float: right; margin-top: -3px !important; margin-left: 2px !important;'>" .
1004
+			ui_print_help_icon ($help, true, '', 'images/help_w.png') . "</div>";
1005
 	$buffer .= '</span></li></ul></div>';
1006
 	
1007
 	if (is_array($options)) {
1008
Index: include/functions.php
1009
===================================================================
1010
--- include/functions.php	(revision 10314)
1011
+++ include/functions.php	(working copy)
1012
@@ -768,6 +768,23 @@
1013
 	return get_parameter($name, 0);
1014
 }
1015
 
1016
+function get_cookie($name, $default = '') {
1017
+	if (isset($_COOKIE[$name])) {
1018
+		return $_COOKIE[$name];
1019
+	}
1020
+	else {
1021
+		return $default;
1022
+	}
1023
+}
1024
+
1025
+function set_cookie($name, $value) {
1026
+	if (is_null($value)) {
1027
+		unset($_COOKIE[$value]);
1028
+		setcookie($value, null, -1, '/');
1029
+	}
1030
+	setcookie($name, $value);
1031
+}
1032
+
1033
 /** 
1034
  * Get a parameter from a request.
1035
  *
1036
@@ -1430,9 +1447,11 @@
1037
  * 
1038
  * @return array SNMP result.
1039
  */
1040
-function get_snmpwalk($ip_target, $snmp_version, $snmp_community = '', $snmp3_auth_user = '',
1041
-	$snmp3_security_level = '', $snmp3_auth_method = '', $snmp3_auth_pass = '',
1042
-	$snmp3_privacy_method = '', $snmp3_privacy_pass = '', $quick_print = 0, $base_oid = "", $snmp_port = '') {
1043
+function get_snmpwalk($ip_target, $snmp_version, $snmp_community = '',
1044
+	$snmp3_auth_user = '', $snmp3_security_level = '',
1045
+	$snmp3_auth_method = '', $snmp3_auth_pass = '',
1046
+	$snmp3_privacy_method = '', $snmp3_privacy_pass = '',
1047
+	$quick_print = 0, $base_oid = "", $snmp_port = '') {
1048
 	
1049
 	global $config;
1050
 	
1051
@@ -1464,7 +1483,7 @@
1052
 	else {
1053
 		$snmpwalk_bin = $config['snmpwalk'];
1054
 	}
1055
-
1056
+	
1057
 	switch (PHP_OS) {
1058
 		case "WIN32":
1059
 		case "WINNT":
1060
@@ -1480,16 +1499,54 @@
1061
 	$rc = 0;
1062
 	switch ($snmp_version) {
1063
 		case '3':
1064
-			exec ($snmpwalk_bin . ' -m ALL -v 3 -u ' . escapeshellarg($snmp3_auth_user) . ' -A ' . escapeshellarg($snmp3_auth_pass) . ' -l ' . escapeshellarg($snmp3_security_level) . ' -a ' . escapeshellarg($snmp3_auth_method) . ' -x ' . escapeshellarg($snmp3_privacy_method) . ' -X ' . escapeshellarg($snmp3_privacy_pass) . ' ' . escapeshellarg($ip_target)  . ' ' . $base_oid . ' 2> ' . $error_redir_dir, $output, $rc);
1065
+			switch ($snmp3_security_level) {
1066
+				case "authNoPriv":
1067
+					$command_str = $snmpwalk_bin .
1068
+						' -m ALL -v 3' .
1069
+						' -u ' . escapeshellarg($snmp3_auth_user) .
1070
+						' -A ' . escapeshellarg($snmp3_auth_pass) .
1071
+						' -l ' . escapeshellarg($snmp3_security_level) .
1072
+						' -a ' . escapeshellarg($snmp3_auth_method) .
1073
+						' ' . escapeshellarg($ip_target)  .
1074
+						' ' . $base_oid .
1075
+						' 2> ' . $error_redir_dir;
1076
+					break;
1077
+				case "noAuthNoPriv":
1078
+					$command_str = $snmpwalk_bin .
1079
+						' -m ALL -v 3' .
1080
+						' -u ' . escapeshellarg($snmp3_auth_user) .
1081
+						' -l ' . escapeshellarg($snmp3_security_level) .
1082
+						' ' . escapeshellarg($ip_target)  .
1083
+						' ' . $base_oid .
1084
+						' 2> ' . $error_redir_dir;
1085
+					break;
1086
+				default:
1087
+					$command_str = $snmpwalk_bin .
1088
+						' -m ALL -v 3' .
1089
+						' -u ' . escapeshellarg($snmp3_auth_user) .
1090
+						' -A ' . escapeshellarg($snmp3_auth_pass) .
1091
+						' -l ' . escapeshellarg($snmp3_security_level) .
1092
+						' -a ' . escapeshellarg($snmp3_auth_method) .
1093
+						' -x ' . escapeshellarg($snmp3_privacy_method) .
1094
+						' -X ' . escapeshellarg($snmp3_privacy_pass) .
1095
+						' ' . escapeshellarg($ip_target)  .
1096
+						' ' . $base_oid .
1097
+						' 2> ' . $error_redir_dir;
1098
+					break;
1099
+			}
1100
 			break;
1101
 		case '2':
1102
 		case '2c':
1103
 		case '1':
1104
 		default:
1105
-			exec ($snmpwalk_bin . ' -m ALL -v ' . escapeshellarg($snmp_version) . ' -c ' . escapeshellarg($snmp_community) . ' ' . escapeshellarg($ip_target)  . ' ' . $base_oid . ' 2> ' . $error_redir_dir, $output, $rc);	
1106
+			$command_str = $snmpwalk_bin . ' -m ALL -v ' . escapeshellarg($snmp_version) . ' -c ' . escapeshellarg($snmp_community) . ' ' . escapeshellarg($ip_target)  . ' ' . $base_oid . ' 2> ' . $error_redir_dir;
1107
 			break;
1108
 	}
1109
 	
1110
+	//html_debug_print($command_str);
1111
+	
1112
+	exec($command_str, $output, $rc);
1113
+	
1114
 	// Parse the output of snmpwalk
1115
 	$snmpwalk = array();
1116
 	foreach ($output as $line) {
1117
@@ -2134,4 +2191,29 @@
1118
 	return $news;
1119
 }
1120
 
1121
+
1122
+/**
1123
+ * Print audit data in CSV format.
1124
+ *
1125
+ * @param array Audit data.
1126
+ *
1127
+ */
1128
+function print_audit_csv ($data) {
1129
+	global $config;
1130
+	global $graphic_type;
1131
+
1132
+	$config['ignore_callback'] = true;
1133
+	while (@ob_end_clean ());
1134
+	
1135
+	header("Content-type: application/octet-stream");
1136
+	header("Content-Disposition: attachment; filename=audit_log".date("Y-m-d_His").".csv");
1137
+	header("Pragma: no-cache");
1138
+	header("Expires: 0");
1139
+	
1140
+	echo __('User') . ';' . __('Action') . ';' . __('Date') . ';' . __('Source ID') . ';'. __('Comments') ."\n";
1141
+	foreach ($data as $line) {
1142
+		echo io_safe_output($line['id_usuario']) . ';' .  io_safe_output($line['accion']) . ';' .  $line['fecha'] . ';' .  $line['ip_origen'] . ';'.  io_safe_output($line['descripcion']). "\n";
1143
+	}
1144
+}
1145
+
1146
 ?>
1147
Index: include/functions_agents.php
1148
===================================================================
1149
--- include/functions_agents.php	(revision 10314)
1150
+++ include/functions_agents.php	(working copy)
1151
@@ -360,6 +360,11 @@
1152
 		}
1153
 	}
1154
 	
1155
+	//Fix for postgresql
1156
+	if (empty($filter['id_agente'])) {
1157
+		unset($filter['id_agente']);
1158
+	}
1159
+	
1160
 	$where = db_format_array_where_clause_sql ($filter, 'AND', '');
1161
 	
1162
 	$where_nogroup = db_format_array_where_clause_sql ($filter_nogroup, 'AND', '');
1163
@@ -412,6 +417,7 @@
1164
 				return $sql;
1165
 			else
1166
 				$agents = db_get_all_rows_sql($sql);
1167
+			
1168
 			break;
1169
 		case "oracle":
1170
 			$set = array();
1171
Index: include/functions_graph.php
1172
===================================================================
1173
--- include/functions_graph.php	(revision 10314)
1174
+++ include/functions_graph.php	(working copy)
1175
@@ -102,13 +102,14 @@
1176
 	
1177
 	foreach ($chart_array as $item) {
1178
 		if ($series_suffix != '') {
1179
-			$item['sum'] = $item['sum'.$series_suffix];
1180
-			$item['min'] = $item['min'.$series_suffix];
1181
-			$item['max'] = $item['max'.$series_suffix];
1182
+			$item['sum'] = $item['sum' . $series_suffix];
1183
+			$item['min'] = $item['min' . $series_suffix];
1184
+			$item['max'] = $item['max' . $series_suffix];
1185
 		}
1186
 		
1187
 		//Get stats for normal graph
1188
 		if (isset($item['sum']) && $item['sum']) {
1189
+			
1190
 			//Sum all values later divide by the number of elements
1191
 			$stats['sum']['avg'] = $stats['sum']['avg'] + $item['sum'];
1192
 			
1193
@@ -245,6 +246,7 @@
1194
 	$is_unknown = $start_unknown;
1195
 	
1196
 	// Calculate chart data
1197
+	$last_known = $previous_data;
1198
 	for ($i = 0; $i < $resolution; $i++) {
1199
 		$timestamp = $datelimit + ($interval * $i);
1200
 		
1201
@@ -270,6 +272,7 @@
1202
 				$interval_min = $data[$data_i]['datos'];
1203
 			}
1204
 			$total += $data[$data_i]['datos'];
1205
+			$last_known = $data[$data_i]['datos'];
1206
 			$count++;
1207
 			$data_i++;
1208
 		}
1209
@@ -399,7 +402,6 @@
1210
 				$chart[$timestamp]['sum'.$series_suffix] = $total;
1211
 				$chart[$timestamp]['min'.$series_suffix] = $interval_min;
1212
 			}
1213
-			$previous_data = $total;
1214
 		// Compressed data
1215
 		}
1216
 		else {
1217
@@ -415,12 +417,12 @@
1218
 			}
1219
 			else {
1220
 				if ($avg_only) {
1221
-					$chart[$timestamp]['sum'.$series_suffix] = $previous_data;
1222
+					$chart[$timestamp]['sum'.$series_suffix] = $last_known;
1223
 				}
1224
 				else {
1225
-					$chart[$timestamp]['max'.$series_suffix] = $previous_data;
1226
-					$chart[$timestamp]['sum'.$series_suffix] = $previous_data;
1227
-					$chart[$timestamp]['min'.$series_suffix] = $previous_data;
1228
+					$chart[$timestamp]['max'.$series_suffix] = $last_known;
1229
+					$chart[$timestamp]['sum'.$series_suffix] = $last_known;
1230
+					$chart[$timestamp]['min'.$series_suffix] = $last_known;
1231
 				}
1232
 			}
1233
 		}
1234
@@ -580,7 +582,7 @@
1235
 			if (!$projection) {
1236
 				return fs_error_image ();
1237
 			}
1238
-			else{
1239
+			else {
1240
 				return fs_error_image ();
1241
 			}
1242
 		}
1243
@@ -1103,6 +1105,7 @@
1244
 		$countAvg = 0;
1245
 		
1246
 		// Calculate chart data
1247
+		$last_known = $previous_data;
1248
 		for ($l = 0; $l < $resolution; $l++) {
1249
 			$countAvg ++;
1250
 			
1251
@@ -1117,8 +1120,8 @@
1252
 			$count = 0;
1253
 			
1254
 			// Read data that falls in the current interval
1255
-			$interval_min = $previous_data;
1256
-			$interval_max = $previous_data;
1257
+			$interval_min = $last_known;
1258
+			$interval_max = $last_known;
1259
 			while (isset ($data[$j]) && $data[$j]['utimestamp'] >= $timestamp && $data[$j]['utimestamp'] < ($timestamp + $interval)) {
1260
 				if ($data[$j]['datos'] > $interval_max) {
1261
 					$interval_max = $data[$j]['datos'];
1262
@@ -1127,6 +1130,7 @@
1263
 					$interval_min = $data[$j]['datos'];
1264
 				}
1265
 				$total += $data[$j]['datos'];
1266
+				$last_known = $data[$j]['datos'];
1267
 				$count++;
1268
 				$j++;
1269
 			}
1270
@@ -1153,18 +1157,14 @@
1271
 			if ($count > 0) {
1272
 				//$graph_values[$i][$timestamp] = $total * $weight_list[$i];
1273
 				$temp_graph_values[$timestamp_short] = $total * $weight_list[$i];
1274
-				
1275
-				$previous_data = $total;
1276
 			}
1277
 			else {
1278
 				// Compressed data
1279
 				if ($uncompressed_module || ($timestamp > time ())) {
1280
-					//$graph_values[$i][$timestamp] = 0;
1281
 					$temp_graph_values[$timestamp_short] = 0;
1282
 				}
1283
 				else {
1284
-					//$graph_values[$i][$timestamp] = $previous_data * $weight_list[$i];
1285
-					$temp_graph_values[$timestamp_short] = $previous_data * $weight_list[$i];
1286
+					$temp_graph_values[$timestamp_short] = $last_known * $weight_list[$i];
1287
 				}
1288
 			}
1289
 			
1290
@@ -1459,16 +1459,19 @@
1291
 		$filter['id_agente'] = $id_agent; 
1292
 	}
1293
 	
1294
-	$fields = array('SUM(critical_count) Critical', 
1295
-		'SUM(warning_count) Warning', 
1296
-		'SUM(normal_count) Normal', 
1297
-		'SUM(unknown_count) Unknown');
1298
+	$fields = array('SUM(critical_count) AS Critical', 
1299
+		'SUM(warning_count) AS Warning', 
1300
+		'SUM(normal_count) AS Normal', 
1301
+		'SUM(unknown_count) AS Unknown');
1302
 	
1303
 	if ($show_not_init) {
1304
 		$fields[] = 'SUM(notinit_count) "Not init"';
1305
 	}
1306
 	
1307
 	$data = db_get_row_filter('tagente', $filter, $fields);
1308
+	if (empty($data)) {
1309
+		$data = array();
1310
+	}
1311
 	
1312
 	array_walk($data, 'truncate_negatives');
1313
 	
1314
@@ -1796,6 +1799,7 @@
1315
 	if ($modules === false)
1316
 		$modules = array ();
1317
 	
1318
+	$data = array();
1319
 	foreach ($modules as $module) {
1320
 		$agent_name = agents_get_name ($module['id_agente'], "none");
1321
 		
1322
@@ -1816,7 +1820,8 @@
1323
 	$water_mark = array('file' => $config['homedir'] .  "/images/logo_vertical_water.png",
1324
 		'url' => ui_get_full_url("/images/logo_vertical_water.png"));
1325
 		
1326
-	return hbar_graph($config['flash_charts'], $data, $width, $height, array(),
1327
+	return hbar_graph($config['flash_charts'],
1328
+		$data, $width, $height, array(),
1329
 		array(), "", "", true, "",
1330
 		$water_mark,
1331
 		$config['fontpath'], $config['font_size'], false);
1332
@@ -2670,6 +2675,7 @@
1333
 	$max_value = 0;
1334
 	
1335
 	// Calculate chart data
1336
+	$last_known = $previous_data;
1337
 	for ($i = 0; $i < $resolution; $i++) {
1338
 		$timestamp = $datelimit + ($interval * $i);
1339
 		
1340
@@ -2689,6 +2695,7 @@
1341
 				$count++;
1342
 			}
1343
 			
1344
+			$last_known = $data[$j]['datos'];
1345
 			$j++;
1346
 		}
1347
 		
1348
@@ -2796,43 +2803,20 @@
1349
 			//New code set 0 if there is a 0
1350
 			//Please check the incident #665
1351
 			//http://192.168.50.2/integria/index.php?sec=incidents&sec2=operation/incidents/incident_dashboard_detail&id=665
1352
-			
1353
-			
1354
 			$chart[$timestamp]['sum'.$series_suffix] = 0;
1355
-			$previous_data = 0;
1356
-			
1357
-			//Old code that make a AVG
1358
-			
1359
-			//~ if ($avg_only) {
1360
-				//~ $chart[$timestamp]['sum'.$series_suffix] = $total;
1361
-			//~ }
1362
-			//~ else {
1363
-				//~ $chart[$timestamp]['sum'.$series_suffix] = $total;
1364
-				//~ $chart[$timestamp + 1] = array ('sum'.$series_suffix => 0,
1365
-					//~ //'count' => 0,
1366
-					//~ //'timestamp_bottom' => $timestamp,
1367
-					//~ //'timestamp_top' => $timestamp + $interval,
1368
-					//~ 'min'.$series_suffix => 0,
1369
-					//~ 'max'.$series_suffix => 0,
1370
-					//~ 'event'.$series_suffix => $event_value,
1371
-					//~ 'alert'.$series_suffix => $alert_value);
1372
-			//~ }
1373
-			//~ $previous_data = 0;
1374
 		}
1375
 		else if ($zero == 1) { // Just zeros
1376
 			$chart[$timestamp]['sum'.$series_suffix] = 0;
1377
-			$previous_data = 0;
1378
 		}
1379
 		else if ($count > 0) { // No zeros
1380
 			$chart[$timestamp]['sum'.$series_suffix] = $total;
1381
-			$previous_data = $total;
1382
 		}
1383
 		else { // Compressed data
1384
 			if ($uncompressed_module || ($timestamp > time ()) || $is_unknown) {
1385
 				$chart[$timestamp]['sum'.$series_suffix] = 0;
1386
 			}
1387
 			else {
1388
-				$chart[$timestamp]['sum'.$series_suffix] = $previous_data;
1389
+				$chart[$timestamp]['sum'.$series_suffix] = $last_known;
1390
 			}
1391
 		}
1392
 		
1393
@@ -3279,7 +3263,7 @@
1394
  * @param integer date date
1395
  */
1396
 function grafico_modulo_string ($agent_module_id, $period, $show_events,
1397
-	$width, $height , $title, $unit_name, $show_alerts, $avg_only = 0, $pure=0,
1398
+	$width, $height , $title, $unit_name, $show_alerts, $avg_only = 0, $pure = 0,
1399
 	$date = 0, $only_image = false, $homeurl = '', $adapt_key = '', $ttl = 1, $menu = true) {
1400
 	global $config;
1401
 	global $graphic_type;
1402
@@ -3381,6 +3365,7 @@
1403
 	}
1404
 	
1405
 	// Calculate chart data
1406
+	$last_known = $previous_data;
1407
 	for ($i = 0; $i < $resolution; $i++) {
1408
 		$timestamp = $datelimit + ($interval * $i);
1409
 		
1410
@@ -3388,6 +3373,7 @@
1411
 		$total = 0;	
1412
 		// Read data that falls in the current interval
1413
 		while (isset($data[$j]) && isset ($data[$j]) !== null && $data[$j]['utimestamp'] >= $timestamp && $data[$j]['utimestamp'] <= ($timestamp + $interval)) {
1414
+			$last_known = $data[$j];
1415
 			$count++;
1416
 			$j++;
1417
 		}
1418
@@ -3437,7 +3423,7 @@
1419
 		//The order in chart array is very important!!!!
1420
 		if ($show_events) {
1421
 			$chart[$timestamp]['event'] = $event_value;
1422
-		}	
1423
+		}
1424
 		
1425
 		if ($show_alerts) {
1426
 			$chart[$timestamp]['alert'] = $alert_value;
1427
@@ -3449,11 +3435,10 @@
1428
 		
1429
 		if ($count > 0) {
1430
 			$chart[$timestamp]['sum'] = $count;
1431
-			$previous_data = $total;
1432
 		}
1433
 		else {
1434
 			// Compressed data
1435
-			$chart[$timestamp]['sum'] = $previous_data;
1436
+			$chart[$timestamp]['sum'] = $last_known;
1437
 		}
1438
 		
1439
 		if (!$avg_only) {
1440
@@ -4106,47 +4091,304 @@
1441
 /**
1442
  * Print a solarburst graph with a representation of all the groups, agents, module groups and modules grouped
1443
  */
1444
-function graph_monitor_wheel ($data, $unit, $width = 700, $height = 700) {
1445
+function graph_monitor_wheel ($width = 500, $height = 600) {
1446
 	global $config;
1447
 
1448
-	$data = array();
1449
-
1450
 	include_once ($config['homedir'] . "/include/functions_users.php");
1451
-	//include_once ($config['homedir'] . "/include/functions_groups.php");
1452
+	include_once ($config['homedir'] . "/include/functions_groups.php");
1453
 	include_once ($config['homedir'] . "/include/functions_agents.php");
1454
-	//include_once ($config['homedir'] . "/include/functions_modules.php");
1455
+	include_once ($config['homedir'] . "/include/functions_modules.php");
1456
 
1457
+	$graph_data = array();
1458
+
1459
 	$groups = users_get_groups(false, "AR", false, true);
1460
 
1461
+	$data_groups = array();
1462
 	if (!empty($groups)) {
1463
+		$groups_aux = $groups;
1464
+		$data_groups = groups_get_tree($groups_aux);
1465
+		$groups_aux = $groups = null;
1466
+	}
1467
+
1468
+	if (!empty($data_groups)) {
1469
 		$filter = array('id_grupo' => array_keys($groups));
1470
 		$fields = array('id_agente', 'id_parent', 'id_grupo', 'nombre');
1471
 		$agents = agents_get_agents($filter, $fields);
1472
 
1473
 		if (!empty($agents)) {
1474
 			$agents_id = array();
1475
+			$agents_aux = array();
1476
 			foreach ($agents as $key => $agent) {
1477
-				$agents_id[] = $agent['id_agente'];
1478
+				$agents_aux[$agent['id_agente']] = $agent;
1479
 			}
1480
+			$agents = $agents_aux;
1481
+			$agents_aux = null;
1482
 			$fields = array('id_agente_modulo', 'id_agente', 'id_module_group', 'nombre');
1483
 
1484
 			$module_groups = modules_get_modulegroups();
1485
-			$modules = agents_get_modules($agents_id, $fields);
1486
+			$module_groups[0] = __('Not assigned');
1487
+			$modules = agents_get_modules(array_keys($agents), '*');
1488
 
1489
+			$data_agents = array();
1490
 			if (!empty($modules)) {
1491
-				
1492
+				foreach ($modules as $key => $module) {
1493
+					$module_id = (int) $module['id_agente_modulo'];
1494
+					$agent_id = (int) $module['id_agente'];
1495
+					$module_group_id = (int) $module['id_module_group'];
1496
+					$module_name = $module['nombre'];
1497
+					$module_status = modules_get_agentmodule_status($module_id);
1498
+
1499
+					if (!isset($data_agents[$agent_id])) {
1500
+						$data_agents[$agent_id] = array();
1501
+						$data_agents[$agent_id]['id'] = $agent_id;
1502
+						$data_agents[$agent_id]['name'] = $agents[$agent_id]['nombre'];
1503
+						$data_agents[$agent_id]['group'] = (int) $agents[$agent_id]['id_grupo'];
1504
+						$data_agents[$agent_id]['type'] = 'agent';
1505
+						$data_agents[$agent_id]['size'] = 30;
1506
+						$data_agents[$agent_id]['children'] = array();
1507
+
1508
+						$tooltip_content = __('Agent') . ": <b>" . $data_agents[$agent_id]['name'] . "</b>";
1509
+						$data_agents[$agent_id]['tooltip_content'] = $tooltip_content;
1510
+
1511
+						$data_agents[$agent_id]['modules_critical'] = 0;
1512
+						$data_agents[$agent_id]['modules_warning'] = 0;
1513
+						$data_agents[$agent_id]['modules_normal'] = 0;
1514
+						$data_agents[$agent_id]['modules_not_init'] = 0;
1515
+						$data_agents[$agent_id]['modules_not_normal'] = 0;
1516
+						$data_agents[$agent_id]['modules_unknown'] = 0;
1517
+
1518
+						$data_agents[$agent_id]['color'] = COL_UNKNOWN;
1519
+
1520
+						unset($agents[$agent_id]);
1521
+					}
1522
+					if (!isset($data_agents[$agent_id]['children'][$module_group_id])) {
1523
+						$data_agents[$agent_id]['children'][$module_group_id] = array();
1524
+						$data_agents[$agent_id]['children'][$module_group_id]['id'] = $module_group_id;
1525
+						$data_agents[$agent_id]['children'][$module_group_id]['name'] = $module_groups[$module_group_id];
1526
+						$data_agents[$agent_id]['children'][$module_group_id]['type'] = 'module_group';
1527
+						$data_agents[$agent_id]['children'][$module_group_id]['size'] = 10;
1528
+						$data_agents[$agent_id]['children'][$module_group_id]['children'] = array();
1529
+
1530
+						$tooltip_content = __('Module group') . ": <b>" . $module_groups[$module_group_id] . "</b>";
1531
+						$data_agents[$agent_id]['children'][$module_group_id]['tooltip_content'] = $tooltip_content;
1532
+
1533
+						$data_agents[$agent_id]['children'][$module_group_id]['modules_critical'] = 0;
1534
+						$data_agents[$agent_id]['children'][$module_group_id]['modules_warning'] = 0;
1535
+						$data_agents[$agent_id]['children'][$module_group_id]['modules_normal'] = 0;
1536
+						$data_agents[$agent_id]['children'][$module_group_id]['modules_not_init'] = 0;
1537
+						$data_agents[$agent_id]['children'][$module_group_id]['modules_not_normal'] = 0;
1538
+						$data_agents[$agent_id]['children'][$module_group_id]['modules_unknown'] = 0;
1539
+
1540
+						$data_agents[$agent_id]['children'][$module_group_id]['color'] = COL_UNKNOWN;
1541
+					}
1542
+					
1543
+					switch ($module_status) {
1544
+						case AGENT_MODULE_STATUS_CRITICAL_BAD:
1545
+						case AGENT_MODULE_STATUS_CRITICAL_ALERT:
1546
+							$data_agents[$agent_id]['modules_critical']++;
1547
+							$data_agents[$agent_id]['children'][$module_group_id]['modules_critical']++;
1548
+							break;
1549
+						
1550
+						case AGENT_MODULE_STATUS_WARNING:
1551
+						case AGENT_MODULE_STATUS_WARNING_ALERT:
1552
+							$data_agents[$agent_id]['modules_warning']++;
1553
+							$data_agents[$agent_id]['children'][$module_group_id]['modules_warning']++;
1554
+							break;
1555
+
1556
+						case AGENT_MODULE_STATUS_NORMAL:
1557
+						case AGENT_MODULE_STATUS_NORMAL_ALERT:
1558
+							$data_agents[$agent_id]['modules_normal']++;
1559
+							$data_agents[$agent_id]['children'][$module_group_id]['modules_normal']++;
1560
+							break;
1561
+
1562
+						case AGENT_MODULE_STATUS_NOT_INIT:
1563
+							$data_agents[$agent_id]['modules_not_init']++;
1564
+							$data_agents[$agent_id]['children'][$module_group_id]['modules_not_init']++;
1565
+							break;
1566
+
1567
+						case AGENT_MODULE_STATUS_NOT_NORMAL:
1568
+							$data_agents[$agent_id]['modules_not_normal']++;
1569
+							$data_agents[$agent_id]['children'][$module_group_id]['modules_not_normal']++;
1570
+							break;
1571
+
1572
+						case AGENT_MODULE_STATUS_NO_DATA:
1573
+						case AGENT_MODULE_STATUS_UNKNOWN:
1574
+							$data_agents[$agent_id]['modules_unknown']++;
1575
+							$data_agents[$agent_id]['children'][$module_group_id]['modules_unknown']++;
1576
+							break;
1577
+					}
1578
+
1579
+					if ($data_agents[$agent_id]['modules_critical'] > 0) {
1580
+						$data_agents[$agent_id]['color'] = COL_CRITICAL;
1581
+					}
1582
+					else if ($data_agents[$agent_id]['modules_warning'] > 0) {
1583
+						$data_agents[$agent_id]['color'] = COL_WARNING;
1584
+					}
1585
+					else if ($data_agents[$agent_id]['modules_not_normal'] > 0) {
1586
+						$data_agents[$agent_id]['color'] = COL_WARNING;
1587
+					}
1588
+					else if ($data_agents[$agent_id]['modules_unknown'] > 0) {
1589
+						$data_agents[$agent_id]['color'] = COL_UNKNOWN;
1590
+					}
1591
+					else if ($data_agents[$agent_id]['modules_normal'] > 0) {
1592
+						$data_agents[$agent_id]['color'] = COL_NORMAL;
1593
+					}
1594
+					else {
1595
+						$data_agents[$agent_id]['color'] = COL_NOTINIT;
1596
+					}
1597
+
1598
+					if ($data_agents[$agent_id]['children'][$module_group_id]['modules_critical'] > 0) {
1599
+						$data_agents[$agent_id]['children'][$module_group_id]['color'] = COL_CRITICAL;
1600
+					}
1601
+					else if ($data_agents[$agent_id]['children'][$module_group_id]['modules_warning'] > 0) {
1602
+						$data_agents[$agent_id]['children'][$module_group_id]['color'] = COL_WARNING;
1603
+					}
1604
+					else if ($data_agents[$agent_id]['children'][$module_group_id]['modules_not_normal'] > 0) {
1605
+						$data_agents[$agent_id]['children'][$module_group_id]['color'] = COL_WARNING;
1606
+					}
1607
+					else if ($data_agents[$agent_id]['children'][$module_group_id]['modules_unknown'] > 0) {
1608
+						$data_agents[$agent_id]['children'][$module_group_id]['color'] = COL_UNKNOWN;
1609
+					}
1610
+					else if ($data_agents[$agent_id]['children'][$module_group_id]['modules_normal'] > 0) {
1611
+						$data_agents[$agent_id]['children'][$module_group_id]['color'] = COL_NORMAL;
1612
+					}
1613
+					else {
1614
+						$data_agents[$agent_id]['children'][$module_group_id]['color'] = COL_NOTINIT;
1615
+					}
1616
+					
1617
+					$data_module = array();
1618
+					$data_module['id'] = $module_id;
1619
+					$data_module['name'] = $module_name;
1620
+					$data_module['type'] = 'module';
1621
+					$data_module['size'] = 10;
1622
+
1623
+					$tooltip_content = __('Module') . ": <b>" . $module_name . "</b>";
1624
+					$data_module['tooltip_content'] = $tooltip_content;
1625
+
1626
+					switch ($module_status) {
1627
+						case AGENT_MODULE_STATUS_CRITICAL_BAD:
1628
+						case AGENT_MODULE_STATUS_CRITICAL_ALERT:
1629
+							$data_module['color'] = COL_CRITICAL;
1630
+							break;
1631
+						
1632
+						case AGENT_MODULE_STATUS_WARNING:
1633
+						case AGENT_MODULE_STATUS_WARNING_ALERT:
1634
+							$data_module['color'] = COL_WARNING;
1635
+							break;
1636
+
1637
+						case AGENT_MODULE_STATUS_NORMAL:
1638
+						case AGENT_MODULE_STATUS_NORMAL_ALERT:
1639
+							$data_module['color'] = COL_NORMAL;
1640
+							break;
1641
+
1642
+						case AGENT_MODULE_STATUS_NOT_INIT:
1643
+							$data_module['color'] = COL_NOTINIT;
1644
+							break;
1645
+
1646
+						case AGENT_MODULE_STATUS_NOT_NORMAL:
1647
+							$data_module['color'] = COL_WARNING;
1648
+							break;
1649
+
1650
+						case AGENT_MODULE_STATUS_NO_DATA:
1651
+						case AGENT_MODULE_STATUS_UNKNOWN:
1652
+						default:
1653
+							$data_module['color'] = COL_UNKNOWN;
1654
+							break;
1655
+					}
1656
+
1657
+					$data_agents[$agent_id]['children'][$module_group_id]['children'][] = $data_module;
1658
+
1659
+					unset($modules[$module_id]);
1660
+				}
1661
 			}
1662
+			foreach ($agents as $id => $agent) {
1663
+				if (!isset($data_agents[$id])) {
1664
+					$data_agents[$id] = array();
1665
+					$data_agents[$id]['id'] = (int) $id;
1666
+					$data_agents[$id]['name'] = $agent['nombre'];
1667
+					$data_agents[$id]['type'] = 'agent';
1668
+					$data_agents[$id]['color'] = COL_NOTINIT;
1669
+				}
1670
+			}
1671
+			$agents = null;
1672
 		}
1673
 	}
1674
 
1675
+	function iterate_group_array ($groups, &$data_agents) {
1676
+		
1677
+		$data = array();
1678
 
1679
-	if (empty ($data)) {
1680
-		return fs_error_image ();
1681
+		foreach ($groups as $id => $group) {
1682
+
1683
+			$group_aux = array();
1684
+			$group_aux['id'] = (int) $id;
1685
+			$group_aux['name'] = $group['nombre'];
1686
+			$group_aux['parent'] = (int) $group['parent'];
1687
+			$group_aux['type'] = 'group';
1688
+			$group_aux['size'] = 100;
1689
+			$group_aux['status'] = groups_get_status($id);
1690
+
1691
+			switch ($group_aux['status']) {
1692
+				case AGENT_STATUS_CRITICAL:
1693
+					$group_aux['color'] = COL_CRITICAL;
1694
+					break;
1695
+				
1696
+				case AGENT_STATUS_WARNING:
1697
+				case AGENT_STATUS_ALERT_FIRED:
1698
+					$group_aux['color'] = COL_WARNING;
1699
+					break;
1700
+
1701
+				case AGENT_STATUS_NORMAL:
1702
+					$group_aux['color'] = COL_NORMAL;
1703
+					break;
1704
+
1705
+				case AGENT_STATUS_UNKNOWN:
1706
+				default:
1707
+					$group_aux['color'] = COL_UNKNOWN;
1708
+					break;
1709
+			}
1710
+
1711
+			$tooltip_content = html_print_image("images/groups_small/" . $group['icon'] . ".png", true) . "&nbsp;" . __('Group') . ": <b>" . $group_aux['name'] . "</b>";
1712
+			$group_aux['tooltip_content'] = $tooltip_content;
1713
+
1714
+			if (!isset($group['children']))
1715
+				$group_aux['children'] = array();
1716
+			if (!empty($group['children']))
1717
+				$group_aux['children'] = iterate_group_array($group['children']);
1718
+
1719
+			$agents = extract_agents_with_group_id($data_agents, (int) $id);
1720
+
1721
+			if (!empty($agents))
1722
+				$group_aux['children'] = array_merge($group_aux['children'], $agents);
1723
+			
1724
+			$data[] = $group_aux;
1725
+		}
1726
+
1727
+		return $data;
1728
 	}
1729
 
1730
+	function extract_agents_with_group_id (&$agents, $group_id) {
1731
+		$valid_agents = array();
1732
+		foreach ($agents as $id => $agent) {
1733
+			if (isset($agent['group']) && $agent['group'] == $group_id) {
1734
+				$valid_agents[$id] = $agent;
1735
+				unset($agents[$id]);
1736
+			}
1737
+		}
1738
+		if (!empty($valid_agents))
1739
+			return $valid_agents;
1740
+		else
1741
+			return false;
1742
+	}
1743
+
1744
+	$graph_data = array('name' => __('Main node'), 'children' => iterate_group_array($data_groups, $data_agents));
1745
+	
1746
+	if (empty($graph_data['children']))
1747
+		return fs_error_image();
1748
+
1749
 	include_once($config['homedir'] . "/include/graphs/functions_d3.php");
1750
 
1751
-	return d3_tree_map_graph ($data, $width, $height, true);
1752
+	return d3_sunburst_graph ($graph_data, $width, $height, true);
1753
 }
1754
 
1755
 ?>
1756
Index: include/functions_events.php
1757
===================================================================
1758
--- include/functions_events.php	(revision 10314)
1759
+++ include/functions_events.php	(working copy)
1760
@@ -162,7 +162,16 @@
1761
 						(SELECT ack_utimestamp FROM $table WHERE id_evento = MAX(te.id_evento)) AS ack_utimestamp
1762
 					FROM $table te
1763
 					WHERE 1=1 " . $sql_post . "
1764
-					GROUP BY estado, evento, id_agentmodule, id_evento, id_agente, id_usuario, id_grupo, estado, timestamp, utimestamp, event_type, id_alert_am, criticity, user_comment, tags, source, id_extra" . $groupby_extra . "
1765
+					GROUP BY estado, evento, id_agentmodule, id_evento,
1766
+						id_agente, id_usuario, id_grupo, estado,
1767
+						timestamp, utimestamp, event_type, id_alert_am,
1768
+						criticity, user_comment, tags, source, id_extra,
1769
+						te.critical_instructions,
1770
+						te.warning_instructions,
1771
+						te.unknown_instructions,
1772
+						te.owner_user,
1773
+						te.ack_utimestamp,
1774
+						te.custom_data " . $groupby_extra . "
1775
 					ORDER BY timestamp_rep DESC LIMIT " . $pagination . " OFFSET " . $offset;
1776
 			}
1777
 			break;
1778
@@ -582,7 +591,7 @@
1779
 			
1780
 			$event_comments_array[] = $comment_for_json;
1781
 			
1782
-			$event_comments = json_encode($event_comments_array);
1783
+			$event_comments = io_json_mb_encode($event_comments_array);
1784
 			
1785
 			// Update comment
1786
 			$ret = db_process_sql_update($event_table,  array('user_comment' => $event_comments), array('id_evento' => implode(',', $id_event)));
1787
@@ -2244,6 +2253,7 @@
1788
 	$table_comments->class = "alternate rounded_cells";
1789
 	
1790
 	$event_comments = io_safe_output($event["user_comment"]);
1791
+	$event_comments = str_replace("\n", "<br>", $event_comments);
1792
 	
1793
 	// If comments are not stored in json, the format is old
1794
 	$event_comments_array = json_decode($event_comments, true);
1795
Index: include/graphs/functions_flot.php
1796
===================================================================
1797
--- include/graphs/functions_flot.php	(revision 10314)
1798
+++ include/graphs/functions_flot.php	(working copy)
1799
@@ -442,6 +442,7 @@
1800
 	
1801
 	$max = 0;
1802
 	$i = count($graph_data);
1803
+	$data = array();
1804
 	foreach ($graph_data as $label => $values) {
1805
 		$labels[] = io_safe_output($label);
1806
 		$i--;
1807
Index: include/graphs/pandora.d3.js
1808
===================================================================
1809
--- include/graphs/pandora.d3.js	(revision 10314)
1810
+++ include/graphs/pandora.d3.js	(working copy)
1811
@@ -715,8 +715,11 @@
1812
 		.data(partition.nodes(data))
1813
 		.enter().append("path")
1814
 		.attr("d", arc)
1815
-		.style("fill", function(d) { return color((d.children ? d : d.parent).name); })
1816
-		.on("click", click);
1817
+		.style("fill", function(d) { return d.color ? d3.rgb(d.color) : color((d.children ? d : d.parent).name); })
1818
+		.on("click", click)
1819
+		.on("mouseover", over_user)
1820
+		.on("mouseout", out_user)
1821
+		.on("mousemove", move_tooltip);
1822
 
1823
 	function click(d) {
1824
 		path.transition()
1825
@@ -737,4 +740,68 @@
1826
 				: function(t) { x.domain(xd(t)); y.domain(yd(t)).range(yr(t)); return arc(d); };
1827
 		};
1828
 	}
1829
+
1830
+	function move_tooltip(d) {
1831
+		var x = d3.event.pageX + 10;
1832
+		var y = d3.event.pageY + 10;
1833
+		
1834
+		$("#tooltip").css('left', x + 'px');
1835
+		$("#tooltip").css('top', y + 'px');
1836
+	}
1837
+	
1838
+	function over_user(d) {
1839
+		id = d.id;
1840
+		
1841
+		$("#" + id).css('border', '1px solid black');
1842
+		$("#" + id).css('z-index', '1');
1843
+		
1844
+		show_tooltip(d);
1845
+	}
1846
+	
1847
+	function out_user(d) {
1848
+		id = d.id;
1849
+		
1850
+		$("#" + id).css('border', '');
1851
+		$("#" + id).css('z-index', '');
1852
+		
1853
+		hide_tooltip();
1854
+	}
1855
+
1856
+	function create_tooltip(d, x, y) {
1857
+		var tooltip = (typeof d.tooltip_content != 'undefined') ? d.tooltip_content : d.name;
1858
+
1859
+		if ($("#tooltip").length == 0) {
1860
+			$(recipient)
1861
+				.append($("<div></div>")
1862
+				.attr('id', 'tooltip')
1863
+				.html(tooltip));
1864
+		}
1865
+		else {
1866
+			$("#tooltip").html(tooltip);
1867
+		}
1868
+		
1869
+		$("#tooltip").attr('style', 'background: #fff;' +
1870
+			'position: absolute;' +
1871
+			'display: block;' +
1872
+			'width: 200px;' +
1873
+			'text-align: left;' +
1874
+			'padding: 10px 10px 10px 10px;' +
1875
+			'z-index: 2;' +
1876
+			"-webkit-box-shadow: 7px 7px 5px rgba(50, 50, 50, 0.75);" +
1877
+			"-moz-box-shadow:    7px 7px 5px rgba(50, 50, 50, 0.75);" +
1878
+			"box-shadow:         7px 7px 5px rgba(50, 50, 50, 0.75);" +
1879
+			'left: ' + x + 'px;' +
1880
+			'top: ' + y + 'px;');
1881
+	}
1882
+	
1883
+	function show_tooltip(d) {
1884
+		var x = d3.event.pageX + 10;
1885
+		var y = d3.event.pageY + 10;
1886
+		
1887
+		create_tooltip(d, x, y);
1888
+	}
1889
+	
1890
+	function hide_tooltip() {
1891
+		$("#tooltip").hide();
1892
+	}
1893
 }
1894
\ No newline at end of file
1895
Index: include/graphs/fgraph.php
1896
===================================================================
1897
--- include/graphs/fgraph.php	(revision 10314)
1898
+++ include/graphs/fgraph.php	(working copy)
1899
@@ -398,11 +398,13 @@
1900
 	setup_watermark($water_mark, $water_mark_file, $water_mark_url);
1901
 	
1902
 	if ($flash_chart) {
1903
-		if ($return){
1904
-			return flot_hcolumn_chart ($chart_data, $width, $height, $water_mark_url);
1905
+		if ($return) {
1906
+			return flot_hcolumn_chart(
1907
+				$chart_data, $width, $height, $water_mark_url);
1908
 		}
1909
-		else{
1910
-			echo flot_hcolumn_chart ($chart_data, $width, $height, $water_mark_url);
1911
+		else {
1912
+			echo flot_hcolumn_chart(
1913
+				$chart_data, $width, $height, $water_mark_url);
1914
 		}
1915
 	}
1916
 	else {
1917
@@ -422,7 +424,7 @@
1918
 		
1919
 		$id_graph = serialize_in_temp($graph, null, $ttl);
1920
 		
1921
-		return "<img src='".$homedir."include/graphs/functions_pchart.php?static_graph=1&graph_type=hbar&ttl=".$ttl."&id_graph=".$id_graph."'>";
1922
+		return "<img src='" . $homedir . "include/graphs/functions_pchart.php?static_graph=1&graph_type=hbar&ttl=".$ttl."&id_graph=".$id_graph."'>";
1923
 	}
1924
 }
1925
 
1926
Index: include/db/postgresql.php
1927
===================================================================
1928
--- include/db/postgresql.php	(revision 10314)
1929
+++ include/db/postgresql.php	(working copy)
1930
@@ -332,6 +332,9 @@
1931
 		else if (is_float ($value) || is_double ($value)) {
1932
 			$values_str .= sprintf("%f", $value);
1933
 		}
1934
+		elseif (is_string($value) && (strtoupper($value) === 'NULL')) {
1935
+			$values_str .= "NULL";
1936
+		}
1937
 		else {
1938
 			$values_str .= sprintf("'%s'", $value);
1939
 		}
1940
@@ -346,6 +349,8 @@
1941
 	
1942
 	$query .= ' VALUES (' . $values_str . ')';
1943
 	
1944
+	//html_debug_print($query);
1945
+	
1946
 	return db_process_sql($query, 'insert_id');
1947
 }
1948
 
1949
@@ -362,6 +367,18 @@
1950
 	return $str;
1951
 }
1952
 
1953
+function postgresql_encapsule_fields_with_same_name_to_instructions($field) {
1954
+	$return = $field;
1955
+	
1956
+	if (is_string($return)) {
1957
+		if ($return[0] !== '"') {
1958
+			$return = '"' . $return . '"';
1959
+		}
1960
+	}
1961
+	
1962
+	return $return;
1963
+}
1964
+
1965
 /**
1966
  * Get the first value of the first row of a table in the database from an
1967
  * array with filter conditions.
1968
Index: include/db/mysql.php
1969
===================================================================
1970
--- include/db/mysql.php	(revision 10314)
1971
+++ include/db/mysql.php	(working copy)
1972
@@ -346,6 +346,18 @@
1973
 	return $str;
1974
 }
1975
 
1976
+function mysql_encapsule_fields_with_same_name_to_instructions($field) {
1977
+	$return = $field;
1978
+	
1979
+	if (is_string($return)) {
1980
+		if ($return[0] !== '`') {
1981
+			$return = '`' . $return . '`';
1982
+		}
1983
+	}
1984
+	
1985
+	return $return;
1986
+}
1987
+
1988
 /**
1989
  * Get the first value of the first row of a table in the database from an
1990
  * array with filter conditions.
1991
Index: include/db/oracle.php
1992
===================================================================
1993
--- include/db/oracle.php	(revision 10314)
1994
+++ include/db/oracle.php	(working copy)
1995
@@ -254,7 +254,7 @@
1996
 			else if ($type[0] == '/INSERT'){
1997
 				$query = oci_parse($config['dbconnection'], substr($sql,1));			
1998
 			}
1999
-			else{
2000
+			else {
2001
 				$query = oci_parse($config['dbconnection'], $sql);
2002
 			}
2003
 		}
2004
@@ -448,6 +448,18 @@
2005
 	return str_replace(array('"', "'", '\\'), array('\\"', '\\\'', '\\\\'), $string);
2006
 }
2007
 
2008
+function oracle_encapsule_fields_with_same_name_to_instructions($field) {
2009
+	$return = $field;
2010
+	
2011
+	if (is_string($return)) {
2012
+		if ($return[0] !== '"') {
2013
+			$return = '"' . $return . '"';
2014
+		}
2015
+	}
2016
+	
2017
+	return $return;
2018
+}
2019
+
2020
 /**
2021
  * Get the first value of the first row of a table in the database from an
2022
  * array with filter conditions.
2023
@@ -649,7 +661,7 @@
2024
 			else if ($value[0] == '%') {
2025
 				$query .= sprintf ("%s LIKE '%s'", $field, $value);
2026
 			}
2027
-			else{ 
2028
+			else { 
2029
 				$query .= sprintf ("%s = '%s'", $field, $value);
2030
 			}
2031
 		}
2032
@@ -997,16 +1009,16 @@
2033
 	global $config;
2034
 	
2035
 	$type = explode(' ',strtoupper(trim($sql)));
2036
-	if ($type[0] == 'SELECT'){
2037
+	if ($type[0] == 'SELECT') {
2038
 		$sql = "SELECT count(*) as NUM FROM (" . $sql . ")";
2039
 	}
2040
 	$query = oci_parse($config['dbconnection'], $sql);
2041
 	oci_execute($query);
2042
-	if ($type[0] == 'SELECT'){
2043
+	if ($type[0] == 'SELECT') {
2044
 		$row = oci_fetch_assoc($query);
2045
 		$rows = $row['NUM'];
2046
 	}
2047
-	else{
2048
+	else {
2049
 		$rows = oci_num_rows($query);
2050
 	}
2051
 	
2052
@@ -1027,13 +1039,19 @@
2053
  */
2054
 function oracle_db_get_all_rows_field_filter ($table, $field, $condition, $order_field = "") {
2055
 	if (is_int ($condition) || is_bool ($condition)) {
2056
-		$sql = sprintf ("SELECT * FROM %s WHERE %s = %d", $table, $field, $condition);
2057
+		$sql = sprintf ("SELECT *
2058
+			FROM %s
2059
+			WHERE %s = %d", $table, $field, $condition);
2060
 	}
2061
 	else if (is_float ($condition) || is_double ($condition)) {
2062
-		$sql = sprintf ("SELECT * FROM %s WHERE %s = %f", $table, $field, $condition);
2063
+		$sql = sprintf ("SELECT *
2064
+			FROM %s
2065
+			WHERE %s = %f", $table, $field, $condition);
2066
 	}
2067
 	else {
2068
-		$sql = sprintf ("SELECT * FROM %s WHERE %s = '%s'", $table, $field, $condition);
2069
+		$sql = sprintf ("SELECT *
2070
+			FROM %s
2071
+			WHERE %s = '%s'", $table, $field, $condition);
2072
 	}
2073
 	
2074
 	if ($order_field != "")
2075
Index: include/functions_modules.php
2076
===================================================================
2077
--- include/functions_modules.php	(revision 10314)
2078
+++ include/functions_modules.php	(working copy)
2079
@@ -1663,15 +1663,15 @@
2080
 		$status = STATUS_AGENT_DOWN;
2081
 		$last_status =  modules_get_agentmodule_last_status($id_agent_module);
2082
 		switch($last_status) {
2083
-			case 0:
2084
+			case AGENT_STATUS_NORMAL:
2085
 				$title = __('UNKNOWN') . " - " . __('Last status') .
2086
 					" " . __('NORMAL');
2087
 				break;
2088
-			case 1:
2089
+			case AGENT_STATUS_CRITICAL:
2090
 				$title = __('UNKNOWN') . " - " . __('Last status') .
2091
 					" " . __('CRITICAL');
2092
 				break;
2093
-			case 2:
2094
+			case AGENT_STATUS_WARNING:
2095
 				$title = __('UNKNOWN') . " - " . __('Last status') .
2096
 					" " . __('WARNING');
2097
 				break;
2098
Index: include/functions_reporting.php
2099
===================================================================
2100
--- include/functions_reporting.php	(revision 10314)
2101
+++ include/functions_reporting.php	(working copy)
2102
@@ -907,6 +907,8 @@
2103
 }
2104
 
2105
 function reporting_get_stats_servers($tiny = true) {
2106
+	global $config;
2107
+	
2108
 	$server_performance = servers_get_performance();
2109
 	
2110
 	// Alerts table
2111
@@ -959,7 +961,9 @@
2112
 			$tdata[0] = html_print_image('images/network.png', true, array('title' => __('Network modules'), 'width' => '25px'));
2113
 			$tdata[1] = '<span class="big_data">' . format_numeric($server_performance ["total_network_modules"]) . '</span>';
2114
 			
2115
-			$tdata[2] = '<span class="med_data">' . format_numeric($server_performance ["network_modules_rate"], 2) . '</span>';
2116
+			$tdata[2] = '<span class="med_data">' .
2117
+				format_numeric($server_performance ["network_modules_rate"], 2) .
2118
+				'</span>';
2119
 			$tdata[3] = html_print_image('images/module.png', true, array('title' => __('Ratio') . ': ' . __('Modules by second'), 'width' => '16px')) . '/sec </span>';
2120
 			
2121
 			$table_srv->rowclass[] = '';
2122
@@ -1020,8 +1024,23 @@
2123
 		$table_srv->rowclass[] = '';
2124
 		$table_srv->data[] = $tdata;
2125
 		
2126
-		$system_events = db_get_value_sql('SELECT SQL_NO_CACHE COUNT(id_evento) FROM tevento');
2127
-
2128
+		
2129
+		switch ($config["dbtype"]) {
2130
+			case "mysql":
2131
+				$system_events = db_get_value_sql(
2132
+					'SELECT SQL_NO_CACHE COUNT(id_evento)
2133
+					FROM tevento');
2134
+				break;
2135
+			case "postgresql":
2136
+			case "oracle":
2137
+				$system_events = db_get_value_sql(
2138
+					'SELECT COUNT(id_evento)
2139
+					FROM tevento');
2140
+				break;
2141
+		}
2142
+		
2143
+		
2144
+		
2145
 		$tdata = array();
2146
 		$tdata[0] = html_print_image('images/lightning_go.png', true, array('title' => __('Total events'), 'width' => '25px'));
2147
 		$tdata[1] = '<span class="big_data">' . format_numeric($system_events) . '</span>';
2148
@@ -1109,16 +1128,21 @@
2149
 		$tdata = array();
2150
 		$table_mbs->colspan[count($table_mbs->data)][0] = 4;
2151
 		$table_mbs->cellstyle[count($table_mbs->data)][0] = 'text-align: center;';
2152
-		$tdata[0] = '<div id="outter_status_pie" style="height: ' . $graph_height . 'px"><div id="status_pie" style="margin: auto; width: ' . $graph_width . 'px;">' . graph_agent_status (false, $graph_width, $graph_height, true, true) . '</div></div>';
2153
+		$tdata[0] = '<div id="outter_status_pie" style="height: ' . $graph_height . 'px">' .
2154
+			'<div id="status_pie" style="margin: auto; width: ' . $graph_width . 'px;">' .
2155
+				graph_agent_status(false, $graph_width, $graph_height, true, true) .
2156
+			'</div></div>';
2157
 		$table_mbs->rowclass[] = '';
2158
 		$table_mbs->data[] = $tdata;
2159
 	}
2160
 	
2161
-	$output = '<fieldset class="databox tactical_set">
2162
-				<legend>' . 
2163
-					__('Monitors by status') . 
2164
-				'</legend>' . 
2165
-				html_print_table($table_mbs, true) . '</fieldset>';
2166
+	$output = '
2167
+		<fieldset class="databox tactical_set">
2168
+			<legend>' . 
2169
+				__('Monitors by status') . 
2170
+			'</legend>' . 
2171
+			html_print_table($table_mbs, true) .
2172
+		'</fieldset>';
2173
 	
2174
 	return $output;
2175
 }
2176
@@ -3123,9 +3147,29 @@
2177
 			}
2178
 			else {
2179
 				
2180
-				$data[0] = grafico_modulo_sparse($content['id_agent_module'], $content['period'],
2181
-					false, $sizgraph_w, $sizgraph_h, '', '', false, true, true,
2182
-					$report["datetime"], '', 0, 0, true, true, ui_get_full_url(false) . '/');
2183
+				$data[0] = grafico_modulo_sparse(
2184
+					$content['id_agent_module'],
2185
+					$content['period'],
2186
+					false,
2187
+					$sizgraph_w,
2188
+					$sizgraph_h,
2189
+					'',
2190
+					'',
2191
+					false,
2192
+					true,
2193
+					true,
2194
+					$report["datetime"],
2195
+					'',
2196
+					0,
2197
+					0,
2198
+					true,
2199
+					true,
2200
+					ui_get_full_url(false) . '/',
2201
+					1,
2202
+					false,
2203
+					'',
2204
+					false,
2205
+					true);
2206
 			}
2207
 			
2208
 			array_push ($table->data, $data);
2209
Index: include/auth/ldap.php
2210
===================================================================
2211
--- include/auth/ldap.php	(revision 10314)
2212
+++ include/auth/ldap.php	(working copy)
2213
@@ -65,8 +65,11 @@
2214
 $config["admin_can_make_admin"] = false;
2215
 
2216
 //Required and optional keys for this function to work
2217
-$req_keys = array ("ldap_server", "ldap_base_dn", "ldap_login_attr", "ldap_admin_group_name", "ldap_admin_group_attr", "ldap_admin_group_type", "ldap_user_filter", "ldap_user_attr");
2218
-$opt_keys = array ("ldap_port", "ldap_start_tls", "ldap_version", "ldap_admin_dn", "ldap_admin_pwd");
2219
+$req_keys = array("ldap_server", "ldap_base_dn", "ldap_login_attr",
2220
+	"ldap_admin_group_name", "ldap_admin_group_attr",
2221
+	"ldap_admin_group_type", "ldap_user_filter", "ldap_user_attr");
2222
+$opt_keys = array("ldap_port", "ldap_start_tls", "ldap_version",
2223
+	"ldap_admin_dn", "ldap_admin_pwd");
2224
 
2225
 global $ldap_cache; //Needs to be globalized because config_process_config () function calls this file first and the variable would be local and subsequently lost
2226
 $ldap_cache = array ();
2227
@@ -76,13 +79,15 @@
2228
 //Put each required key in a variable.
2229
 foreach ($req_keys as $key) {
2230
 	if (!isset ($config["auth"][$key])) {
2231
-		user_error ("Required key ".$key." not set", E_USER_ERROR);
2232
+		user_error("Required key " . $key . " not set", E_USER_ERROR);
2233
 	}
2234
 }
2235
 
2236
 // Convert group name to lower case to prevent problems
2237
-$config["auth"]["ldap_admin_group_attr"] = strtolower ($config["auth"]["ldap_admin_group_attr"]);
2238
-$config["auth"]["ldap_admin_group_type"] = strtolower ($config["auth"]["ldap_admin_group_type"]);
2239
+$config["auth"]["ldap_admin_group_attr"] =
2240
+	strtolower ($config["auth"]["ldap_admin_group_attr"]);
2241
+$config["auth"]["ldap_admin_group_type"] =
2242
+	strtolower ($config["auth"]["ldap_admin_group_type"]);
2243
 
2244
 foreach ($opt_keys as $key) {
2245
 	if (!isset ($config["auth"][$key])) {
2246
@@ -122,7 +127,7 @@
2247
 		return false;
2248
 	} 
2249
 	global $config;
2250
-		
2251
+	
2252
 	$profile = db_get_value ("id_usuario", "tusuario_perfil", "id_usuario", $login);
2253
 	
2254
 	if ($profile === false && empty ($config["auth"]["create_user_undefined"])) {
2255
@@ -311,7 +316,8 @@
2256
 	
2257
 	$nick = false;
2258
 	if (ldap_connect_bind ()) {
2259
-		$sr = @ldap_search ($ldap_cache["ds"], $config["auth"]["ldap_base_dn"], "(&(".$config["auth"]["ldap_login_attr"]."=".$login.")".$config["auth"]["ldap_user_filter"].")", array_values ($config["auth"]["ldap_user_attr"]));
2260
+		$sr = @ldap_search ($ldap_cache["ds"],
2261
+			io_safe_output($config["auth"]["ldap_base_dn"]), "(&(".io_safe_output($config["auth"]["ldap_login_attr"])."=".$login.")".io_safe_output($config["auth"]["ldap_user_filter"]).")", array_values ($config["auth"]["ldap_user_attr"]));
2262
 		
2263
 		if (!$sr) {
2264
 			$ldap_cache["error"] .= 'Error searching LDAP server: ' . ldap_error ($ldap_cache["ds"]);
2265
@@ -364,7 +370,7 @@
2266
 			return $ret;
2267
 		}
2268
 		
2269
-		$r = @ldap_bind ($ds, $config["auth"]["ldap_login_attr"]."=".$login.",".$config["auth"]["ldap_base_dn"], $password);
2270
+		$r = @ldap_bind ($ds, io_safe_output($config["auth"]["ldap_login_attr"])."=".$login.",".io_safe_output($config["auth"]["ldap_base_dn"]), $password);
2271
 		if (!$r) {
2272
 			$ldap_cache["error"] .= 'Invalid login';
2273
 		}
2274
@@ -393,7 +399,8 @@
2275
 	$time = get_system_time ();
2276
 	if (ldap_connect_bind ()) {
2277
 		
2278
-		$sr = ldap_search ($ldap_cache["ds"], $config["auth"]["ldap_base_dn"], "(&(".$config["auth"]["ldap_login_attr"]."=".$login.")".$config["auth"]["ldap_user_filter"].")", array_values ($config["auth"]["ldap_user_attr"]));
2279
+		$sr = ldap_search ($ldap_cache["ds"],
2280
+			io_safe_output($config["auth"]["ldap_base_dn"]), "(&(".io_safe_output($config["auth"]["ldap_login_attr"])."=".$login.")".io_safe_output($config["auth"]["ldap_user_filter"]).")", array_values ($config["auth"]["ldap_user_attr"]));
2281
 		
2282
 		if (!$sr) {
2283
 			$ldap_cache["error"] .= 'Error searching LDAP server (load_user): ' . ldap_error( $ldap_cache["ds"] );
2284
@@ -497,7 +504,7 @@
2285
 	$time = get_system_time ();
2286
 	
2287
 	if (ldap_connect_bind ()) {
2288
-		$sr = @ldap_search ($ldap_cache["ds"], $config["auth"]["ldap_base_dn"], $config["auth"]["ldap_user_filter"], array_values ($config["auth"]["ldap_user_attr"]));
2289
+		$sr = @ldap_search ($ldap_cache["ds"], io_safe_output($config["auth"]["ldap_base_dn"]), io_safe_output($config["auth"]["ldap_user_filter"]), array_values ($config["auth"]["ldap_user_attr"]));
2290
 		if (!$sr) {
2291
 			$ldap_cache["error"] .= 'Error searching LDAP server (get_users): ' . ldap_error( $ldap_cache["ds"] );
2292
 		}
2293
Index: include/auth/mysql.php
2294
===================================================================
2295
--- include/auth/mysql.php	(revision 10314)
2296
+++ include/auth/mysql.php	(working copy)
2297
@@ -512,7 +512,11 @@
2298
 		}
2299
 	}
2300
 	
2301
-	if (strlen($password) == 0 || !@ldap_bind ($ds, $config["ldap_login_attr"]."=".$login.",".$config["ldap_base_dn"], $password)) {
2302
+	if (strlen($password) == 0 ||
2303
+		!@ldap_bind($ds,
2304
+			io_safe_output($config["ldap_login_attr"]) . "=" . $login . "," . io_safe_output($config["ldap_base_dn"]),
2305
+			$password)) {
2306
+		
2307
 		$config["auth_error"] = 'User not found in database or incorrect password';
2308
 		@ldap_close ($ds);
2309
 		
2310
Index: include/functions_networkmap.php
2311
===================================================================
2312
--- include/functions_networkmap.php	(revision 10314)
2313
+++ include/functions_networkmap.php	(working copy)
2314
@@ -233,7 +233,8 @@
2315
 	$simple = 0, $font_size = 12, $layout = 'radial', $nooverlap = 0,
2316
 	$zoom = 1, $ranksep = 2.5, $center = 0, $regen = 1, $pure = 0,
2317
 	$id_networkmap = 0, $show_snmp_modules = 0, $cut_names = true,
2318
-	$relative = false, $text_filter = '', $l2_network = false, $ip_mask = null) {
2319
+	$relative = false, $text_filter = '', $l2_network = false, $ip_mask = null,
2320
+	$dont_show_subgroups = false) {
2321
 	
2322
 	global $config;
2323
 	
2324
@@ -262,7 +263,20 @@
2325
 	}
2326
 	
2327
 	if ($group >= 1) {
2328
-		$filter['id_grupo'] = $group;
2329
+		if ($dont_show_subgroups)
2330
+			$filter['id_grupo'] = $group;
2331
+		else {
2332
+			$childrens = groups_get_childrens($group, null, true);
2333
+			if (!empty($childrens)) {
2334
+				$childrens = array_keys($childrens);
2335
+				
2336
+				$filter['id_grupo'] = $childrens;
2337
+				$filter['id_grupo'][] = $group;
2338
+			}
2339
+			else {
2340
+				$filter['id_grupo'] = $group;
2341
+			}
2342
+		}
2343
 		
2344
 		//Order by id_parent ascendant for to avoid the bugs
2345
 		//because the first agents to process in the next
2346
@@ -589,7 +603,13 @@
2347
 }
2348
 
2349
 // Generate a dot graph definition for graphviz with groups
2350
-function networkmap_generate_dot_groups ($pandora_name, $group = 0, $simple = 0, $font_size = 12, $layout = 'radial', $nooverlap = 0, $zoom = 1, $ranksep = 2.5, $center = 0, $regen = 1, $pure = 0, $modwithalerts = 0, $module_group = 0, $hidepolicymodules = 0, $depth = 'all', $id_networkmap = 0, $dont_show_subgroups = 0, $text_filter = '') {
2351
+function networkmap_generate_dot_groups ($pandora_name, $group = 0,
2352
+	$simple = 0, $font_size = 12, $layout = 'radial', $nooverlap = 0,
2353
+	$zoom = 1, $ranksep = 2.5, $center = 0, $regen = 1, $pure = 0,
2354
+	$modwithalerts = 0, $module_group = 0, $hidepolicymodules = 0,
2355
+	$depth = 'all', $id_networkmap = 0, $dont_show_subgroups = 0,
2356
+	$text_filter = '') {
2357
+	
2358
 	global $config;
2359
 	
2360
 	$parents = array();
2361
@@ -682,7 +702,8 @@
2362
 		// Get agents data
2363
 		$agents = agents_get_agents ($filter,
2364
 			array ('id_grupo, nombre, id_os, id_agente, 
2365
-				normal_count, warning_count, critical_count, unknown_count, total_count, notinit_count'));
2366
+				normal_count, warning_count, critical_count,
2367
+				unknown_count, total_count, notinit_count'));
2368
 		
2369
 		if ($agents === false)
2370
 			$agents = array();
2371
@@ -1427,7 +1448,9 @@
2372
 	$values['show_groups'] = $show_groups;
2373
 	$values['show_modules'] = $show_modules;
2374
 	
2375
-	return @db_process_sql_insert ('tnetwork_map', $values);
2376
+	$values['server_name'] = "";
2377
+	
2378
+	return @db_process_sql_insert('tnetwork_map', $values);
2379
 }
2380
 
2381
 /**
2382
Index: include/javascript/introjs.css
2383
===================================================================
2384
--- include/javascript/introjs.css	(revision 0)
2385
+++ include/javascript/introjs.css	(revision 10417)
2386
@@ -0,0 +1,276 @@
2387
+.introjs-overlay {
2388
+  position: absolute;
2389
+  z-index: 999999;
2390
+  background-color: #000;
2391
+  opacity: 0;
2392
+  background: -moz-radial-gradient(center,ellipse cover,rgba(0,0,0,0.4) 0,rgba(0,0,0,0.9) 100%);
2393
+  background: -webkit-gradient(radial,center center,0px,center center,100%,color-stop(0%,rgba(0,0,0,0.4)),color-stop(100%,rgba(0,0,0,0.9)));
2394
+  background: -webkit-radial-gradient(center,ellipse cover,rgba(0,0,0,0.4) 0,rgba(0,0,0,0.9) 100%);
2395
+  background: -o-radial-gradient(center,ellipse cover,rgba(0,0,0,0.4) 0,rgba(0,0,0,0.9) 100%);
2396
+  background: -ms-radial-gradient(center,ellipse cover,rgba(0,0,0,0.4) 0,rgba(0,0,0,0.9) 100%);
2397
+  background: radial-gradient(center,ellipse cover,rgba(0,0,0,0.4) 0,rgba(0,0,0,0.9) 100%);
2398
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#66000000',endColorstr='#e6000000',GradientType=1);
2399
+  -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=50)";
2400
+  filter: alpha(opacity=50);
2401
+  -webkit-transition: all 0.3s ease-out;
2402
+     -moz-transition: all 0.3s ease-out;
2403
+      -ms-transition: all 0.3s ease-out;
2404
+       -o-transition: all 0.3s ease-out;
2405
+          transition: all 0.3s ease-out;
2406
+}
2407
+
2408
+.introjs-fixParent {
2409
+  z-index: auto !important;
2410
+  opacity: 1.0 !important;
2411
+}
2412
+
2413
+.introjs-showElement,
2414
+tr.introjs-showElement > td,
2415
+tr.introjs-showElement > th {
2416
+  z-index: 9999999 !important;
2417
+}
2418
+
2419
+.introjs-relativePosition,
2420
+tr.introjs-showElement > td,
2421
+tr.introjs-showElement > th {
2422
+  position: relative;
2423
+}
2424
+
2425
+.introjs-helperLayer {
2426
+  position: absolute;
2427
+  z-index: 9999998;
2428
+  background-color: #FFF;
2429
+  background-color: rgba(255,255,255,.9);
2430
+  border: 1px solid #777;
2431
+  border: 1px solid rgba(0,0,0,.5);
2432
+  border-radius: 4px;
2433
+  box-shadow: 0 2px 15px rgba(0,0,0,.4);
2434
+  -webkit-transition: all 0.3s ease-out;
2435
+     -moz-transition: all 0.3s ease-out;
2436
+      -ms-transition: all 0.3s ease-out;
2437
+       -o-transition: all 0.3s ease-out;
2438
+          transition: all 0.3s ease-out;
2439
+}
2440
+
2441
+.introjs-helperNumberLayer {
2442
+  position: absolute;
2443
+  top: -16px;
2444
+  left: -16px;
2445
+  z-index: 9999999999 !important;
2446
+  padding: 2px;
2447
+  font-family: Arial, verdana, tahoma;
2448
+  font-size: 13px;
2449
+  font-weight: bold;
2450
+  color: white;
2451
+  text-align: center;
2452
+  text-shadow: 1px 1px 1px rgba(0,0,0,.3);
2453
+  background: #ff3019; /* Old browsers */
2454
+  background: -webkit-linear-gradient(top, #ff3019 0%, #cf0404 100%); /* Chrome10+,Safari5.1+ */
2455
+  background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #ff3019), color-stop(100%, #cf0404)); /* Chrome,Safari4+ */
2456
+  background:    -moz-linear-gradient(top, #ff3019 0%, #cf0404 100%); /* FF3.6+ */
2457
+  background:     -ms-linear-gradient(top, #ff3019 0%, #cf0404 100%); /* IE10+ */
2458
+  background:      -o-linear-gradient(top, #ff3019 0%, #cf0404 100%); /* Opera 11.10+ */
2459
+  background:         linear-gradient(to bottom, #ff3019 0%, #cf0404 100%);  /* W3C */
2460
+  width: 20px;
2461
+  height:20px;
2462
+  line-height: 20px;
2463
+  border: 3px solid white;
2464
+  border-radius: 50%;
2465
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3019', endColorstr='#cf0404', GradientType=0); /* IE6-9 */
2466
+  filter: progid:DXImageTransform.Microsoft.Shadow(direction=135, strength=2, color=ff0000); /* IE10 text shadows */
2467
+  box-shadow: 0 2px 5px rgba(0,0,0,.4);
2468
+}
2469
+
2470
+.introjs-arrow {
2471
+  border: 5px solid white;
2472
+  content:'';
2473
+  position: absolute;
2474
+}
2475
+.introjs-arrow.top {
2476
+  top: -10px;
2477
+  border-top-color:transparent;
2478
+  border-right-color:transparent;
2479
+  border-bottom-color:white;
2480
+  border-left-color:transparent;
2481
+}
2482
+.introjs-arrow.top-right {
2483
+  top: -10px;
2484
+  right: 10px;
2485
+  border-top-color:transparent;
2486
+  border-right-color:transparent;
2487
+  border-bottom-color:white;
2488
+  border-left-color:transparent;
2489
+}
2490
+.introjs-arrow.top-middle {
2491
+  top: -10px;
2492
+  left: 50%;
2493
+  margin-left: -5px;
2494
+  border-top-color:transparent;
2495
+  border-right-color:transparent;
2496
+  border-bottom-color:white;
2497
+  border-left-color:transparent;
2498
+}
2499
+.introjs-arrow.right {
2500
+  right: -10px;
2501
+  top: 10px;
2502
+  border-top-color:transparent;
2503
+  border-right-color:transparent;
2504
+  border-bottom-color:transparent;
2505
+  border-left-color:white;
2506
+}
2507
+.introjs-arrow.bottom {
2508
+  bottom: -10px;
2509
+  border-top-color:white;
2510
+  border-right-color:transparent;
2511
+  border-bottom-color:transparent;
2512
+  border-left-color:transparent;
2513
+}
2514
+.introjs-arrow.left {
2515
+  left: -10px;
2516
+  top: 10px;
2517
+  border-top-color:transparent;
2518
+  border-right-color:white;
2519
+  border-bottom-color:transparent;
2520
+  border-left-color:transparent;
2521
+}
2522
+
2523
+.introjs-tooltip {
2524
+  position: absolute;
2525
+  padding: 10px;
2526
+  background-color: white;
2527
+  min-width: 200px;
2528
+  max-width: 300px;
2529
+  border-radius: 3px;
2530
+  box-shadow: 0 1px 10px rgba(0,0,0,.4);
2531
+  -webkit-transition: opacity 0.1s ease-out;
2532
+     -moz-transition: opacity 0.1s ease-out;
2533
+      -ms-transition: opacity 0.1s ease-out;
2534
+       -o-transition: opacity 0.1s ease-out;
2535
+          transition: opacity 0.1s ease-out;
2536
+}
2537
+
2538
+.introjs-tooltipbuttons {
2539
+  text-align: right;
2540
+}
2541
+
2542
+/*
2543
+ Buttons style by http://nicolasgallagher.com/lab/css3-github-buttons/
2544
+ Changed by Afshin Mehrabani
2545
+*/
2546
+.introjs-button {
2547
+  position: relative;
2548
+  overflow: visible;
2549
+  display: inline-block;
2550
+  padding: 0.3em 0.8em;
2551
+  border: 1px solid #d4d4d4;
2552
+  margin: 0;
2553
+  text-decoration: none;
2554
+  text-shadow: 1px 1px 0 #fff;
2555
+  font: 11px/normal sans-serif;
2556
+  color: #333;
2557
+  white-space: nowrap;
2558
+  cursor: pointer;
2559
+  outline: none;
2560
+  background-color: #ececec;
2561
+  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f4f4f4), to(#ececec));
2562
+  background-image: -moz-linear-gradient(#f4f4f4, #ececec);
2563
+  background-image: -o-linear-gradient(#f4f4f4, #ececec);
2564
+  background-image: linear-gradient(#f4f4f4, #ececec);
2565
+  -webkit-background-clip: padding;
2566
+  -moz-background-clip: padding;
2567
+  -o-background-clip: padding-box;
2568
+  /*background-clip: padding-box;*/ /* commented out due to Opera 11.10 bug */
2569
+  -webkit-border-radius: 0.2em;
2570
+  -moz-border-radius: 0.2em;
2571
+  border-radius: 0.2em;
2572
+  /* IE hacks */
2573
+  zoom: 1;
2574
+  *display: inline;
2575
+  margin-top: 10px;
2576
+}
2577
+
2578
+.introjs-button:hover {
2579
+  border-color: #bcbcbc;
2580
+  text-decoration: none;
2581
+  box-shadow: 0px 1px 1px #e3e3e3;
2582
+}
2583
+
2584
+.introjs-button:focus,
2585
+.introjs-button:active {
2586
+  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ececec), to(#f4f4f4));
2587
+  background-image: -moz-linear-gradient(#ececec, #f4f4f4);
2588
+  background-image: -o-linear-gradient(#ececec, #f4f4f4);
2589
+  background-image: linear-gradient(#ececec, #f4f4f4);
2590
+}
2591
+
2592
+/* overrides extra padding on button elements in Firefox */
2593
+.introjs-button::-moz-focus-inner {
2594
+  padding: 0;
2595
+  border: 0;
2596
+}
2597
+
2598
+.introjs-skipbutton {
2599
+  margin-right: 5px;
2600
+  color: #7a7a7a;
2601
+}
2602
+
2603
+.introjs-prevbutton {
2604
+  -webkit-border-radius: 0.2em 0 0 0.2em;
2605
+  -moz-border-radius: 0.2em 0 0 0.2em;
2606
+  border-radius: 0.2em 0 0 0.2em;
2607
+  border-right: none;
2608
+}
2609
+
2610
+.introjs-nextbutton {
2611
+  -webkit-border-radius: 0 0.2em 0.2em 0;
2612
+  -moz-border-radius: 0 0.2em 0.2em 0;
2613
+  border-radius: 0 0.2em 0.2em 0;
2614
+}
2615
+
2616
+.introjs-disabled, .introjs-disabled:hover, .introjs-disabled:focus {
2617
+  color: #9a9a9a;
2618
+  border-color: #d4d4d4;
2619
+  box-shadow: none;
2620
+  cursor: default;
2621
+  background-color: #f4f4f4;
2622
+  background-image: none;
2623
+  text-decoration: none;
2624
+}
2625
+
2626
+.introjs-bullets {
2627
+  text-align: center;
2628
+}
2629
+.introjs-bullets ul {
2630
+  clear: both;
2631
+  margin: 15px auto 0;
2632
+  padding: 0;
2633
+  display: inline-block;
2634
+}
2635
+.introjs-bullets ul li {
2636
+  list-style: none;
2637
+  float: left;
2638
+  margin: 0 2px;
2639
+}
2640
+.introjs-bullets ul li a {
2641
+  display: block;
2642
+  width: 6px;
2643
+  height: 6px;
2644
+  background: #ccc;
2645
+  border-radius: 10px;
2646
+  -moz-border-radius: 10px;
2647
+  -webkit-border-radius: 10px;
2648
+  text-decoration: none;
2649
+}
2650
+.introjs-bullets ul li a:hover {
2651
+  background: #999;
2652
+}
2653
+.introjs-bullets ul li a.active {
2654
+  background: #999;
2655
+}
2656
+.introjsFloatingElement {
2657
+  position: absolute;
2658
+  height: 0;
2659
+  width: 0;
2660
+  left: 50%;
2661
+  top: 50%;
2662
+}
2663
Index: include/javascript/intro.js
2664
===================================================================
2665
--- include/javascript/intro.js	(revision 0)
2666
+++ include/javascript/intro.js	(revision 10417)
2667
@@ -0,0 +1,1049 @@
2668
+/**
2669
+ * Intro.js v0.9.0
2670
+ * https://github.com/usablica/intro.js
2671
+ * MIT licensed
2672
+ *
2673
+ * Copyright (C) 2013 usabli.ca - A weekend project by Afshin Mehrabani (@afshinmeh)
2674
+ */
2675
+
2676
+(function (root, factory) {
2677
+  if (typeof exports === 'object') {
2678
+    // CommonJS
2679
+    factory(exports);
2680
+  } else if (typeof define === 'function' && define.amd) {
2681
+    // AMD. Register as an anonymous module.
2682
+    define(['exports'], factory);
2683
+  } else {
2684
+    // Browser globals
2685
+    factory(root);
2686
+  }
2687
+} (this, function (exports) {
2688
+  //Default config/variables
2689
+  var VERSION = '0.9.0';
2690
+
2691
+  /**
2692
+   * IntroJs main class
2693
+   *
2694
+   * @class IntroJs
2695
+   */
2696
+  function IntroJs(obj) {
2697
+    this._targetElement = obj;
2698
+
2699
+    this._options = {
2700
+      /* Next button label in tooltip box */
2701
+      nextLabel: 'Next &rarr;',
2702
+      /* Previous button label in tooltip box */
2703
+      prevLabel: '&larr; Back',
2704
+      /* Skip button label in tooltip box */
2705
+      skipLabel: 'Skip',
2706
+      /* Done button label in tooltip box */
2707
+      doneLabel: 'Done',
2708
+      /* Default tooltip box position */
2709
+      tooltipPosition: 'bottom',
2710
+      /* Next CSS class for tooltip boxes */
2711
+      tooltipClass: '',
2712
+      /* Close introduction when pressing Escape button? */
2713
+      exitOnEsc: true,
2714
+      /* Close introduction when clicking on overlay layer? */
2715
+      exitOnOverlayClick: true,
2716
+      /* Show step numbers in introduction? */
2717
+      showStepNumbers: true,
2718
+      /* Let user use keyboard to navigate the tour? */
2719
+      keyboardNavigation: true,
2720
+      /* Show tour control buttons? */
2721
+      showButtons: true,
2722
+      /* Show tour bullets? */
2723
+      showBullets: true,
2724
+      /* Scroll to highlighted element? */
2725
+      scrollToElement: true,
2726
+      /* Set the overlay opacity */
2727
+      overlayOpacity: 0.8
2728
+    };
2729
+  }
2730
+
2731
+  /**
2732
+   * Initiate a new introduction/guide from an element in the page
2733
+   *
2734
+   * @api private
2735
+   * @method _introForElement
2736
+   * @param {Object} targetElm
2737
+   * @returns {Boolean} Success or not?
2738
+   */
2739
+  function _introForElement(targetElm) {
2740
+    var introItems = [],
2741
+        self = this;
2742
+
2743
+    if (this._options.steps) {
2744
+      //use steps passed programmatically
2745
+      var allIntroSteps = [];
2746
+
2747
+      for (var i = 0, stepsLength = this._options.steps.length; i < stepsLength; i++) {
2748
+        var currentItem = _cloneObject(this._options.steps[i]);
2749
+        //set the step
2750
+        currentItem.step = introItems.length + 1;
2751
+        //use querySelector function only when developer used CSS selector
2752
+        if (typeof(currentItem.element) === 'string') {
2753
+          //grab the element with given selector from the page
2754
+          currentItem.element = document.querySelector(currentItem.element);
2755
+        }
2756
+
2757
+        //intro without element
2758
+        if (typeof(currentItem.element) === 'undefined' || currentItem.element == null) {
2759
+          var floatingElementQuery = document.querySelector(".introjsFloatingElement");
2760
+
2761
+          if (floatingElementQuery == null) {
2762
+            floatingElementQuery = document.createElement('div');
2763
+            floatingElementQuery.className = 'introjsFloatingElement';
2764
+
2765
+            document.body.appendChild(floatingElementQuery);
2766
+          }
2767
+
2768
+          currentItem.element  = floatingElementQuery;
2769
+          currentItem.position = 'floating';
2770
+        }
2771
+
2772
+        if (currentItem.element != null) {
2773
+          introItems.push(currentItem);
2774
+        }
2775
+      }
2776
+
2777
+    } else {
2778
+       //use steps from data-* annotations
2779
+      var allIntroSteps = targetElm.querySelectorAll('*[data-intro]');
2780
+      //if there's no element to intro
2781
+      if (allIntroSteps.length < 1) {
2782
+        return false;
2783
+      }
2784
+
2785
+      //first add intro items with data-step
2786
+      for (var i = 0, elmsLength = allIntroSteps.length; i < elmsLength; i++) {
2787
+        var currentElement = allIntroSteps[i];
2788
+        var step = parseInt(currentElement.getAttribute('data-step'), 10);
2789
+
2790
+        if (step > 0) {
2791
+          introItems[step - 1] = {
2792
+            element: currentElement,
2793
+            intro: currentElement.getAttribute('data-intro'),
2794
+            step: parseInt(currentElement.getAttribute('data-step'), 10),
2795
+            tooltipClass: currentElement.getAttribute('data-tooltipClass'),
2796
+            position: currentElement.getAttribute('data-position') || this._options.tooltipPosition
2797
+          };
2798
+        }
2799
+      }
2800
+
2801
+      //next add intro items without data-step
2802
+      //todo: we need a cleanup here, two loops are redundant
2803
+      var nextStep = 0;
2804
+      for (var i = 0, elmsLength = allIntroSteps.length; i < elmsLength; i++) {
2805
+        var currentElement = allIntroSteps[i];
2806
+
2807
+        if (currentElement.getAttribute('data-step') == null) {
2808
+
2809
+          while (true) {
2810
+            if (typeof introItems[nextStep] == 'undefined') {
2811
+              break;
2812
+            } else {
2813
+              nextStep++;
2814
+            }
2815
+          }
2816
+
2817
+          introItems[nextStep] = {
2818
+            element: currentElement,
2819
+            intro: currentElement.getAttribute('data-intro'),
2820
+            step: nextStep + 1,
2821
+            tooltipClass: currentElement.getAttribute('data-tooltipClass'),
2822
+            position: currentElement.getAttribute('data-position') || this._options.tooltipPosition
2823
+          };
2824
+        }
2825
+      }
2826
+    }
2827
+
2828
+    //removing undefined/null elements
2829
+    var tempIntroItems = [];
2830
+    for (var z = 0; z < introItems.length; z++) {
2831
+      introItems[z] && tempIntroItems.push(introItems[z]);  // copy non-empty values to the end of the array
2832
+    }
2833
+
2834
+    introItems = tempIntroItems;
2835
+
2836
+    //Ok, sort all items with given steps
2837
+    introItems.sort(function (a, b) {
2838
+      return a.step - b.step;
2839
+    });
2840
+
2841
+    //set it to the introJs object
2842
+    self._introItems = introItems;
2843
+
2844
+    //add overlay layer to the page
2845
+    if(_addOverlayLayer.call(self, targetElm)) {
2846
+      //then, start the show
2847
+      _nextStep.call(self);
2848
+
2849
+      var skipButton     = targetElm.querySelector('.introjs-skipbutton'),
2850
+          nextStepButton = targetElm.querySelector('.introjs-nextbutton');
2851
+
2852
+      self._onKeyDown = function(e) {
2853
+        if (e.keyCode === 27 && self._options.exitOnEsc == true) {
2854
+          propagate_exit = true;
2855
+          
2856
+          //check if any callback is defined
2857
+          if (self._introExitCallback != undefined) {
2858
+            propagate_exit = self._introExitCallback.call(self);
2859
+            if (typeof(propagate_exit) == "undefined")
2860
+              propagate_exit = true;
2861
+          }
2862
+          
2863
+          //escape key pressed, exit the intro
2864
+          if (propagate_exit)
2865
+            _exitIntro.call(self, targetElm);
2866
+          
2867
+        } else if(e.keyCode === 37) {
2868
+          //left arrow
2869
+          _previousStep.call(self);
2870
+        } else if (e.keyCode === 39 || e.keyCode === 13) {
2871
+          //right arrow or enter
2872
+          _nextStep.call(self);
2873
+          //prevent default behaviour on hitting Enter, to prevent steps being skipped in some browsers
2874
+          if(e.preventDefault) {
2875
+            e.preventDefault();
2876
+          } else {
2877
+            e.returnValue = false;
2878
+          }
2879
+        }
2880
+      };
2881
+
2882
+      self._onResize = function(e) {
2883
+        _setHelperLayerPosition.call(self, document.querySelector('.introjs-helperLayer'));
2884
+      };
2885
+
2886
+      if (window.addEventListener) {
2887
+        if (this._options.keyboardNavigation) {
2888
+          window.addEventListener('keydown', self._onKeyDown, true);
2889
+        }
2890
+        //for window resize
2891
+        window.addEventListener("resize", self._onResize, true);
2892
+      } else if (document.attachEvent) { //IE
2893
+        if (this._options.keyboardNavigation) {
2894
+          document.attachEvent('onkeydown', self._onKeyDown);
2895
+        }
2896
+        //for window resize
2897
+        document.attachEvent("onresize", self._onResize);
2898
+      }
2899
+    }
2900
+    return false;
2901
+  }
2902
+
2903
+ /*
2904
+   * makes a copy of the object
2905
+   * @api private
2906
+   * @method _cloneObject
2907
+  */
2908
+  function _cloneObject(object) {
2909
+      if (object == null || typeof (object) != 'object' || typeof (object.nodeType) != 'undefined') {
2910
+          return object;
2911
+      }
2912
+      var temp = {};
2913
+      for (var key in object) {
2914
+          temp[key] = _cloneObject(object[key]);
2915
+      }
2916
+      return temp;
2917
+  }
2918
+  /**
2919
+   * Go to specific step of introduction
2920
+   *
2921
+   * @api private
2922
+   * @method _goToStep
2923
+   */
2924
+  function _goToStep(step) {
2925
+    //because steps starts with zero
2926
+    this._currentStep = step - 2;
2927
+    if (typeof (this._introItems) !== 'undefined') {
2928
+      _nextStep.call(this);
2929
+    }
2930
+  }
2931
+
2932
+  /**
2933
+   * Go to next step on intro
2934
+   *
2935
+   * @api private
2936
+   * @method _nextStep
2937
+   */
2938
+  function _nextStep() {
2939
+    this._direction = 'forward';
2940
+
2941
+    if (typeof (this._currentStep) === 'undefined') {
2942
+      this._currentStep = 0;
2943
+    } else {
2944
+      ++this._currentStep;
2945
+    }
2946
+
2947
+    if ((this._introItems.length) <= this._currentStep) {
2948
+      //end of the intro
2949
+      //check if any callback is defined
2950
+      if (typeof (this._introCompleteCallback) === 'function') {
2951
+        this._introCompleteCallback.call(this);
2952
+      }
2953
+      _exitIntro.call(this, this._targetElement);
2954
+      return;
2955
+    }
2956
+
2957
+    var nextStep = this._introItems[this._currentStep];
2958
+    if (typeof (this._introBeforeChangeCallback) !== 'undefined') {
2959
+      this._introBeforeChangeCallback.call(this, nextStep.element);
2960
+    }
2961
+
2962
+    _showElement.call(this, nextStep);
2963
+  }
2964
+
2965
+  /**
2966
+   * Go to previous step on intro
2967
+   *
2968
+   * @api private
2969
+   * @method _nextStep
2970
+   */
2971
+  function _previousStep() {
2972
+    this._direction = 'backward';
2973
+
2974
+    if (this._currentStep === 0) {
2975
+      return false;
2976
+    }
2977
+
2978
+    var nextStep = this._introItems[--this._currentStep];
2979
+    if (typeof (this._introBeforeChangeCallback) !== 'undefined') {
2980
+      this._introBeforeChangeCallback.call(this, nextStep.element);
2981
+    }
2982
+
2983
+    _showElement.call(this, nextStep);
2984
+  }
2985
+
2986
+  /**
2987
+   * Exit from intro
2988
+   *
2989
+   * @api private
2990
+   * @method _exitIntro
2991
+   * @param {Object} targetElement
2992
+   */
2993
+  function _exitIntro(targetElement) {
2994
+    //remove overlay layer from the page
2995
+    var overlayLayer = targetElement.querySelector('.introjs-overlay');
2996
+
2997
+    //return if intro already completed or skipped
2998
+    if (overlayLayer == null) {
2999
+      return;
3000
+    }
3001
+
3002
+    //for fade-out animation
3003
+    overlayLayer.style.opacity = 0;
3004
+    setTimeout(function () {
3005
+      if (overlayLayer.parentNode) {
3006
+        overlayLayer.parentNode.removeChild(overlayLayer);
3007
+      }
3008
+    }, 500);
3009
+
3010
+    //remove all helper layers
3011
+    var helperLayer = targetElement.querySelector('.introjs-helperLayer');
3012
+    if (helperLayer) {
3013
+      helperLayer.parentNode.removeChild(helperLayer);
3014
+    }
3015
+
3016
+    //remove intro floating element
3017
+    var floatingElement = document.querySelector('.introjsFloatingElement');
3018
+    if (floatingElement) {
3019
+      floatingElement.parentNode.removeChild(floatingElement);
3020
+    }
3021
+
3022
+    //remove `introjs-showElement` class from the element
3023
+    var showElement = document.querySelector('.introjs-showElement');
3024
+    if (showElement) {
3025
+      showElement.className = showElement.className.replace(/introjs-[a-zA-Z]+/g, '').replace(/^\s+|\s+$/g, ''); // This is a manual trim.
3026
+    }
3027
+
3028
+    //remove `introjs-fixParent` class from the elements
3029
+    var fixParents = document.querySelectorAll('.introjs-fixParent');
3030
+    if (fixParents && fixParents.length > 0) {
3031
+      for (var i = fixParents.length - 1; i >= 0; i--) {
3032
+        fixParents[i].className = fixParents[i].className.replace(/introjs-fixParent/g, '').replace(/^\s+|\s+$/g, '');
3033
+      };
3034
+    }
3035
+
3036
+    //clean listeners
3037
+    if (window.removeEventListener) {
3038
+      window.removeEventListener('keydown', this._onKeyDown, true);
3039
+    } else if (document.detachEvent) { //IE
3040
+      document.detachEvent('onkeydown', this._onKeyDown);
3041
+    }
3042
+
3043
+    //set the step to zero
3044
+    this._currentStep = undefined;
3045
+  }
3046
+
3047
+  /**
3048
+   * Render tooltip box in the page
3049
+   *
3050
+   * @api private
3051
+   * @method _placeTooltip
3052
+   * @param {Object} targetElement
3053
+   * @param {Object} tooltipLayer
3054
+   * @param {Object} arrowLayer
3055
+   */
3056
+  function _placeTooltip(targetElement, tooltipLayer, arrowLayer, helperNumberLayer) {
3057
+    var tooltipCssClass = '',
3058
+        currentStepObj,
3059
+        tooltipOffset,
3060
+        targetElementOffset;
3061
+
3062
+    //reset the old style
3063
+    tooltipLayer.style.top        = null;
3064
+    tooltipLayer.style.right      = null;
3065
+    tooltipLayer.style.bottom     = null;
3066
+    tooltipLayer.style.left       = null;
3067
+    tooltipLayer.style.marginLeft = null;
3068
+    tooltipLayer.style.marginTop  = null;
3069
+
3070
+    arrowLayer.style.display = 'inherit';
3071
+
3072
+    if (typeof(helperNumberLayer) != 'undefined' && helperNumberLayer != null) {
3073
+      helperNumberLayer.style.top  = null;
3074
+      helperNumberLayer.style.left = null;
3075
+    }
3076
+
3077
+    //prevent error when `this._currentStep` is undefined
3078
+    if (!this._introItems[this._currentStep]) return;
3079
+
3080
+    //if we have a custom css class for each step
3081
+    currentStepObj = this._introItems[this._currentStep];
3082
+    if (typeof (currentStepObj.tooltipClass) === 'string') {
3083
+      tooltipCssClass = currentStepObj.tooltipClass;
3084
+    } else {
3085
+      tooltipCssClass = this._options.tooltipClass;
3086
+    }
3087
+
3088
+    tooltipLayer.className = ('introjs-tooltip ' + tooltipCssClass).replace(/^\s+|\s+$/g, '');
3089
+
3090
+    //custom css class for tooltip boxes
3091
+    var tooltipCssClass = this._options.tooltipClass;
3092
+
3093
+    currentTooltipPosition = this._introItems[this._currentStep].position;
3094
+    switch (currentTooltipPosition) {
3095
+      case 'top':
3096
+        tooltipLayer.style.left = '15px';
3097
+        tooltipLayer.style.top = '-' + (_getOffset(tooltipLayer).height + 10) + 'px';
3098
+        arrowLayer.className = 'introjs-arrow bottom';
3099
+        break;
3100
+      case 'right':
3101
+        tooltipLayer.style.left = (_getOffset(targetElement).width + 20) + 'px';
3102
+        arrowLayer.className = 'introjs-arrow left';
3103
+        break;
3104
+      case 'left':
3105
+        if (this._options.showStepNumbers == true) {
3106
+          tooltipLayer.style.top = '15px';
3107
+        }
3108
+        tooltipLayer.style.right = (_getOffset(targetElement).width + 20) + 'px';
3109
+        arrowLayer.className = 'introjs-arrow right';
3110
+        break;
3111
+      case 'floating':
3112
+        arrowLayer.style.display = 'none';
3113
+
3114
+        //we have to adjust the top and left of layer manually for intro items without element
3115
+        tooltipOffset = _getOffset(tooltipLayer);
3116
+
3117
+        tooltipLayer.style.left   = '50%';
3118
+        tooltipLayer.style.top    = '50%';
3119
+        tooltipLayer.style.marginLeft = '-' + (tooltipOffset.width / 2)  + 'px';
3120
+        tooltipLayer.style.marginTop  = '-' + (tooltipOffset.height / 2) + 'px';
3121
+
3122
+        if (typeof(helperNumberLayer) != 'undefined' && helperNumberLayer != null) {
3123
+          helperNumberLayer.style.left = '-' + ((tooltipOffset.width / 2) + 18) + 'px';
3124
+          helperNumberLayer.style.top  = '-' + ((tooltipOffset.height / 2) + 18) + 'px';
3125
+        }
3126
+
3127
+        break;
3128
+      case 'bottom-right-aligned':
3129
+        arrowLayer.className      = 'introjs-arrow top-right';
3130
+        tooltipLayer.style.right  = '0px';
3131
+        tooltipLayer.style.bottom = '-' + (_getOffset(tooltipLayer).height + 10) + 'px';
3132
+        break;
3133
+      case 'bottom-middle-aligned':
3134
+        targetElementOffset = _getOffset(targetElement);
3135
+        tooltipOffset       = _getOffset(tooltipLayer);
3136
+
3137
+        arrowLayer.className      = 'introjs-arrow top-middle';
3138
+        tooltipLayer.style.left   = (targetElementOffset.width / 2 - tooltipOffset.width / 2) + 'px';
3139
+        tooltipLayer.style.bottom = '-' + (tooltipOffset.height + 10) + 'px';
3140
+        break;
3141
+      case 'bottom-left-aligned':
3142
+      // Bottom-left-aligned is the same as the default bottom
3143
+      case 'bottom':
3144
+      // Bottom going to follow the default behavior
3145
+      default:
3146
+        tooltipLayer.style.bottom = '-' + (_getOffset(tooltipLayer).height + 10) + 'px';
3147
+        arrowLayer.className = 'introjs-arrow top';
3148
+        break;
3149
+    }
3150
+  }
3151
+
3152
+  /**
3153
+   * Update the position of the helper layer on the screen
3154
+   *
3155
+   * @api private
3156
+   * @method _setHelperLayerPosition
3157
+   * @param {Object} helperLayer
3158
+   */
3159
+  function _setHelperLayerPosition(helperLayer) {
3160
+    if (helperLayer) {
3161
+      //prevent error when `this._currentStep` in undefined
3162
+      if (!this._introItems[this._currentStep]) return;
3163
+
3164
+      var currentElement  = this._introItems[this._currentStep],
3165
+          elementPosition = _getOffset(currentElement.element),
3166
+          widthHeightPadding = 10;
3167
+
3168
+      if (currentElement.position == 'floating') {
3169
+        widthHeightPadding = 0;
3170
+      }
3171
+
3172
+      //set new position to helper layer
3173
+      helperLayer.setAttribute('style', 'width: ' + (elementPosition.width  + widthHeightPadding)  + 'px; ' +
3174
+                                        'height:' + (elementPosition.height + widthHeightPadding)  + 'px; ' +
3175
+                                        'top:'    + (elementPosition.top    - 5)   + 'px;' +
3176
+                                        'left: '  + (elementPosition.left   - 5)   + 'px;');
3177
+    }
3178
+  }
3179
+
3180
+  /**
3181
+   * Show an element on the page
3182
+   *
3183
+   * @api private
3184
+   * @method _showElement
3185
+   * @param {Object} targetElement
3186
+   */
3187
+  function _showElement(targetElement) {
3188
+
3189
+    if (typeof (this._introChangeCallback) !== 'undefined') {
3190
+        this._introChangeCallback.call(this, targetElement.element);
3191
+    }
3192
+
3193
+    var self = this,
3194
+        oldHelperLayer = document.querySelector('.introjs-helperLayer'),
3195
+        elementPosition = _getOffset(targetElement.element);
3196
+
3197
+    if (oldHelperLayer != null) {
3198
+      var oldHelperNumberLayer = oldHelperLayer.querySelector('.introjs-helperNumberLayer'),
3199
+          oldtooltipLayer      = oldHelperLayer.querySelector('.introjs-tooltiptext'),
3200
+          oldArrowLayer        = oldHelperLayer.querySelector('.introjs-arrow'),
3201
+          oldtooltipContainer  = oldHelperLayer.querySelector('.introjs-tooltip'),
3202
+          skipTooltipButton    = oldHelperLayer.querySelector('.introjs-skipbutton'),
3203
+          prevTooltipButton    = oldHelperLayer.querySelector('.introjs-prevbutton'),
3204
+          nextTooltipButton    = oldHelperLayer.querySelector('.introjs-nextbutton');
3205
+
3206
+      //hide the tooltip
3207
+      oldtooltipContainer.style.opacity = 0;
3208
+
3209
+      if (oldHelperNumberLayer != null) {
3210
+        var lastIntroItem = this._introItems[(targetElement.step - 2 >= 0 ? targetElement.step - 2 : 0)];
3211
+
3212
+        if (lastIntroItem != null && (this._direction == 'forward' && lastIntroItem.position == 'floating') || (this._direction == 'backward' && targetElement.position == 'floating')) {
3213
+          oldHelperNumberLayer.style.opacity = 0;
3214
+        }
3215
+      }
3216
+
3217
+      //set new position to helper layer
3218
+      _setHelperLayerPosition.call(self, oldHelperLayer);
3219
+
3220
+      //remove `introjs-fixParent` class from the elements
3221
+      var fixParents = document.querySelectorAll('.introjs-fixParent');
3222
+      if (fixParents && fixParents.length > 0) {
3223
+        for (var i = fixParents.length - 1; i >= 0; i--) {
3224
+          fixParents[i].className = fixParents[i].className.replace(/introjs-fixParent/g, '').replace(/^\s+|\s+$/g, '');
3225
+        };
3226
+      }
3227
+
3228
+      //remove old classes
3229
+      var oldShowElement = document.querySelector('.introjs-showElement');
3230
+      oldShowElement.className = oldShowElement.className.replace(/introjs-[a-zA-Z]+/g, '').replace(/^\s+|\s+$/g, '');
3231
+      //we should wait until the CSS3 transition is competed (it's 0.3 sec) to prevent incorrect `height` and `width` calculation
3232
+      if (self._lastShowElementTimer) {
3233
+        clearTimeout(self._lastShowElementTimer);
3234
+      }
3235
+      self._lastShowElementTimer = setTimeout(function() {
3236
+        //set current step to the label
3237
+        if (oldHelperNumberLayer != null) {
3238
+          oldHelperNumberLayer.innerHTML = targetElement.step;
3239
+        }
3240
+        //set current tooltip text
3241
+        oldtooltipLayer.innerHTML = targetElement.intro;
3242
+        //set the tooltip position
3243
+        _placeTooltip.call(self, targetElement.element, oldtooltipContainer, oldArrowLayer, oldHelperNumberLayer);
3244
+
3245
+        //change active bullet
3246
+        oldHelperLayer.querySelector('.introjs-bullets li > a.active').className = '';
3247
+        oldHelperLayer.querySelector('.introjs-bullets li > a[data-stepnumber="' + targetElement.step + '"]').className = 'active';
3248
+
3249
+        //show the tooltip
3250
+        oldtooltipContainer.style.opacity = 1;
3251
+        if (oldHelperNumberLayer) oldHelperNumberLayer.style.opacity = 1;
3252
+      }, 350);
3253
+
3254
+    } else {
3255
+      var helperLayer       = document.createElement('div'),
3256
+          arrowLayer        = document.createElement('div'),
3257
+          tooltipLayer      = document.createElement('div'),
3258
+          tooltipTextLayer  = document.createElement('div'),
3259
+          bulletsLayer      = document.createElement('div'),
3260
+          buttonsLayer      = document.createElement('div');
3261
+
3262
+      helperLayer.className = 'introjs-helperLayer';
3263
+
3264
+      //set new position to helper layer
3265
+      _setHelperLayerPosition.call(self, helperLayer);
3266
+
3267
+      //add helper layer to target element
3268
+      this._targetElement.appendChild(helperLayer);
3269
+
3270
+      arrowLayer.className = 'introjs-arrow';
3271
+
3272
+      tooltipTextLayer.className = 'introjs-tooltiptext';
3273
+      tooltipTextLayer.innerHTML = targetElement.intro;
3274
+
3275
+      bulletsLayer.className = 'introjs-bullets';
3276
+
3277
+      if (this._options.showBullets === false) {
3278
+        bulletsLayer.style.display = 'none';
3279
+      }
3280
+
3281
+      var ulContainer = document.createElement('ul');
3282
+
3283
+      for (var i = 0, stepsLength = this._introItems.length; i < stepsLength; i++) {
3284
+        var innerLi    = document.createElement('li');
3285
+        var anchorLink = document.createElement('a');
3286
+
3287
+        anchorLink.onclick = function() {
3288
+          self.goToStep(this.getAttribute('data-stepnumber'));
3289
+        };
3290
+
3291
+        if (i === (targetElement.step-1)) anchorLink.className = "active";
3292
+
3293
+        anchorLink.href = 'javascript:void(0);';
3294
+        anchorLink.innerHTML = "&nbsp;";
3295
+        anchorLink.setAttribute('data-stepnumber', this._introItems[i].step);
3296
+
3297
+        innerLi.appendChild(anchorLink);
3298
+        ulContainer.appendChild(innerLi);
3299
+      }
3300
+
3301
+      bulletsLayer.appendChild(ulContainer);
3302
+
3303
+      buttonsLayer.className = 'introjs-tooltipbuttons';
3304
+      if (this._options.showButtons === false) {
3305
+        buttonsLayer.style.display = 'none';
3306
+      }
3307
+
3308
+      tooltipLayer.className = 'introjs-tooltip';
3309
+      tooltipLayer.appendChild(tooltipTextLayer);
3310
+      tooltipLayer.appendChild(bulletsLayer);
3311
+
3312
+      //add helper layer number
3313
+      if (this._options.showStepNumbers == true) {
3314
+        var helperNumberLayer = document.createElement('span');
3315
+        helperNumberLayer.className = 'introjs-helperNumberLayer';
3316
+        helperNumberLayer.innerHTML = targetElement.step;
3317
+        helperLayer.appendChild(helperNumberLayer);
3318
+      }
3319
+      tooltipLayer.appendChild(arrowLayer);
3320
+      helperLayer.appendChild(tooltipLayer);
3321
+
3322
+      //next button
3323
+      var nextTooltipButton = document.createElement('a');
3324
+
3325
+      nextTooltipButton.onclick = function() {
3326
+        if (self._introItems.length - 1 != self._currentStep) {
3327
+          _nextStep.call(self);
3328
+        }
3329
+      };
3330
+
3331
+      nextTooltipButton.href = 'javascript:void(0);';
3332
+      nextTooltipButton.innerHTML = this._options.nextLabel;
3333
+
3334
+      //previous button
3335
+      var prevTooltipButton = document.createElement('a');
3336
+
3337
+      prevTooltipButton.onclick = function() {
3338
+        if (self._currentStep != 0) {
3339
+          _previousStep.call(self);
3340
+        }
3341
+      };
3342
+
3343
+      prevTooltipButton.href = 'javascript:void(0);';
3344
+      prevTooltipButton.innerHTML = this._options.prevLabel;
3345
+
3346
+      //skip button
3347
+      var skipTooltipButton = document.createElement('a');
3348
+      skipTooltipButton.className = 'introjs-button introjs-skipbutton';
3349
+      skipTooltipButton.href = 'javascript:void(0);';
3350
+      skipTooltipButton.innerHTML = this._options.skipLabel;
3351
+
3352
+      skipTooltipButton.onclick = function() {
3353
+        propagate_exit = true;
3354
+        
3355
+        if (self._introItems.length - 1 == self._currentStep && typeof (self._introCompleteCallback) === 'function') {
3356
+          propagate_exit = self._introCompleteCallback.call(self);
3357
+          if (typeof(propagate_exit) == "undefined")
3358
+            propagate_exit = true;
3359
+        }
3360
+        
3361
+        if (self._introItems.length - 1 != self._currentStep && typeof (self._introExitCallback) === 'function') {
3362
+          propagate_exit = self._introExitCallback.call(self);
3363
+          if (typeof(propagate_exit) == "undefined")
3364
+            propagate_exit = true;
3365
+        }
3366
+        
3367
+        if (propagate_exit)
3368
+          _exitIntro.call(self, self._targetElement);
3369
+      };
3370
+
3371
+      buttonsLayer.appendChild(skipTooltipButton);
3372
+
3373
+      //in order to prevent displaying next/previous button always
3374
+      if (this._introItems.length > 1) {
3375
+        buttonsLayer.appendChild(prevTooltipButton);
3376
+        buttonsLayer.appendChild(nextTooltipButton);
3377
+      }
3378
+
3379
+      tooltipLayer.appendChild(buttonsLayer);
3380
+
3381
+      //set proper position
3382
+      _placeTooltip.call(self, targetElement.element, tooltipLayer, arrowLayer, helperNumberLayer);
3383
+    }
3384
+
3385
+    if (this._currentStep == 0 && this._introItems.length > 1) {
3386
+      prevTooltipButton.className = 'introjs-button introjs-prevbutton introjs-disabled';
3387
+      nextTooltipButton.className = 'introjs-button introjs-nextbutton';
3388
+      skipTooltipButton.innerHTML = this._options.skipLabel;
3389
+    } else if (this._introItems.length - 1 == this._currentStep || this._introItems.length == 1) {
3390
+      skipTooltipButton.innerHTML = this._options.doneLabel;
3391
+      prevTooltipButton.className = 'introjs-button introjs-prevbutton';
3392
+      nextTooltipButton.className = 'introjs-button introjs-nextbutton introjs-disabled';
3393
+    } else {
3394
+      prevTooltipButton.className = 'introjs-button introjs-prevbutton';
3395
+      nextTooltipButton.className = 'introjs-button introjs-nextbutton';
3396
+      skipTooltipButton.innerHTML = this._options.skipLabel;
3397
+    }
3398
+
3399
+    //Set focus on "next" button, so that hitting Enter always moves you onto the next step
3400
+    nextTooltipButton.focus();
3401
+
3402
+    //add target element position style
3403
+    targetElement.element.className += ' introjs-showElement';
3404
+
3405
+    var currentElementPosition = _getPropValue(targetElement.element, 'position');
3406
+    if (currentElementPosition !== 'absolute' &&
3407
+        currentElementPosition !== 'relative') {
3408
+      //change to new intro item
3409
+      targetElement.element.className += ' introjs-relativePosition';
3410
+    }
3411
+
3412
+    var parentElm = targetElement.element.parentNode;
3413
+    while (parentElm != null) {
3414
+      if (parentElm.tagName.toLowerCase() === 'body') break;
3415
+
3416
+      //fix The Stacking Contenxt problem.
3417
+      //More detail: https://developer.mozilla.org/en-US/docs/Web/Guide/CSS/Understanding_z_index/The_stacking_context
3418
+      var zIndex = _getPropValue(parentElm, 'z-index');
3419
+      var opacity = parseFloat(_getPropValue(parentElm, 'opacity'));
3420
+      var transform = _getPropValue(parentElm, 'transform') || _getPropValue(parentElm, '-webkit-transform') || _getPropValue(parentElm, '-moz-transform') || _getPropValue(parentElm, '-ms-transform') || _getPropValue(parentElm, '-o-transform');
3421
+      if (/[0-9]+/.test(zIndex) || opacity < 1 || transform !== 'none') {
3422
+        parentElm.className += ' introjs-fixParent';
3423
+      }
3424
+
3425
+      parentElm = parentElm.parentNode;
3426
+    }
3427
+
3428
+    if (!_elementInViewport(targetElement.element) && this._options.scrollToElement === true) {
3429
+      var rect = targetElement.element.getBoundingClientRect(),
3430
+        winHeight=_getWinSize().height,
3431
+        top = rect.bottom - (rect.bottom - rect.top),
3432
+        bottom = rect.bottom - winHeight;
3433
+
3434
+      //Scroll up
3435
+      if (top < 0 || targetElement.element.clientHeight > winHeight) {
3436
+        window.scrollBy(0, top - 30); // 30px padding from edge to look nice
3437
+
3438
+      //Scroll down
3439
+      } else {
3440
+        window.scrollBy(0, bottom + 100); // 70px + 30px padding from edge to look nice
3441
+      }
3442
+    }
3443
+
3444
+    if (typeof (this._introAfterChangeCallback) !== 'undefined') {
3445
+        this._introAfterChangeCallback.call(this, targetElement.element);
3446
+    }
3447
+  }
3448
+
3449
+  /**
3450
+   * Get an element CSS property on the page
3451
+   * Thanks to JavaScript Kit: http://www.javascriptkit.com/dhtmltutors/dhtmlcascade4.shtml
3452
+   *
3453
+   * @api private
3454
+   * @method _getPropValue
3455
+   * @param {Object} element
3456
+   * @param {String} propName
3457
+   * @returns Element's property value
3458
+   */
3459
+  function _getPropValue (element, propName) {
3460
+    var propValue = '';
3461
+    if (element.currentStyle) { //IE
3462
+      propValue = element.currentStyle[propName];
3463
+    } else if (document.defaultView && document.defaultView.getComputedStyle) { //Others
3464
+      propValue = document.defaultView.getComputedStyle(element, null).getPropertyValue(propName);
3465
+    }
3466
+
3467
+    //Prevent exception in IE
3468
+    if (propValue && propValue.toLowerCase) {
3469
+      return propValue.toLowerCase();
3470
+    } else {
3471
+      return propValue;
3472
+    }
3473
+  }
3474
+
3475
+  /**
3476
+   * Provides a cross-browser way to get the screen dimensions
3477
+   * via: http://stackoverflow.com/questions/5864467/internet-explorer-innerheight
3478
+   *
3479
+   * @api private
3480
+   * @method _getWinSize
3481
+   * @returns {Object} width and height attributes
3482
+   */
3483
+  function _getWinSize() {
3484
+    if (window.innerWidth != undefined) {
3485
+      return { width: window.innerWidth, height: window.innerHeight };
3486
+    } else {
3487
+      var D = document.documentElement;
3488
+      return { width: D.clientWidth, height: D.clientHeight };
3489
+    }
3490
+  }
3491
+
3492
+  /**
3493
+   * Add overlay layer to the page
3494
+   * http://stackoverflow.com/questions/123999/how-to-tell-if-a-dom-element-is-visible-in-the-current-viewport
3495
+   *
3496
+   * @api private
3497
+   * @method _elementInViewport
3498
+   * @param {Object} el
3499
+   */
3500
+  function _elementInViewport(el) {
3501
+    var rect = el.getBoundingClientRect();
3502
+
3503
+    return (
3504
+      rect.top >= 0 &&
3505
+      rect.left >= 0 &&
3506
+      (rect.bottom+80) <= window.innerHeight && // add 80 to get the text right
3507
+      rect.right <= window.innerWidth
3508
+    );
3509
+  }
3510
+
3511
+  /**
3512
+   * Add overlay layer to the page
3513
+   *
3514
+   * @api private
3515
+   * @method _addOverlayLayer
3516
+   * @param {Object} targetElm
3517
+   */
3518
+  function _addOverlayLayer(targetElm) {
3519
+    var overlayLayer = document.createElement('div'),
3520
+        styleText = '',
3521
+        self = this;
3522
+
3523
+    //set css class name
3524
+    overlayLayer.className = 'introjs-overlay';
3525
+
3526
+    //check if the target element is body, we should calculate the size of overlay layer in a better way
3527
+    if (targetElm.tagName.toLowerCase() === 'body') {
3528
+      styleText += 'top: 0;bottom: 0; left: 0;right: 0;position: fixed;';
3529
+      overlayLayer.setAttribute('style', styleText);
3530
+    } else {
3531
+      //set overlay layer position
3532
+      var elementPosition = _getOffset(targetElm);
3533
+      if (elementPosition) {
3534
+        styleText += 'width: ' + elementPosition.width + 'px; height:' + elementPosition.height + 'px; top:' + elementPosition.top + 'px;left: ' + elementPosition.left + 'px;';
3535
+        overlayLayer.setAttribute('style', styleText);
3536
+      }
3537
+    }
3538
+
3539
+    targetElm.appendChild(overlayLayer);
3540
+
3541
+    overlayLayer.onclick = function() {
3542
+      if (self._options.exitOnOverlayClick == true) {
3543
+        _exitIntro.call(self, targetElm);
3544
+
3545
+        //check if any callback is defined
3546
+        if (self._introExitCallback != undefined) {
3547
+          self._introExitCallback.call(self);
3548
+        }
3549
+      }
3550
+    };
3551
+
3552
+    setTimeout(function() {
3553
+      styleText += 'opacity: ' + self._options.overlayOpacity.toString() + ';';
3554
+      overlayLayer.setAttribute('style', styleText);
3555
+    }, 10);
3556
+
3557
+    return true;
3558
+  }
3559
+
3560
+  /**
3561
+   * Get an element position on the page
3562
+   * Thanks to `meouw`: http://stackoverflow.com/a/442474/375966
3563
+   *
3564
+   * @api private
3565
+   * @method _getOffset
3566
+   * @param {Object} element
3567
+   * @returns Element's position info
3568
+   */
3569
+  function _getOffset(element) {
3570
+    var elementPosition = {};
3571
+
3572
+    //set width
3573
+    elementPosition.width = element.offsetWidth;
3574
+
3575
+    //set height
3576
+    elementPosition.height = element.offsetHeight;
3577
+
3578
+    //calculate element top and left
3579
+    var _x = 0;
3580
+    var _y = 0;
3581
+    while (element && !isNaN(element.offsetLeft) && !isNaN(element.offsetTop)) {
3582
+      _x += element.offsetLeft;
3583
+      _y += element.offsetTop;
3584
+      element = element.offsetParent;
3585
+    }
3586
+    //set top
3587
+    elementPosition.top = _y;
3588
+    //set left
3589
+    elementPosition.left = _x;
3590
+
3591
+    return elementPosition;
3592
+  }
3593
+
3594
+  /**
3595
+   * Overwrites obj1's values with obj2's and adds obj2's if non existent in obj1
3596
+   * via: http://stackoverflow.com/questions/171251/how-can-i-merge-properties-of-two-javascript-objects-dynamically
3597
+   *
3598
+   * @param obj1
3599
+   * @param obj2
3600
+   * @returns obj3 a new object based on obj1 and obj2
3601
+   */
3602
+  function _mergeOptions(obj1,obj2) {
3603
+    var obj3 = {};
3604
+    for (var attrname in obj1) { obj3[attrname] = obj1[attrname]; }
3605
+    for (var attrname in obj2) { obj3[attrname] = obj2[attrname]; }
3606
+    return obj3;
3607
+  }
3608
+
3609
+  var introJs = function (targetElm) {
3610
+    if (typeof (targetElm) === 'object') {
3611
+      //Ok, create a new instance
3612
+      return new IntroJs(targetElm);
3613
+
3614
+    } else if (typeof (targetElm) === 'string') {
3615
+      //select the target element with query selector
3616
+      var targetElement = document.querySelector(targetElm);
3617
+
3618
+      if (targetElement) {
3619
+        return new IntroJs(targetElement);
3620
+      } else {
3621
+        throw new Error('There is no element with given selector.');
3622
+      }
3623
+    } else {
3624
+      return new IntroJs(document.body);
3625
+    }
3626
+  };
3627
+
3628
+  /**
3629
+   * Current IntroJs version
3630
+   *
3631
+   * @property version
3632
+   * @type String
3633
+   */
3634
+  introJs.version = VERSION;
3635
+
3636
+  //Prototype
3637
+  introJs.fn = IntroJs.prototype = {
3638
+    clone: function () {
3639
+      return new IntroJs(this);
3640
+    },
3641
+    setOption: function(option, value) {
3642
+      this._options[option] = value;
3643
+      return this;
3644
+    },
3645
+    setOptions: function(options) {
3646
+      this._options = _mergeOptions(this._options, options);
3647
+      return this;
3648
+    },
3649
+    start: function () {
3650
+      _introForElement.call(this, this._targetElement);
3651
+      return this;
3652
+    },
3653
+    goToStep: function(step) {
3654
+      _goToStep.call(this, step);
3655
+      return this;
3656
+    },
3657
+    nextStep: function() {
3658
+      _nextStep.call(this);
3659
+      return this;
3660
+    },
3661
+    previousStep: function() {
3662
+      _previousStep.call(this);
3663
+      return this;
3664
+    },
3665
+    exit: function() {
3666
+      _exitIntro.call(this, this._targetElement);
3667
+    },
3668
+    refresh: function() {
3669
+      _setHelperLayerPosition.call(this, document.querySelector('.introjs-helperLayer'));
3670
+      return this;
3671
+    },
3672
+    onbeforechange: function(providedCallback) {
3673
+      if (typeof (providedCallback) === 'function') {
3674
+        this._introBeforeChangeCallback = providedCallback;
3675
+      } else {
3676
+        throw new Error('Provided callback for onbeforechange was not a function');
3677
+      }
3678
+      return this;
3679
+    },
3680
+    onchange: function(providedCallback) {
3681
+      if (typeof (providedCallback) === 'function') {
3682
+        this._introChangeCallback = providedCallback;
3683
+      } else {
3684
+        throw new Error('Provided callback for onchange was not a function.');
3685
+      }
3686
+      return this;
3687
+    },
3688
+    onafterchange: function(providedCallback) {
3689
+      if (typeof (providedCallback) === 'function') {
3690
+        this._introAfterChangeCallback = providedCallback;
3691
+      } else {
3692
+        throw new Error('Provided callback for onafterchange was not a function');
3693
+      }
3694
+      return this;
3695
+    },
3696
+    oncomplete: function(providedCallback) {
3697
+      if (typeof (providedCallback) === 'function') {
3698
+        this._introCompleteCallback = providedCallback;
3699
+      } else {
3700
+        throw new Error('Provided callback for oncomplete was not a function.');
3701
+      }
3702
+      return this;
3703
+    },
3704
+    onexit: function(providedCallback) {
3705
+      if (typeof (providedCallback) === 'function') {
3706
+        this._introExitCallback = providedCallback;
3707
+      } else {
3708
+        throw new Error('Provided callback for onexit was not a function.');
3709
+      }
3710
+      return this;
3711
+    }
3712
+  };
3713
+
3714
+  exports.introJs = introJs;
3715
+  return introJs;
3716
+}));
3717
Index: include/javascript/clippy.js
3718
===================================================================
3719
--- include/javascript/clippy.js	(revision 0)
3720
+++ include/javascript/clippy.js	(revision 10417)
3721
@@ -0,0 +1,8 @@
3722
+function clippy_set_help(help_section) {
3723
+	document.cookie = 'clippy=' + help_section;
3724
+}
3725
+
3726
+function clippy_go_link_show_help(link, help_section) {
3727
+	document.cookie = 'clippy=' + help_section;
3728
+	window.location.href = link;
3729
+}
3730
\ No newline at end of file
3731
Index: include/functions_servers.php
3732
===================================================================
3733
--- include/functions_servers.php	(revision 10314)
3734
+++ include/functions_servers.php	(working copy)
3735
@@ -79,7 +79,9 @@
3736
 	$data["avg_interval_remote_modules"] = array();
3737
 	$data["avg_interval_local_modules"] = 0;
3738
 	$data["local_modules_rate"] = 0;
3739
+	$data["network_modules_rate"] = 0;
3740
 	
3741
+	
3742
 	if ($config["realtimestats"] == 1) {
3743
 		$counts = db_get_all_rows_sql ("SELECT tagente_modulo.id_modulo, COUNT(tagente_modulo.id_agente_modulo) modules
3744
 			FROM tagente_modulo, tagente_estado, tagente
3745
@@ -195,6 +197,8 @@
3746
 		$interval_avgs_agents = array();
3747
 	}
3748
 	
3749
+	$interval_avgs = array();
3750
+	
3751
 	// Merge with the previous calculated array
3752
 	foreach($interval_avgs_agents as $iaagents) {
3753
 		if(!isset($interval_avgs[$iaagents['id_modulo']]['modules'])) {
3754
Index: include/functions_treeview.php
3755
===================================================================
3756
--- include/functions_treeview.php	(revision 10314)
3757
+++ include/functions_treeview.php	(working copy)
3758
@@ -468,11 +468,19 @@
3759
 	echo '<table class="databox" style="width:98%">';
3760
 	echo '<tr><td style="width:50%" valign="top">';
3761
 	
3762
+	
3763
+	
3764
 	if (! defined ('METACONSOLE')) {
3765
+		
3766
 		$list = treeview_getData ($type);
3767
+		
3768
 	}
3769
 	else {
3770
-		$servers = db_get_all_rows_sql ("SELECT * FROM tmetaconsole_setup WHERE disabled = 0");
3771
+		$servers = db_get_all_rows_sql ("
3772
+			SELECT *
3773
+			FROM tmetaconsole_setup
3774
+			WHERE disabled = 0");
3775
+		
3776
 		if ($servers === false) {
3777
 			$servers = array();
3778
 		}
3779
@@ -502,6 +510,8 @@
3780
 		metaconsole_restore_db();
3781
 	}
3782
 	
3783
+	
3784
+	
3785
 	if ($list === false) {
3786
 		ui_print_error_message(__('There aren\'t agents in this agrupation'));
3787
 		echo '</td></tr>';
3788
@@ -543,19 +553,25 @@
3789
 			else {
3790
 				$id = $item['_id_'];
3791
 			}
3792
-
3793
+			
3794
 			echo "<a onfocus='JavaScript: this.blur()' href='javascript: loadSubTree(\"" . $type . "\",\"" . $id . "\", " . $lessBranchs . ", \"\", \"\")'>";
3795
 			
3796
 			echo $img . $item['_iconImg_'] ."&nbsp;" . __($item['_name_']) . ' (';
3797
 			
3798
-			$counts_info = array('total_count' => $item['_num_ok_'] + $item['_num_critical_'] + $item['_num_warning_'] + $item['_num_unknown_'],
3799
-					'normal_count' => $item['_num_ok_'],
3800
-					'critical_count' => $item['_num_critical_'],
3801
-					'warning_count' => $item['_num_warning_'],
3802
-					'unknown_count' => $item['_num_unknown_']);
3803
-
3804
+			$counts_info = array(
3805
+				'total_count' => $item['_num_ok_'] +
3806
+					$item['_num_critical_'] +
3807
+					$item['_num_warning_'] +
3808
+					$item['_num_unknown_'],
3809
+				'normal_count' => $item['_num_ok_'],
3810
+				'critical_count' => $item['_num_critical_'],
3811
+				'warning_count' => $item['_num_warning_'],
3812
+				'unknown_count' => $item['_num_unknown_']);
3813
+			
3814
+			
3815
 			reporting_tiny_stats($counts_info, false, $type);
3816
 			
3817
+			
3818
 			echo ') '. "</a>";
3819
 			
3820
 			echo "<div hiddenDiv='1' loadDiv='0' style='margin: 0px; padding: 0px;' class='tree_view' id='tree_div_" . $type . "_" . $id . "'></div>";
3821
@@ -581,7 +597,11 @@
3822
 	$avariableGroups = users_get_groups ();
3823
 	
3824
 	//Get all groups with agents
3825
-	$full_groups = db_get_all_rows_sql("SELECT DISTINCT id_grupo FROM tagente WHERE total_count > 0");
3826
+	$full_groups = db_get_all_rows_sql("
3827
+		SELECT DISTINCT id_grupo
3828
+		FROM tagente
3829
+		WHERE total_count > 0");
3830
+	
3831
 	if ($full_groups === false) {
3832
 		return array ();
3833
 	}
3834
@@ -607,9 +627,12 @@
3835
 		switch ($select_status) {
3836
 			case NORMAL:
3837
 				foreach ($avariableGroups as $group_name) {
3838
-					$id_group = db_get_value_sql('SELECT id_grupo FROM tgrupo where nombre ="' . $group_name . '"');
3839
+					$id_group = db_get_value_sql('
3840
+						SELECT id_grupo
3841
+						FROM tgrupo
3842
+						WHERE nombre ="' . $group_name . '"');
3843
 					
3844
-					$num_ok = groups_agent_ok($id_group);	
3845
+					$num_ok = groups_agent_ok($id_group);
3846
 					
3847
 					if ($num_ok <= 0)
3848
 						unset($avariableGroups[$id_group]);
3849
@@ -619,7 +642,10 @@
3850
 				break;
3851
 			case WARNING:
3852
 				foreach ($avariableGroups as $group_name) {
3853
-					$id_group = db_get_value_sql('SELECT id_grupo FROM tgrupo where nombre ="' . $group_name . '"');
3854
+					$id_group = db_get_value_sql('
3855
+						SELECT id_grupo
3856
+						FROM tgrupo
3857
+						WHERE nombre ="' . $group_name . '"');
3858
 					
3859
 					$num_warning = groups_agent_warning($id_group);
3860
 					
3861
@@ -629,7 +655,10 @@
3862
 				break;
3863
 			case CRITICAL:
3864
 				foreach ($avariableGroups as $group_name) {
3865
-					$id_group = db_get_value_sql('SELECT id_grupo FROM tgrupo where nombre ="' . $group_name . '"');
3866
+					$id_group = db_get_value_sql('
3867
+						SELECT id_grupo
3868
+						FROM tgrupo
3869
+						WHERE nombre ="' . $group_name . '"');
3870
 					
3871
 					$num_critical = groups_agent_critical($id_group);
3872
 					
3873
@@ -639,7 +668,10 @@
3874
 				break;
3875
 			case UNKNOWN:
3876
 				foreach ($avariableGroups as $group_name) {
3877
-					$id_group = db_get_value_sql('SELECT id_grupo FROM tgrupo where nombre ="' . $group_name . '"');
3878
+					$id_group = db_get_value_sql('
3879
+						SELECT id_grupo
3880
+						FROM tgrupo
3881
+						WHERE nombre ="' . $group_name . '"');
3882
 					
3883
 					$num_unknown = groups_agent_unknown($id_group);
3884
 					
3885
@@ -656,17 +688,42 @@
3886
 	}
3887
 	
3888
 	if ($search_free != '') {
3889
-		$sql_search = " AND id_grupo IN (SELECT id_grupo FROM tagente
3890
-			WHERE tagente.nombre COLLATE utf8_general_ci LIKE '%$search_free%')";
3891
+		switch ($config['dbtype']) {
3892
+			case "mysql":
3893
+				$sql_search = " AND id_grupo IN (
3894
+					SELECT id_grupo
3895
+					FROM tagente
3896
+					WHERE tagente.nombre COLLATE utf8_general_ci LIKE '%$search_free%')";
3897
+				break;
3898
+			case "postgresql":
3899
+				$sql_search = " AND id_grupo IN (
3900
+					SELECT id_grupo
3901
+					FROM tagente
3902
+					WHERE tagente.nombre LIKE '%$search_free%')";
3903
+				break;
3904
+			case "oracle":
3905
+				$sql_search = " AND id_grupo IN (
3906
+					SELECT id_grupo
3907
+					FROM tagente
3908
+					WHERE tagente.nombre COLLATE utf8_general_ci LIKE '%$search_free%')";
3909
+				break;
3910
+		}
3911
 	}
3912
 	else {
3913
 		$sql_search ='';
3914
 	}
3915
 	
3916
+	$order_collate = "";
3917
+	switch ($config['dbtype']) {
3918
+		case "mysql":
3919
+			$order_collate = "COLLATE utf8_general_ci";
3920
+			break;
3921
+	}
3922
+	
3923
 	switch ($type) {
3924
-		case 'os':		
3925
+		case 'os':
3926
 			$sql = agents_get_agents(array (
3927
-				'order' => 'nombre COLLATE utf8_general_ci ASC',
3928
+				'order' => 'nombre ' . $order_collate . ' ASC',
3929
 				'disabled' => 0,
3930
 				'status' => $select_status,
3931
 				'search' => $sql_search),
3932
@@ -676,7 +733,9 @@
3933
 				false,
3934
 				true);
3935
 			
3936
-			$sql_os = sprintf("SELECT * FROM tconfig_os WHERE id_os IN (%s)", $sql);
3937
+			$sql_os = sprintf("SELECT *
3938
+				FROM tconfig_os
3939
+				WHERE id_os IN (%s)", $sql);
3940
 			
3941
 			$list = db_get_all_rows_sql($sql_os);
3942
 			
3943
@@ -692,17 +751,31 @@
3944
 			
3945
 			switch ($config["dbtype"]) {
3946
 				case "mysql":
3947
+					$list = db_get_all_rows_sql("
3948
+						SELECT *
3949
+						FROM tgrupo
3950
+						WHERE nombre IN (" . $stringAvariableGroups . ") $sql_search
3951
+						ORDER BY nombre COLLATE utf8_general_ci ASC");
3952
+					break;
3953
 				case "postgresql":
3954
-					$list = db_get_all_rows_sql("SELECT * FROM tgrupo WHERE nombre IN (" . $stringAvariableGroups . ") $sql_search ORDER BY nombre COLLATE utf8_general_ci ASC");
3955
+					$list = db_get_all_rows_sql("
3956
+						SELECT *
3957
+						FROM tgrupo
3958
+						WHERE nombre IN (" . $stringAvariableGroups . ") $sql_search
3959
+						ORDER BY nombre ASC");
3960
 					break;
3961
 				case "oracle":
3962
-					$list = db_get_all_rows_sql("SELECT * FROM tgrupo WHERE dbms_lob.substr(nombre,4000,1) IN (" . $stringAvariableGroups . ") ORDER BY nombre COLLATE utf8_general_ci ASC");
3963
+					$list = db_get_all_rows_sql("
3964
+						SELECT *
3965
+						FROM tgrupo
3966
+						WHERE dbms_lob.substr(nombre,4000,1) IN (" . $stringAvariableGroups . ")
3967
+						ORDER BY nombre COLLATE utf8_general_ci ASC");
3968
 					break;
3969
 			}
3970
 			break;
3971
 		case 'module_group':
3972
 			$sql = agents_get_agents(array (
3973
-				'order' => 'nombre COLLATE utf8_general_ci ASC',
3974
+				'order' => 'nombre ' . $order_collate . ' ASC',
3975
 				'disabled' => 0,
3976
 				'status' => $select_status,
3977
 				'search' => $sql_search),
3978
@@ -714,8 +787,13 @@
3979
 			// Skip agents without modules
3980
 			$sql .= ' AND tagente.total_count>0';
3981
 			
3982
-			$sql_module_groups = sprintf("SELECT * FROM tmodule_group
3983
-				WHERE id_mg IN (SELECT id_module_group FROM tagente_modulo WHERE id_agente IN (%s))", $sql);			
3984
+			$sql_module_groups = sprintf("
3985
+				SELECT *
3986
+				FROM tmodule_group
3987
+				WHERE id_mg IN (
3988
+					SELECT id_module_group
3989
+					FROM tagente_modulo
3990
+					WHERE id_agente IN (%s))", $sql);
3991
 			
3992
 			
3993
 			$list = db_get_all_rows_sql($sql_module_groups);
3994
@@ -734,7 +812,8 @@
3995
 			$groups = implode(',',$groups_id);
3996
 			
3997
 			if ($search_free != '') {
3998
-				$sql = "SELECT DISTINCT tpolicies.id, tpolicies.name
3999
+				$sql = "
4000
+					SELECT DISTINCT tpolicies.id, tpolicies.name
4001
 					FROM tpolicies, tpolicy_modules,
4002
 						tagente_estado, tagente, tagente_modulo
4003
 					WHERE 
4004
@@ -749,7 +828,7 @@
4005
 						tagente.nombre LIKE '%$search_free%' AND
4006
 						tagente.disabled = 0 AND
4007
 						tagente_modulo.disabled = 0
4008
-						ORDER BY tpolicies.name COLLATE utf8_general_ci ASC";
4009
+					ORDER BY tpolicies.name COLLATE utf8_general_ci ASC";
4010
 				
4011
 				$list = db_get_all_rows_sql($sql);
4012
 				
4013
@@ -825,7 +904,7 @@
4014
 						tagente.id_grupo IN ($groups) AND
4015
 						tagente.disabled = 0 AND
4016
 						tagente_modulo.disabled = 0
4017
-						ORDER BY tpolicies.name COLLATE utf8_general_ci ASC");
4018
+						ORDER BY tpolicies.name ' . $order_collate . ' ASC");
4019
 				
4020
 				$element = 0;
4021
 				switch ($select_status) {
4022
@@ -889,8 +968,28 @@
4023
 			}
4024
 			
4025
 			if ($search_free != '') {
4026
-				$sql_search = " AND t1.id_agente IN (SELECT id_agente FROM tagente
4027
-					WHERE nombre COLLATE utf8_general_ci LIKE '%$search_free%')";
4028
+				switch ($config['dbtype']) {
4029
+					case "mysql":
4030
+						$sql_search = " AND t1.id_agente IN (
4031
+							SELECT id_agente
4032
+							FROM tagente
4033
+							WHERE nombre COLLATE utf8_general_ci LIKE '%$search_free%')";
4034
+						break;
4035
+					case "postgresql":
4036
+						$sql_search = " AND t1.id_agente IN (
4037
+							SELECT id_agente
4038
+							FROM tagente
4039
+							WHERE nombre LIKE '%$search_free%')";
4040
+						break;
4041
+					case "oracle":
4042
+						$sql_search = " AND t1.id_agente IN (
4043
+							SELECT id_agente
4044
+							FROM tagente
4045
+							WHERE nombre COLLATE utf8_general_ci LIKE '%$search_free%')";
4046
+						break;
4047
+				}
4048
+				
4049
+				
4050
 			}
4051
 			else {
4052
 				$sql_search = '';
4053
@@ -899,7 +998,8 @@
4054
 			if ($select_status != -1)
4055
 				$sql_search .= " AND estado = " . $select_status . " ";
4056
 			
4057
-			$sql_search .= tags_get_acl_tags($config['id_user'], 0, 'AR', 'module_condition', 'AND', 't1');
4058
+			$sql_search .= tags_get_acl_tags(
4059
+				$config['id_user'], 0, 'AR', 'module_condition', 'AND', 't1');
4060
 			
4061
 			switch ($config["dbtype"]) {
4062
 				case "mysql":
4063
@@ -915,7 +1015,7 @@
4064
 							$sql_search.'
4065
 						GROUP BY t1.nombre ORDER BY t1.nombre');
4066
 					break;
4067
-				case "oracle":	
4068
+				case "oracle":
4069
 					$list = db_get_all_rows_sql('
4070
 						SELECT dbms_lob.substr(t1.nombre,4000,1) as nombre
4071
 						FROM tagente_modulo t1, tagente t2,
4072
@@ -950,15 +1050,16 @@
4073
 					$search_sql = sprintf(" AND tagente.nombre COLLATE utf8_general_ci LIKE '%%%s%%'", $search_free);
4074
 				}
4075
 				
4076
-				$sql = "SELECT DISTINCT ttag.name 
4077
-						FROM ttag, ttag_module, tagente, tagente_modulo 
4078
-						WHERE ttag.id_tag = ttag_module.id_tag
4079
+				$sql = "
4080
+					SELECT DISTINCT ttag.name 
4081
+					FROM ttag, ttag_module, tagente, tagente_modulo 
4082
+					WHERE ttag.id_tag = ttag_module.id_tag
4083
 						AND tagente.id_agente = tagente_modulo.id_agente
4084
 						AND tagente.disabled = 0
4085
 						AND ttag_module.id_agente_modulo = tagente_modulo.id_agente_modulo" .
4086
 						$search_sql . 
4087
-						$user_tags_sql . 
4088
-						" ORDER BY ttag.name COLLATE utf8_general_ci ASC";
4089
+						$user_tags_sql . "
4090
+					ORDER BY ttag.name ' . $order_collate . ' ASC";
4091
 				
4092
 				$list = db_get_all_rows_sql($sql);
4093
 			break;
4094
@@ -1054,6 +1155,13 @@
4095
 		return false;
4096
 	}
4097
 	
4098
+	$order_collate = "";
4099
+	switch ($config['dbtype']) {
4100
+		case "mysql":
4101
+			$order_collate = "COLLATE utf8_general_ci";
4102
+			break;
4103
+	}
4104
+	
4105
 	//TODO CHANGE POLICY ACL FOR TAG ACL
4106
 	$extra_sql = '';
4107
 	if ($extra_sql != '') {
4108
@@ -1062,7 +1170,18 @@
4109
 	$groups_sql = implode(', ', $avariableGroupsIds);
4110
 	
4111
 	if ($search_free != '') {
4112
-		$search_sql = " AND tagente.nombre COLLATE utf8_general_ci LIKE '%$search_free%'";
4113
+		switch ($config['dbtype']) {
4114
+			case "mysql":
4115
+				$search_sql = " AND tagente.nombre COLLATE utf8_general_ci LIKE '%$search_free%'";
4116
+				break;
4117
+			case "postgresql":
4118
+				$search_sql = " AND tagente.nombre LIKE '%$search_free%'";
4119
+				break;
4120
+			case "oracle":
4121
+				$search_sql = " AND tagente.nombre COLLATE utf8_general_ci LIKE '%$search_free%'";
4122
+				break;
4123
+		}
4124
+		
4125
 	}
4126
 	else {
4127
 		$search_sql = '';
4128
@@ -1078,14 +1197,14 @@
4129
 				}
4130
 			}
4131
 			
4132
-			$sql = agents_get_agents(array (	
4133
+			$sql = agents_get_agents(array (
4134
 				'id_grupo' => $id,
4135
 				'disabled' => 0,
4136
 				'status' => $statusSel,
4137
 				'search' => $search_sql),
4138
 				array ('*'),
4139
 				'AR',
4140
-				array('field' => 'nombre COLLATE utf8_general_ci', 'order' => ' ASC'),
4141
+				array('field' => 'nombre ' . $order_collate, 'order' => ' ASC'),
4142
 				true);
4143
 			break;
4144
 		case 'os':
4145
@@ -1097,7 +1216,7 @@
4146
 				'search' => $search_sql),
4147
 				array ('*'),
4148
 				'AR',
4149
-				array('field' => 'nombre COLLATE utf8_general_ci', 'order' => ' ASC'),
4150
+				array('field' => 'nombre ' . $order_collate, 'order' => ' ASC'),
4151
 				true);
4152
 			break;
4153
 		case 'module_group':
4154
@@ -1117,7 +1236,7 @@
4155
 				FROM tagente_modulo 
4156
 				WHERE id_module_group = ' . $id . ')';
4157
 			
4158
-			$sql .= 'ORDER BY nombre COLLATE utf8_general_ci ASC';
4159
+			$sql .= 'ORDER BY nombre ' . $order_collate . ' ASC';
4160
 			
4161
 			break;
4162
 		case 'policies':
4163
@@ -1144,7 +1263,7 @@
4164
 					AND tagente_estado.utimestamp != 0
4165
 					AND tagente_modulo.id_policy_module != 0
4166
 					AND tpolicy_modules.id_policy = ' . $id . '
4167
-					group by tagente.id_agente
4168
+					GROUP BY tagente.id_agente
4169
 					having COUNT(*) > 0)';
4170
 			}
4171
 			else if ($statusSel == 0) {
4172
@@ -1152,11 +1271,12 @@
4173
 				// If status filter is NORMAL add void agents
4174
 				$sql .= " UNION SELECT * FROM tagente 
4175
 					WHERE tagente.disabled = 0
4176
-					AND tagente.id_agente NOT IN (SELECT tagente_estado.id_agente 
4177
+					AND tagente.id_agente NOT IN (
4178
+						SELECT tagente_estado.id_agente 
4179
 						FROM tagente_estado)";
4180
 			}
4181
 			
4182
-			$sql .= 'ORDER BY nombre COLLATE utf8_general_ci ASC';
4183
+			$sql .= 'ORDER BY nombre ' . $order_collate . ' ASC';
4184
 			
4185
 			break;
4186
 		case 'module':
4187
@@ -1188,7 +1308,7 @@
4188
 				)
4189
 				', $name);
4190
 			
4191
-			$sql .= 'ORDER BY nombre COLLATE utf8_general_ci ASC';
4192
+			$sql .= 'ORDER BY nombre ' . $order_collate . ' ASC';
4193
 			
4194
 			break;
4195
 		case 'tag':
4196
@@ -1219,7 +1339,8 @@
4197
 			
4198
 			$sql .= ' AND tagente.disabled = 0'. $search_sql;
4199
 			
4200
-			$sql .= ' GROUP BY tagente.id_agente ORDER BY tagente.nombre COLLATE utf8_general_ci ASC';
4201
+			$sql .= ' GROUP BY tagente.id_agente
4202
+				ORDER BY tagente.nombre ' . $order_collate . ' ASC';
4203
 			
4204
 			break;
4205
 	}
4206
@@ -1234,25 +1355,36 @@
4207
 // Get SQL for the second tree branch
4208
 function treeview_getSecondBranchSQL ($fatherType, $id, $id_father) {
4209
 	global $config;
4210
+	
4211
+	$order_collate = "";
4212
+	switch ($config['dbtype']) {
4213
+		case "mysql":
4214
+			$order_collate = "COLLATE utf8_general_ci";
4215
+			break;
4216
+	}
4217
+	
4218
 	switch ($fatherType) {
4219
 		case 'group':
4220
 			$sql = 'SELECT * 
4221
 				FROM tagente_modulo AS t1 
4222
-				INNER JOIN tagente_estado AS t2 ON t1.id_agente_modulo = t2.id_agente_modulo
4223
+				INNER JOIN tagente_estado AS t2
4224
+					ON t1.id_agente_modulo = t2.id_agente_modulo
4225
 				WHERE t1.id_agente = ' . $id;
4226
 			$sql .= tags_get_acl_tags($config['id_user'], 0, 'AR', 'module_condition', 'AND', 't1');
4227
 			break;
4228
 		case 'os':
4229
 			$sql = 'SELECT * 
4230
 				FROM tagente_modulo AS t1 
4231
-				INNER JOIN tagente_estado AS t2 ON t1.id_agente_modulo = t2.id_agente_modulo
4232
+				INNER JOIN tagente_estado AS t2
4233
+					ON t1.id_agente_modulo = t2.id_agente_modulo
4234
 				WHERE t1.id_agente = ' . $id;
4235
 			$sql .= tags_get_acl_tags($config['id_user'], 0, 'AR', 'module_condition', 'AND', 't1');
4236
 			break;
4237
 		case 'module_group':
4238
 			$sql = 'SELECT * 
4239
 				FROM tagente_modulo AS t1 
4240
-				INNER JOIN tagente_estado AS t2 ON t1.id_agente_modulo = t2.id_agente_modulo
4241
+				INNER JOIN tagente_estado AS t2
4242
+					ON t1.id_agente_modulo = t2.id_agente_modulo
4243
 				WHERE t1.id_agente = ' . $id . ' AND id_module_group = ' . $id_father;
4244
 			$sql .= tags_get_acl_tags($config['id_user'], 0, 'AR', 'module_condition', 'AND', 't1');
4245
 			break;
4246
@@ -1275,8 +1407,10 @@
4247
 			$symbols = ' !"#$%&\'()*+,./:;<=>?@[\\]^{|}~';
4248
 			$name = $id_father;
4249
 			for ($i = 0; $i < strlen($symbols); $i++) {
4250
-				$name = str_replace('_articapandora_'.ord(substr($symbols, $i, 1)).'_pandoraartica_', substr($symbols, $i, 1), $name);
4251
-			}	
4252
+				$name = str_replace('_articapandora_' .
4253
+					ord(substr($symbols, $i, 1)) .'_pandoraartica_',
4254
+					substr($symbols, $i, 1), $name);
4255
+			}
4256
 			switch ($config["dbtype"]) {
4257
 				case "mysql":
4258
 					$sql = 'SELECT * 
4259
@@ -1315,8 +1449,9 @@
4260
 			break;
4261
 		}
4262
 	
4263
-	// This line checks for initializated modules or (non-initialized) asyncronous modules	
4264
-	$sql .= ' AND disabled = 0 AND (utimestamp > 0 OR id_tipo_modulo IN (21,22,23)) ORDER BY nombre COLLATE utf8_general_ci ASC';
4265
+	// This line checks for initializated modules or (non-initialized) asyncronous modules
4266
+	$sql .= ' AND disabled = 0 AND (utimestamp > 0 OR id_tipo_modulo IN (21,22,23))
4267
+		ORDER BY nombre ' . $order_collate . ' ASC';
4268
 	return $sql;
4269
 }
4270
 ?>
4271
Index: include/functions_config.php
4272
===================================================================
4273
--- include/functions_config.php	(revision 10314)
4274
+++ include/functions_config.php	(working copy)
4275
@@ -182,6 +182,8 @@
4276
 						$error_update[] = __('Command Snapshot');
4277
 					if (!config_update_value ('server_log_dir', get_parameter('server_log_dir')))
4278
 						$error_update[] = __('Server logs directory');
4279
+					if (!config_update_value ('tutorial_mode', get_parameter('tutorial_mode')))
4280
+						$error_update[] = __('Tutorial mode');
4281
 					break;
4282
 				case 'enterprise':
4283
 					if (isset($config['enterprise_installed']) && $config['enterprise_installed'] == 1) {
4284
@@ -433,6 +435,10 @@
4285
 						$error_update[] = __('Default icon in GIS');
4286
 					if (!config_update_value ('autohidden_menu', get_parameter('autohidden_menu')))
4287
 						$error_update[] = __('Autohidden menu');
4288
+					if (!config_update_value ('fixed_header', get_parameter('fixed_header')))
4289
+						$error_update[] = __('Fixed header');
4290
+					if (!config_update_value ('fixed_menu', get_parameter('fixed_menu')))
4291
+						$error_update[] = __('Fixed menu');
4292
 					if (!config_update_value ('paginate_module', get_parameter('paginate_module')))
4293
 						$error_update[] = __('Paginate module');
4294
 					if (!config_update_value ('graphviz_bin_dir', get_parameter('graphviz_bin_dir')))
4295
@@ -781,17 +787,31 @@
4296
 	// 	config_update_value ('autoupdate', true);
4297
 	// }
4298
 	
4299
-	require_once ($config["homedir"]."/include/auth/mysql.php");
4300
+	require_once ($config["homedir"] . "/include/auth/mysql.php");
4301
 	
4302
-	// Next is the directory where "/attachment" directory is placed, to upload files stores. 
4303
-	// This MUST be writtable by http server user, and should be in pandora root. 
4304
-	// By default, Pandora adds /attachment to this, so by default is the pandora console home dir
4305
+	
4306
+	// Next is the directory where "/attachment" directory is placed,
4307
+	// to upload files stores. This MUST be writtable by http server
4308
+	// user, and should be in pandora root. By default, Pandora adds
4309
+	// /attachment to this, so by default is the pandora console home
4310
+	// dir.
4311
 	if (!isset ($config['attachment_store'])) {
4312
-		config_update_value ( 'attachment_store', $config['homedir'].'/attachment');
4313
+		config_update_value('attachment_store',
4314
+			$config['homedir'] . '/attachment');
4315
 	}
4316
+	else {
4317
+		//Fixed when the user moves the pandora console to another dir
4318
+		//after the first uses.
4319
+		if (!is_dir($config['attachment_store'])) {
4320
+			config_update_value('attachment_store',
4321
+				$config['homedir'] . '/attachment');
4322
+		}
4323
+	}
4324
 	
4325
+	
4326
 	if (!isset ($config['fontpath'])) {
4327
-		config_update_value ( 'fontpath', $config['homedir'].'/include/fonts/smallfont.ttf');
4328
+		config_update_value('fontpath',
4329
+			$config['homedir'] . '/include/fonts/smallfont.ttf');
4330
 	}
4331
 	
4332
 	if (!isset ($config['style'])) {
4333
@@ -869,7 +889,7 @@
4334
 	if (!isset ($config['netflow_nfexpire'])) {
4335
 		config_update_value ( 'netflow_nfexpire', '/usr/bin/nfexpire');
4336
 	}
4337
-		
4338
+	
4339
 	if (!isset ($config['netflow_max_resolution'])) {
4340
 		config_update_value ( 'netflow_max_resolution', '50');
4341
 	}
4342
@@ -877,7 +897,7 @@
4343
 	if (!isset ($config['netflow_disable_custom_lvfilters'])) {
4344
 		config_update_value ( 'netflow_disable_custom_lvfilters', 0);
4345
 	}
4346
-
4347
+	
4348
 	if (!isset ($config['netflow_max_lifetime'])) {
4349
 		config_update_value ( 'netflow_max_lifetime', '5');
4350
 	}
4351
@@ -919,13 +939,14 @@
4352
 	}
4353
 	
4354
 	if (!isset ($config['ldap_base_dn'])) {
4355
-		config_update_value ( 'ldap_base_dn', 'ou=People,dc=edu,dc=example,dc=org');
4356
+		config_update_value('ldap_base_dn',
4357
+			'ou=People,dc=edu,dc=example,dc=org');
4358
 	}
4359
 	
4360
 	if (!isset ($config['ldap_login_attr'])) {
4361
 		config_update_value ( 'ldap_login_attr', 'uid');
4362
 	}
4363
-
4364
+	
4365
 	if (!isset ($config['fallback_local_auth'])) {
4366
 		config_update_value ( 'fallback_local_auth', '0');
4367
 	}
4368
@@ -1030,11 +1051,11 @@
4369
 		config_update_value( 'api_password', '');
4370
 	}
4371
 	
4372
-	if(defined('METACONSOLE')) {
4373
+	if (defined('METACONSOLE')) {
4374
 		// Customizable sections (Metaconsole)
4375
 		enterprise_include_once ('include/functions_enterprise.php');
4376
 		$customizable_sections = enterprise_hook('enterprise_get_customizable_sections');
4377
-
4378
+		
4379
 		if($customizable_sections != ENTERPRISE_NOT_HOOK) {
4380
 			foreach($customizable_sections as $k => $v) {
4381
 				if (!isset ($config[$k])) {
4382
@@ -1050,7 +1071,7 @@
4383
 	
4384
 	if (!isset ($config['relative_path']) && (isset ($_POST['nick'])
4385
 		|| isset ($config['id_user'])) && isset($config['enterprise_installed'])) {
4386
-
4387
+		
4388
 		$isFunctionSkins = enterprise_include_once ('include/functions_skins.php');
4389
 		if ($isFunctionSkins !== ENTERPRISE_NOT_HOOK) {
4390
 			
4391
@@ -1153,7 +1174,8 @@
4392
 	}
4393
 	
4394
 	if (!isset($config['custom_report_front_logo'])) {
4395
-		config_update_value ('custom_report_front_logo', 'images/pandora_logo_white.jpg');
4396
+		config_update_value ('custom_report_front_logo',
4397
+			'images/pandora_logo_white.jpg');
4398
 	}
4399
 	
4400
 	if (!isset($config['custom_report_front_header'])) {
4401
@@ -1161,7 +1183,8 @@
4402
 	}
4403
 	
4404
 	if (!isset($config['custom_report_front_firstpage'])) {
4405
-		config_update_value ('custom_report_front_firstpage', "&lt;p&#x20;style=&quot;text-align:&#x20;center;&quot;&gt;&amp;nbsp;&lt;/p&gt;&#x0d;&#x0a;&lt;p&#x20;style=&quot;text-align:&#x20;center;&quot;&gt;&amp;nbsp;&lt;/p&gt;&#x0d;&#x0a;&lt;p&#x20;style=&quot;text-align:&#x20;center;&quot;&gt;&amp;nbsp;&lt;/p&gt;&#x0d;&#x0a;&lt;p&#x20;style=&quot;text-align:&#x20;center;&quot;&gt;&amp;nbsp;&lt;/p&gt;&#x0d;&#x0a;&lt;p&#x20;style=&quot;text-align:&#x20;center;&quot;&gt;&amp;nbsp;&lt;/p&gt;&#x0d;&#x0a;&lt;p&#x20;style=&quot;text-align:&#x20;center;&quot;&gt;&amp;nbsp;&lt;/p&gt;&#x0d;&#x0a;&lt;p&#x20;style=&quot;text-align:&#x20;center;&quot;&gt;&amp;nbsp;&lt;/p&gt;&#x0d;&#x0a;&lt;p&#x20;style=&quot;text-align:&#x20;center;&quot;&gt;&lt;img&#x20;src=&quot;" . ui_get_full_url(false, false, false, false) . "/images/pandora_report_logo.png&quot;&#x20;alt=&quot;&quot;&#x20;width=&quot;800&quot;&#x20;/&gt;&lt;/p&gt;&#x0d;&#x0a;&lt;p&#x20;style=&quot;text-align:&#x20;center;&quot;&gt;&amp;nbsp;&lt;/p&gt;&#x0d;&#x0a;&lt;p&#x20;style=&quot;text-align:&#x20;center;&quot;&gt;&lt;span&#x20;style=&quot;font-size:&#x20;xx-large;&quot;&gt;&#40;_REPORT_NAME_&#41;&lt;/span&gt;&lt;/p&gt;&#x0d;&#x0a;&lt;p&#x20;style=&quot;text-align:&#x20;center;&quot;&gt;&lt;span&#x20;style=&quot;font-size:&#x20;large;&quot;&gt;&#40;_DATETIME_&#41;&lt;/span&gt;&lt;/p&gt;");
4406
+		config_update_value ('custom_report_front_firstpage',
4407
+			"&lt;p&#x20;style=&quot;text-align:&#x20;center;&quot;&gt;&amp;nbsp;&lt;/p&gt;&#x0d;&#x0a;&lt;p&#x20;style=&quot;text-align:&#x20;center;&quot;&gt;&amp;nbsp;&lt;/p&gt;&#x0d;&#x0a;&lt;p&#x20;style=&quot;text-align:&#x20;center;&quot;&gt;&amp;nbsp;&lt;/p&gt;&#x0d;&#x0a;&lt;p&#x20;style=&quot;text-align:&#x20;center;&quot;&gt;&amp;nbsp;&lt;/p&gt;&#x0d;&#x0a;&lt;p&#x20;style=&quot;text-align:&#x20;center;&quot;&gt;&amp;nbsp;&lt;/p&gt;&#x0d;&#x0a;&lt;p&#x20;style=&quot;text-align:&#x20;center;&quot;&gt;&amp;nbsp;&lt;/p&gt;&#x0d;&#x0a;&lt;p&#x20;style=&quot;text-align:&#x20;center;&quot;&gt;&amp;nbsp;&lt;/p&gt;&#x0d;&#x0a;&lt;p&#x20;style=&quot;text-align:&#x20;center;&quot;&gt;&lt;img&#x20;src=&quot;" . ui_get_full_url(false, false, false, false) . "/images/pandora_report_logo.png&quot;&#x20;alt=&quot;&quot;&#x20;width=&quot;800&quot;&#x20;/&gt;&lt;/p&gt;&#x0d;&#x0a;&lt;p&#x20;style=&quot;text-align:&#x20;center;&quot;&gt;&amp;nbsp;&lt;/p&gt;&#x0d;&#x0a;&lt;p&#x20;style=&quot;text-align:&#x20;center;&quot;&gt;&lt;span&#x20;style=&quot;font-size:&#x20;xx-large;&quot;&gt;&#40;_REPORT_NAME_&#41;&lt;/span&gt;&lt;/p&gt;&#x0d;&#x0a;&lt;p&#x20;style=&quot;text-align:&#x20;center;&quot;&gt;&lt;span&#x20;style=&quot;font-size:&#x20;large;&quot;&gt;&#40;_DATETIME_&#41;&lt;/span&gt;&lt;/p&gt;");
4408
 	}
4409
 	
4410
 	if (!isset($config['custom_report_front_footer'])) {
4411
@@ -1176,6 +1199,10 @@
4412
 		config_update_value ('networkmap_max_width', 900);
4413
 	}
4414
 	
4415
+	if (!isset($config['tutorial_mode'])) {
4416
+		config_update_value ('tutorial_mode', 'full');
4417
+	}
4418
+	
4419
 	/* Finally, check if any value was overwritten in a form */
4420
 	config_update_config();
4421
 }
4422
@@ -1312,7 +1339,7 @@
4423
 			$config["alert_cnt"]++;
4424
 			$_SESSION["alert_msg"] .= ui_print_info_message(
4425
 				array('title' => __("New update of Pandora Console"),
4426
-				'message' => __('There is a new update please go to menu Administration and into extensions <a style="font-weight:bold;" href="index.php?sec=gsetup&sec2=godmode/update_manager_xxx/update_manager_xxx&tab=online">go to Update Manager</a> for more details.'),
4427
+				'message' => __('There is a new update please go to menu Administration and into extensions <a style="font-weight:bold;" href="index.php?sec=gsetup&sec2=godmode/update_manager/update_manager&tab=online">go to Update Manager</a> for more details.'),
4428
 				'no_close' => true, 'force_style' => 'color: #000000 !important'), '', true);
4429
 		}
4430
 	}
4431
Index: include/help/clippy/godmode_agentes_modificar_agente.php
4432
===================================================================
4433
--- include/help/clippy/godmode_agentes_modificar_agente.php	(revision 0)
4434
+++ include/help/clippy/godmode_agentes_modificar_agente.php	(revision 10417)
4435
@@ -0,0 +1,71 @@
4436
+<?php
4437
+
4438
+// Pandora FMS - http://pandorafms.com
4439
+// ==================================================
4440
+// Copyright (c) 2005-2011 Artica Soluciones Tecnologicas
4441
+// Please see http://pandorafms.org for full contribution list
4442
+
4443
+// This program is free software; you can redistribute it and/or
4444
+// modify it under the terms of the  GNU Lesser General Public License
4445
+// as published by the Free Software Foundation; version 2
4446
+
4447
+// This program is distributed in the hope that it will be useful,
4448
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
4449
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
4450
+// GNU General Public License for more details.
4451
+
4452
+/**
4453
+ * @package Include
4454
+ * @subpackage Clippy
4455
+ */
4456
+
4457
+function clippy_start_page() {
4458
+	
4459
+	$helps = array();
4460
+	
4461
+	//==================================================================
4462
+	//Help tour about the monitoring with a ping (step 1)
4463
+	//------------------------------------------------------------------
4464
+	$helps['monitoring_server_step_1'] = array();
4465
+	$helps['monitoring_server_step_1']['steps'] = array();
4466
+	$helps['monitoring_server_step_1']['steps'][] = array(
4467
+		'element'=> '#clippy',
4468
+		'intro' => __('I show how to monitoring a server.')
4469
+		);
4470
+	$helps['monitoring_server_step_1']['steps'][] = array(
4471
+		'element'=> 'input[name="search"]',
4472
+		'intro' => __('Please type a agent to save the modules for monitoring a server.')
4473
+		);
4474
+	$helps['monitoring_server_step_1']['steps'][] = array(
4475
+		'element'=> 'input[name="srcbutton"]',
4476
+		'intro' => __('Maybe if you typped correctly the name, you can see the agent.')
4477
+		);
4478
+	$helps['monitoring_server_step_1']['conf'] = array();
4479
+	$helps['monitoring_server_step_1']['conf']['showBullets'] = 0;
4480
+	$helps['monitoring_server_step_1']['conf']['showStepNumbers'] = 1;
4481
+	$helps['monitoring_server_step_1']['conf']['next_help'] = 'monitoring_server_step_2';
4482
+	//==================================================================
4483
+	
4484
+	
4485
+	//==================================================================
4486
+	//Help tour about the monitoring with a ping (step 2)
4487
+	//------------------------------------------------------------------
4488
+	$helps['monitoring_server_step_2'] = array();
4489
+	$helps['monitoring_server_step_2']['steps'] = array();
4490
+	$helps['monitoring_server_step_2']['steps'][] = array(
4491
+		'element'=> '#clippy',
4492
+		'intro' => __('Please choose the agent that you have searched.')
4493
+		);
4494
+	$helps['monitoring_server_step_2']['steps'][] = array(
4495
+		'element'=> '#agent_list',
4496
+		'intro' => __('Choose the agent, please click in the name.')
4497
+		);
4498
+	$helps['monitoring_server_step_2']['conf'] = array();
4499
+	$helps['monitoring_server_step_2']['conf']['showBullets'] = 0;
4500
+	$helps['monitoring_server_step_2']['conf']['showStepNumbers'] = 0;
4501
+	$helps['monitoring_server_step_2']['conf']['next_help'] = 'monitoring_server_step_3';
4502
+	//==================================================================
4503
+	
4504
+	clippy_write_javascript_helps_steps($helps, false);
4505
+}
4506
+?>
4507
\ No newline at end of file
4508
Index: include/help/clippy/homepage.php
4509
===================================================================
4510
--- include/help/clippy/homepage.php	(revision 0)
4511
+++ include/help/clippy/homepage.php	(revision 10417)
4512
@@ -0,0 +1,105 @@
4513
+<?php
4514
+
4515
+// Pandora FMS - http://pandorafms.com
4516
+// ==================================================
4517
+// Copyright (c) 2005-2011 Artica Soluciones Tecnologicas
4518
+// Please see http://pandorafms.org for full contribution list
4519
+
4520
+// This program is free software; you can redistribute it and/or
4521
+// modify it under the terms of the  GNU Lesser General Public License
4522
+// as published by the Free Software Foundation; version 2
4523
+
4524
+// This program is distributed in the hope that it will be useful,
4525
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
4526
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
4527
+// GNU General Public License for more details.
4528
+
4529
+/**
4530
+ * @package Include
4531
+ * @subpackage Clippy
4532
+ */
4533
+
4534
+function clippy_start_page_homepage() {
4535
+	global $config;
4536
+	
4537
+	$clippy_is_annoying = (int)get_cookie('clippy_is_annoying', 0);
4538
+	
4539
+	clippy_clean_help();
4540
+	
4541
+	$helps = array();
4542
+	
4543
+	//==================================================================
4544
+	//Help tour with the some task for to help the user.
4545
+	//------------------------------------------------------------------
4546
+	$helps['homepage'] = array();
4547
+	$helps['homepage']['steps'] = array();
4548
+	$helps['homepage']['steps'][] = array(
4549
+		'element'=> '#clippy',
4550
+		'intro' => __('Could I help you?<br/><br/>I am Pandorin, the annoying clippy for Pandora. You could follow my advices for to make common and basic tasks in Pandora.') .
4551
+			'<div style="position:relative;">
4552
+			<div id="pandorin" style="display: block; position: absolute; left: -100px; top: 20px;">' .
4553
+				html_print_image('images/pandorin.png', true) .
4554
+			'</div>
4555
+			</div>'
4556
+		);
4557
+	$helps['homepage']['steps'][] = array(
4558
+		'element'=> '#clippy',
4559
+		'intro' => __('What task do you want to do?') . '<br/><br/>' .
4560
+			'<ul style="text-align: left; margin-left: 3px; list-style-type: disc;">' .
4561
+				'<li>' .
4562
+					"<a href='javascript: clippy_go_link_show_help(\"index.php?sec=gagente&sec2=godmode/agentes/modificar_agente\", \"monitoring_server_step_1\");'>" . 
4563
+					//'<a href="index.php?sec=gagente&sec2=godmode/agentes/modificar_agente&clippy=monitoring_server">' . 
4564
+						__('Monitoring a server Linux/Windows with a pandora agent') .
4565
+					'</a>' .
4566
+				'</li>' .
4567
+				'<li>' . __('Monitoring a switch with remote SNMP') . '</li>' .
4568
+				'<li>' . __('Monitoring a Windows server with remote WMI ') . '</li>' .
4569
+			'</ul>' .
4570
+			'<div style="text-align: left;">'.
4571
+			html_print_checkbox_extended
4572
+				('clippy_is_annoying', 1, $clippy_is_annoying, false,
4573
+				'set_clippy_annoying()', '', true) .
4574
+				__('Please the clippy is annoying, I don\'t want see.') .
4575
+			'</div>'
4576
+		);
4577
+	$helps['homepage']['conf'] = array();
4578
+	$helps['homepage']['conf']['showBullets'] = 0;
4579
+	$helps['homepage']['conf']['showStepNumbers'] = 0;
4580
+	$helps['homepage']['conf']['name_obj_tour'] = 'intro_homepage';
4581
+	$helps['homepage']['conf']['other_js'] = "
4582
+		function show_clippy() {
4583
+			intro_homepage.start();
4584
+		}
4585