mirror of
https://github.com/BlackLight/Snort_AIPreproc.git
synced 2024-11-23 20:25:12 +01:00
Updated documentation and Makefile
This commit is contained in:
parent
d7b3d1aff1
commit
e9dd3ebfa2
8 changed files with 129 additions and 307 deletions
14
Makefile.am
14
Makefile.am
|
@ -47,15 +47,14 @@ doc:
|
||||||
doxygen; \
|
doxygen; \
|
||||||
fi
|
fi
|
||||||
|
|
||||||
doc-install:
|
|
||||||
if test ! -z "${DOC_PREFIX}"; then \
|
|
||||||
mkdir -p "${DOC_PREFIX}"; \
|
|
||||||
cp -r doc/* "${DOC_PREFIX}"; \
|
|
||||||
fi
|
|
||||||
|
|
||||||
install-data-hook:
|
install-data-hook:
|
||||||
|
if test ! -z "${PWD}/doc"; then \
|
||||||
|
mkdir -p "${SHARE_PREFIX}/doc"; \
|
||||||
|
cp -r "${PWD}/doc/"* "${SHARE_PREFIX}/doc"; \
|
||||||
|
fi
|
||||||
mkdir -p "${SHARE_PREFIX}/htdocs"
|
mkdir -p "${SHARE_PREFIX}/htdocs"
|
||||||
mkdir -p "${SHARE_PREFIX}/htdocs/js"
|
mkdir -p "${SHARE_PREFIX}/htdocs/js"
|
||||||
|
mkdir -p "${SHARE_PREFIX}/schemas"
|
||||||
install -m 0644 "${PWD}/htdocs/index.html" "${SHARE_PREFIX}/htdocs"
|
install -m 0644 "${PWD}/htdocs/index.html" "${SHARE_PREFIX}/htdocs"
|
||||||
install -m 0755 "${PWD}/htdocs/pcap.cgi" "${SHARE_PREFIX}/htdocs"
|
install -m 0755 "${PWD}/htdocs/pcap.cgi" "${SHARE_PREFIX}/htdocs"
|
||||||
install -m 0644 "${PWD}/htdocs/js/Curry-1.0.1.js" "${SHARE_PREFIX}/htdocs/js"
|
install -m 0644 "${PWD}/htdocs/js/Curry-1.0.1.js" "${SHARE_PREFIX}/htdocs/js"
|
||||||
|
@ -64,3 +63,6 @@ install-data-hook:
|
||||||
install -m 0644 "${PWD}/htdocs/js/dracula_graph.js" "${SHARE_PREFIX}/htdocs/js"
|
install -m 0644 "${PWD}/htdocs/js/dracula_graph.js" "${SHARE_PREFIX}/htdocs/js"
|
||||||
install -m 0644 "${PWD}/htdocs/js/raphael.js" "${SHARE_PREFIX}/htdocs/js"
|
install -m 0644 "${PWD}/htdocs/js/raphael.js" "${SHARE_PREFIX}/htdocs/js"
|
||||||
install -m 0644 "${PWD}/htdocs/js/seedrandom.js" "${SHARE_PREFIX}/htdocs/js"
|
install -m 0644 "${PWD}/htdocs/js/seedrandom.js" "${SHARE_PREFIX}/htdocs/js"
|
||||||
|
install -m 0644 "${PWD}/schemas/mysql.sql" "${SHARE_PREFIX}/schemas"
|
||||||
|
install -m 0644 "${PWD}/schemas/postgresql.sql" "${SHARE_PREFIX}/schemas"
|
||||||
|
install -m 0644 "${PWD}/schemas/database_ER.png" "${SHARE_PREFIX}/schemas"
|
||||||
|
|
14
Makefile.in
14
Makefile.in
|
@ -823,15 +823,14 @@ doc:
|
||||||
doxygen; \
|
doxygen; \
|
||||||
fi
|
fi
|
||||||
|
|
||||||
doc-install:
|
|
||||||
if test ! -z "${DOC_PREFIX}"; then \
|
|
||||||
mkdir -p "${DOC_PREFIX}"; \
|
|
||||||
cp -r doc/* "${DOC_PREFIX}"; \
|
|
||||||
fi
|
|
||||||
|
|
||||||
install-data-hook:
|
install-data-hook:
|
||||||
|
if test ! -z "${PWD}/doc"; then \
|
||||||
|
mkdir -p "${SHARE_PREFIX}/doc"; \
|
||||||
|
cp -r "${PWD}/doc/"* "${SHARE_PREFIX}/doc"; \
|
||||||
|
fi
|
||||||
mkdir -p "${SHARE_PREFIX}/htdocs"
|
mkdir -p "${SHARE_PREFIX}/htdocs"
|
||||||
mkdir -p "${SHARE_PREFIX}/htdocs/js"
|
mkdir -p "${SHARE_PREFIX}/htdocs/js"
|
||||||
|
mkdir -p "${SHARE_PREFIX}/schemas"
|
||||||
install -m 0644 "${PWD}/htdocs/index.html" "${SHARE_PREFIX}/htdocs"
|
install -m 0644 "${PWD}/htdocs/index.html" "${SHARE_PREFIX}/htdocs"
|
||||||
install -m 0755 "${PWD}/htdocs/pcap.cgi" "${SHARE_PREFIX}/htdocs"
|
install -m 0755 "${PWD}/htdocs/pcap.cgi" "${SHARE_PREFIX}/htdocs"
|
||||||
install -m 0644 "${PWD}/htdocs/js/Curry-1.0.1.js" "${SHARE_PREFIX}/htdocs/js"
|
install -m 0644 "${PWD}/htdocs/js/Curry-1.0.1.js" "${SHARE_PREFIX}/htdocs/js"
|
||||||
|
@ -840,6 +839,9 @@ install-data-hook:
|
||||||
install -m 0644 "${PWD}/htdocs/js/dracula_graph.js" "${SHARE_PREFIX}/htdocs/js"
|
install -m 0644 "${PWD}/htdocs/js/dracula_graph.js" "${SHARE_PREFIX}/htdocs/js"
|
||||||
install -m 0644 "${PWD}/htdocs/js/raphael.js" "${SHARE_PREFIX}/htdocs/js"
|
install -m 0644 "${PWD}/htdocs/js/raphael.js" "${SHARE_PREFIX}/htdocs/js"
|
||||||
install -m 0644 "${PWD}/htdocs/js/seedrandom.js" "${SHARE_PREFIX}/htdocs/js"
|
install -m 0644 "${PWD}/htdocs/js/seedrandom.js" "${SHARE_PREFIX}/htdocs/js"
|
||||||
|
install -m 0644 "${PWD}/schemas/mysql.sql" "${SHARE_PREFIX}/schemas"
|
||||||
|
install -m 0644 "${PWD}/schemas/postgresql.sql" "${SHARE_PREFIX}/schemas"
|
||||||
|
install -m 0644 "${PWD}/schemas/database_ER.png" "${SHARE_PREFIX}/schemas"
|
||||||
|
|
||||||
# Tell versions [3.59,3.63) of GNU make to not export all variables.
|
# Tell versions [3.59,3.63) of GNU make to not export all variables.
|
||||||
# Otherwise a system limit (for SysV at least) may be exceeded.
|
# Otherwise a system limit (for SysV at least) may be exceeded.
|
||||||
|
|
107
README
107
README
|
@ -28,7 +28,9 @@ Table of contents:
|
||||||
3.2 Configure options
|
3.2 Configure options
|
||||||
4. Basic configuration
|
4. Basic configuration
|
||||||
5. Correlation rules
|
5. Correlation rules
|
||||||
6. Additional documentation
|
6. Output database
|
||||||
|
7. Web interface
|
||||||
|
8. Additional documentation
|
||||||
|
|
||||||
|
|
||||||
===============================
|
===============================
|
||||||
|
@ -119,6 +121,14 @@ disabled by the default, and can be enabled by specifying the option
|
||||||
--with-postgresql to ./configure. On a Debian-based system you may need to
|
--with-postgresql to ./configure. On a Debian-based system you may need to
|
||||||
install libpq-dev.
|
install libpq-dev.
|
||||||
|
|
||||||
|
- A DBMS (RECOMMANDED), MySQL and PostgreSQL are supported for now, for writing
|
||||||
|
clusters, correlations and packet streams information on a DBMS, making the
|
||||||
|
analysis easier.
|
||||||
|
|
||||||
|
- Perl (OPTIONAL), used for the CGI script in the web interface that saves a
|
||||||
|
packet stream associated to an alert in .pcap format, to be analyzed by tools
|
||||||
|
like tcpdump and Wireshark.
|
||||||
|
|
||||||
|
|
||||||
=====================
|
=====================
|
||||||
3.2 Configure options
|
3.2 Configure options
|
||||||
|
@ -145,8 +155,6 @@ following:
|
||||||
|
|
||||||
|
|
||||||
preprocessor ai: \
|
preprocessor ai: \
|
||||||
hashtable_cleanup_interval 300 \
|
|
||||||
tcp_stream_expire_interval 300 \
|
|
||||||
alertfile "/your/snort/dir/log/alert" \
|
alertfile "/your/snort/dir/log/alert" \
|
||||||
alert_history_file "/your/snort/dir/log/alert_history" \
|
alert_history_file "/your/snort/dir/log/alert_history" \
|
||||||
alert_serialization_interval 3600 \
|
alert_serialization_interval 3600 \
|
||||||
|
@ -158,9 +166,6 @@ preprocessor ai: \
|
||||||
correlation_rules_dir "/your/snort/dir/etc/corr_rules" \
|
correlation_rules_dir "/your/snort/dir/etc/corr_rules" \
|
||||||
correlated_alerts_dir "/your/snort/dir/log/correlated_alerts" \
|
correlated_alerts_dir "/your/snort/dir/log/correlated_alerts" \
|
||||||
correlation_threshold_coefficient 0.5 \
|
correlation_threshold_coefficient 0.5 \
|
||||||
database ( type="dbtype", name="snort", user="snortusr", password="snortpass", host="dbhost" ) \
|
|
||||||
output_database ( type="dbtype", name="snort", user="snortusr", password="snortpass", host="dbhost" ) \
|
|
||||||
database_parsing_interval 30 \
|
|
||||||
cluster_max_alert_interval 14400 \
|
cluster_max_alert_interval 14400 \
|
||||||
clusterfile "/your/snort/dir/log/clustered_alerts" \
|
clusterfile "/your/snort/dir/log/clustered_alerts" \
|
||||||
cluster ( class="dst_port", name="privileged_ports", range="1-1023" ) \
|
cluster ( class="dst_port", name="privileged_ports", range="1-1023" ) \
|
||||||
|
@ -170,7 +175,16 @@ preprocessor ai: \
|
||||||
cluster ( class="src_addr", name="vpn_net", range="10.8.0.0/24" ) \
|
cluster ( class="src_addr", name="vpn_net", range="10.8.0.0/24" ) \
|
||||||
cluster ( class="dst_addr", name="local_net", range="192.168.1.0/24" ) \
|
cluster ( class="dst_addr", name="local_net", range="192.168.1.0/24" ) \
|
||||||
cluster ( class="dst_addr", name="dmz_net", range="155.185.0.0/16" ) \
|
cluster ( class="dst_addr", name="dmz_net", range="155.185.0.0/16" ) \
|
||||||
cluster ( class="dst_addr", name="vpn_net", range="10.8.0.0/24" )
|
cluster ( class="dst_addr", name="vpn_net", range="10.8.0.0/24" ) \
|
||||||
|
database ( type="dbtype", name="snort", user="snortusr", password="snortpass", host="dbhost" ) \
|
||||||
|
database_parsing_interval 30 \
|
||||||
|
hashtable_cleanup_interval 300 \
|
||||||
|
output_database ( type="dbtype", name="snort", user="snortusr", password="snortpass", host="dbhost" ) \
|
||||||
|
tcp_stream_expire_interval 300 \
|
||||||
|
webserv_banner "Snort AIPreprocessor module" \
|
||||||
|
webserv_dir "/prefix/share/htdocs" \
|
||||||
|
webserv_port 7654
|
||||||
|
|
||||||
|
|
||||||
The options are the following:
|
The options are the following:
|
||||||
|
|
||||||
|
@ -298,6 +312,19 @@ stream as "expired", if no more packets are received inside of that and it's not
|
||||||
"marked" as suspicious (default if not specified: 300 seconds)
|
"marked" as suspicious (default if not specified: 300 seconds)
|
||||||
|
|
||||||
|
|
||||||
|
- webserv_banner: Banner of the web server, to be placed on the error pages and
|
||||||
|
in the "Server" HTTP reply header
|
||||||
|
|
||||||
|
- webserver_dir: Directory containing the contents of the web server running
|
||||||
|
over the module (default if none is specified:
|
||||||
|
$PREFIX/share/snort_ai_preprocessor/htdocs)
|
||||||
|
|
||||||
|
- webserver_port: Port where the web server will listen (default if none is
|
||||||
|
specified: 7654). Set this value to 0 if you don't want to run the web server
|
||||||
|
over the module for having the web interface (in this case, if you want to see
|
||||||
|
the web graphical visualization of the alerts, you should manually copy the
|
||||||
|
files contained in htdocs/ in a web server directory)
|
||||||
|
|
||||||
====================
|
====================
|
||||||
5. Correlation rules
|
5. Correlation rules
|
||||||
====================
|
====================
|
||||||
|
@ -365,11 +392,73 @@ matching would fail. Any new predicates can be defined as well in
|
||||||
hyperalerts, provided that it respects this constraint.
|
hyperalerts, provided that it respects this constraint.
|
||||||
|
|
||||||
|
|
||||||
|
==================
|
||||||
|
6. Output database
|
||||||
|
==================
|
||||||
|
|
||||||
|
If the output_database option is specified in the documentation, the alerts, and
|
||||||
|
the relative clusters, correlations and packet streams information, will be
|
||||||
|
saved on a database as well. This is strongly suggested, first for making the
|
||||||
|
management of the module's information easier (a SELECT query needs to be done
|
||||||
|
for doing also complex searches instead of grep-ing or manually
|
||||||
|
searching inside of a text file), second because the web interface of
|
||||||
|
the module can work ONLY if the output_database option is specified (the web
|
||||||
|
interface strongly depends on the unique IDs assigned to the alerts by
|
||||||
|
the database interface). Note that for using this option you should
|
||||||
|
explicitly tell to the ./configure script which DBMS you're going to use, so
|
||||||
|
that it knows which APIs to use for interfacing with the database, e.g. via
|
||||||
|
--with-mysql or --with-postgresql.
|
||||||
|
|
||||||
|
After you compile the module, you should pick up the right .sql file from
|
||||||
|
schemas/ directory (for example mysql.sql or postgresql.sql), or from
|
||||||
|
$PREFIX/share/snort_ai_preprocessor/schemas after the installation of the
|
||||||
|
module, and import it in your database,
|
||||||
|
|
||||||
|
$ mysql -uusername -ppassword dbname < schemas/mysql.sql (for MySQL)
|
||||||
|
$ psql -U username -W dbname < schemas/postgresql.sql (for PostgreSQL)
|
||||||
|
|
||||||
|
You can check the structure of the database from the SQL file for your DBMS, or
|
||||||
|
from the E/R schema saved in schemas/database_ER.png.
|
||||||
|
|
||||||
|
|
||||||
|
================
|
||||||
|
7. Web interface
|
||||||
|
================
|
||||||
|
|
||||||
|
The module provides an optional (but strongly recommanded) web interface for
|
||||||
|
browsing the triggered (and already clustered) security alerts, their
|
||||||
|
correlations and their packet streams information from your browser. This
|
||||||
|
feature can be switched off by setting the configuration option "webserv_port"
|
||||||
|
of the module to 0. Otherwise, if none between webserv_dir and webserv_port are
|
||||||
|
specified, the web server thread starts with the module picking by default the
|
||||||
|
directory $PREFIX/share/snort_ai_preproc/htdocs as document root and listening
|
||||||
|
for incoming connections on the port 7654.
|
||||||
|
|
||||||
|
You should use a browser supporting JavaScript, AJAX and SVG technologies in
|
||||||
|
order to view correctly the alert web interface on your browser (successfully
|
||||||
|
tested with Firefox 3.5, Chrome and Opera 10), for example, connecting
|
||||||
|
to the address http://localhost:7654. You can drag and drop the nodes in the
|
||||||
|
graph, modifying the layout of the graph on the fly or using the "redraw"
|
||||||
|
function. Each node represents a clustered alert. For viewing the information
|
||||||
|
over that cluster and the alerts group inside, just click on the node. You can
|
||||||
|
optionally save the stream of packets associated to a certain alert in .pcap
|
||||||
|
format (analyzable by tools like tcpdump and Wireshark) from this same
|
||||||
|
interface. This feature, anyway, is based on the CGI script pcap.cgi inside of
|
||||||
|
the document root, and it requires the Perl interpreter to be installed on the
|
||||||
|
machine.
|
||||||
|
|
||||||
|
The web server running over the module is a true web server with its own
|
||||||
|
document path, so you can use it as stand-alone web server as well and place
|
||||||
|
your documents and files inside. You can moreover place some CGI scripts or
|
||||||
|
applications made in the language you prefer, as long as they are files
|
||||||
|
executable by any users and they have the extension ".cgi".
|
||||||
|
|
||||||
|
|
||||||
===========================
|
===========================
|
||||||
6. Additional documentation
|
8. Additional documentation
|
||||||
===========================
|
===========================
|
||||||
|
|
||||||
The additional documentation over the code, functions and data structures can
|
The additional documentation over the code, functions and data structures can
|
||||||
be automatically generated by Doxygen by typing `make doc', and installed in
|
be automatically generated by Doxygen by typing `make doc', and installed in
|
||||||
SNORT_DIR/doc then typing `make doc-install'.
|
$PREFIX/share/snort_ai_preproc/doc then after `make install'.
|
||||||
|
|
||||||
|
|
3
TODO
3
TODO
|
@ -6,9 +6,9 @@ AVERAGE/HIGH PRIORITY:
|
||||||
- Modules for correlation coefficients
|
- Modules for correlation coefficients
|
||||||
- Code profiling
|
- Code profiling
|
||||||
- Comment all the code!!!
|
- Comment all the code!!!
|
||||||
- Saving packet flows as .pcap
|
|
||||||
- Neural network for computing k
|
- Neural network for computing k
|
||||||
- Testing more scenarios, making more hyperalert models
|
- Testing more scenarios, making more hyperalert models
|
||||||
|
- Manual alert correlation from the web interface
|
||||||
|
|
||||||
=============
|
=============
|
||||||
LOW PRIORITY:
|
LOW PRIORITY:
|
||||||
|
@ -36,4 +36,5 @@ DONE:
|
||||||
+ Full PostgreSQL support for output db
|
+ Full PostgreSQL support for output db
|
||||||
+ Web interface
|
+ Web interface
|
||||||
+ Function names (private functions with _ or __ ?)
|
+ Function names (private functions with _ or __ ?)
|
||||||
|
+ Saving packet flows as .pcap
|
||||||
|
|
||||||
|
|
|
@ -211,19 +211,19 @@ window.onload = function() {
|
||||||
|
|
||||||
switch ( month )
|
switch ( month )
|
||||||
{
|
{
|
||||||
case 'Jan': month = 1; break;
|
case 'Jan': month = 0; break;
|
||||||
case 'Feb': month = 2; break;
|
case 'Feb': month = 1; break;
|
||||||
case 'Mar': month = 3; break;
|
case 'Mar': month = 2; break;
|
||||||
case 'Apr': month = 4; break;
|
case 'Apr': month = 3; break;
|
||||||
case 'May': month = 5; break;
|
case 'May': month = 4; break;
|
||||||
case 'Jun': month = 6; break;
|
case 'Jun': month = 5; break;
|
||||||
case 'Jul': month = 7; break;
|
case 'Jul': month = 6; break;
|
||||||
case 'Ago': month = 8; break;
|
case 'Ago': month = 7; break;
|
||||||
case 'Sep': month = 9; break;
|
case 'Sep': month = 8; break;
|
||||||
case 'Oct': month = 10; break;
|
case 'Oct': month = 9; break;
|
||||||
case 'Nov': month = 11; break;
|
case 'Nov': month = 10; break;
|
||||||
case 'Dec': month = 12; break;
|
case 'Dec': month = 11; break;
|
||||||
default : month = 1; break;
|
default : month = 0; break;
|
||||||
}
|
}
|
||||||
|
|
||||||
var timestamp = new Date ( year, month, day, hour, min, sec).getTime().toString();
|
var timestamp = new Date ( year, month, day, hour, min, sec).getTime().toString();
|
||||||
|
|
|
@ -1,143 +0,0 @@
|
||||||
/**
|
|
||||||
*
|
|
||||||
* Base64 encode / decode
|
|
||||||
* http://www.webtoolkit.info/
|
|
||||||
*
|
|
||||||
**/
|
|
||||||
|
|
||||||
var Base64 = {
|
|
||||||
|
|
||||||
// private property
|
|
||||||
_keyStr : "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",
|
|
||||||
|
|
||||||
// public method for encoding
|
|
||||||
encode : function (input) {
|
|
||||||
var output = "";
|
|
||||||
var chr1, chr2, chr3, enc1, enc2, enc3, enc4;
|
|
||||||
var i = 0;
|
|
||||||
|
|
||||||
input = Base64._utf8_encode(input);
|
|
||||||
|
|
||||||
while (i < input.length) {
|
|
||||||
|
|
||||||
chr1 = input.charCodeAt(i++);
|
|
||||||
chr2 = input.charCodeAt(i++);
|
|
||||||
chr3 = input.charCodeAt(i++);
|
|
||||||
|
|
||||||
enc1 = chr1 >> 2;
|
|
||||||
enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
|
|
||||||
enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
|
|
||||||
enc4 = chr3 & 63;
|
|
||||||
|
|
||||||
if (isNaN(chr2)) {
|
|
||||||
enc3 = enc4 = 64;
|
|
||||||
} else if (isNaN(chr3)) {
|
|
||||||
enc4 = 64;
|
|
||||||
}
|
|
||||||
|
|
||||||
output = output +
|
|
||||||
this._keyStr.charAt(enc1) + this._keyStr.charAt(enc2) +
|
|
||||||
this._keyStr.charAt(enc3) + this._keyStr.charAt(enc4);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
return output;
|
|
||||||
},
|
|
||||||
|
|
||||||
// public method for decoding
|
|
||||||
decode : function (input) {
|
|
||||||
var output = "";
|
|
||||||
var chr1, chr2, chr3;
|
|
||||||
var enc1, enc2, enc3, enc4;
|
|
||||||
var i = 0;
|
|
||||||
|
|
||||||
input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");
|
|
||||||
|
|
||||||
while (i < input.length) {
|
|
||||||
|
|
||||||
enc1 = this._keyStr.indexOf(input.charAt(i++));
|
|
||||||
enc2 = this._keyStr.indexOf(input.charAt(i++));
|
|
||||||
enc3 = this._keyStr.indexOf(input.charAt(i++));
|
|
||||||
enc4 = this._keyStr.indexOf(input.charAt(i++));
|
|
||||||
|
|
||||||
chr1 = (enc1 << 2) | (enc2 >> 4);
|
|
||||||
chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
|
|
||||||
chr3 = ((enc3 & 3) << 6) | enc4;
|
|
||||||
|
|
||||||
output = output + String.fromCharCode(chr1);
|
|
||||||
|
|
||||||
if (enc3 != 64) {
|
|
||||||
output = output + String.fromCharCode(chr2);
|
|
||||||
}
|
|
||||||
if (enc4 != 64) {
|
|
||||||
output = output + String.fromCharCode(chr3);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
output = Base64._utf8_decode(output);
|
|
||||||
|
|
||||||
return output;
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
// private method for UTF-8 encoding
|
|
||||||
_utf8_encode : function (string) {
|
|
||||||
string = string.replace(/\r\n/g,"\n");
|
|
||||||
var utftext = "";
|
|
||||||
|
|
||||||
for (var n = 0; n < string.length; n++) {
|
|
||||||
|
|
||||||
var c = string.charCodeAt(n);
|
|
||||||
|
|
||||||
if (c < 128) {
|
|
||||||
utftext += String.fromCharCode(c);
|
|
||||||
}
|
|
||||||
else if((c > 127) && (c < 2048)) {
|
|
||||||
utftext += String.fromCharCode((c >> 6) | 192);
|
|
||||||
utftext += String.fromCharCode((c & 63) | 128);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
utftext += String.fromCharCode((c >> 12) | 224);
|
|
||||||
utftext += String.fromCharCode(((c >> 6) & 63) | 128);
|
|
||||||
utftext += String.fromCharCode((c & 63) | 128);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
return utftext;
|
|
||||||
},
|
|
||||||
|
|
||||||
// private method for UTF-8 decoding
|
|
||||||
_utf8_decode : function (utftext) {
|
|
||||||
var string = "";
|
|
||||||
var i = 0;
|
|
||||||
var c = c1 = c2 = 0;
|
|
||||||
|
|
||||||
while ( i < utftext.length ) {
|
|
||||||
|
|
||||||
c = utftext.charCodeAt(i);
|
|
||||||
|
|
||||||
if (c < 128) {
|
|
||||||
string += String.fromCharCode(c);
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
else if((c > 191) && (c < 224)) {
|
|
||||||
c2 = utftext.charCodeAt(i+1);
|
|
||||||
string += String.fromCharCode(((c & 31) << 6) | (c2 & 63));
|
|
||||||
i += 2;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
c2 = utftext.charCodeAt(i+1);
|
|
||||||
c3 = utftext.charCodeAt(i+2);
|
|
||||||
string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
|
|
||||||
i += 3;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
return string;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,129 +0,0 @@
|
||||||
var dom = (document.getElementById) ? true : false;
|
|
||||||
var ns5 = ((navigator.userAgent.indexOf("Gecko")>-1) && dom) ? true: false;
|
|
||||||
var ie5 = ((navigator.userAgent.indexOf("MSIE")>-1) && dom) ? true : false;
|
|
||||||
var ns4 = (document.layers && !dom) ? true : false;
|
|
||||||
var ie4 = (document.all && !dom) ? true : false;
|
|
||||||
var nodyn = (!ns5 && !ns4 && !ie4 && !ie5) ? true : false;
|
|
||||||
|
|
||||||
var origWidth, origHeight;
|
|
||||||
if (ns4) {
|
|
||||||
origWidth = window.innerWidth; origHeight = window.innerHeight;
|
|
||||||
window.onresize = function() { if (window.innerWidth != origWidth || window.innerHeight != origHeight) history.go(0); }
|
|
||||||
}
|
|
||||||
|
|
||||||
if (nodyn) { event = "nope" }
|
|
||||||
var tipFollowMouse = true;
|
|
||||||
var tipWidth = 160;
|
|
||||||
var offX = 12; // how far from mouse to show tip
|
|
||||||
var offY = 12;
|
|
||||||
var tipFontFamily = "Verdana, arial, helvetica, sans-serif";
|
|
||||||
var tipFontSize = "8pt";
|
|
||||||
var tipFontColor = "#000000";
|
|
||||||
var tipBgColor = "#DDECFF";
|
|
||||||
var origBgColor = tipBgColor; // in case no bgColor set in array
|
|
||||||
var tipBorderColor = "#000080";
|
|
||||||
var tipBorderWidth = 2;
|
|
||||||
var tipBorderStyle = "ridge";
|
|
||||||
var tipPadding = 4;
|
|
||||||
|
|
||||||
var messages = new Array();
|
|
||||||
messages[0] = new Array('http://planmagic.com/images/plmbiz.jpg','Professional business planning software.',"#FFFFFF");
|
|
||||||
messages[1] = new Array('http://planmagic.com/images/plmmar.jpg','Professional marketing planning software.',"#DDECFF");
|
|
||||||
messages[2] = new Array('http://planmagic.com/images/plmfinance.jpg','Financial calculations and projections made easy.',"#E9E9E9");
|
|
||||||
|
|
||||||
if (document.images) {
|
|
||||||
var theImgs = new Array();
|
|
||||||
for (var i=0; i<messages.length; i++) {
|
|
||||||
theImgs[i] = new Image();
|
|
||||||
theImgs[i].src = messages[i][0];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var startStr = '<table width="' + tipWidth + '"><tr><td align="center" width="100%"><img src="';
|
|
||||||
var midStr = '" border="0"></td></tr><tr><td valign="top">';
|
|
||||||
var endStr = '</td></tr></table>';
|
|
||||||
|
|
||||||
var tooltip, tipcss;
|
|
||||||
function initTip() {
|
|
||||||
if (nodyn) return;
|
|
||||||
tooltip = (ns4)? document.tipDiv.document: (ie4)? document.all['tipDiv']: (ie5||ns5)? document.getElementById('tipDiv'): null;
|
|
||||||
tipcss = (ns4)? document.tipDiv: tooltip.style;
|
|
||||||
if (ie4||ie5||ns5) { // ns4 would lose all this on rewrites
|
|
||||||
tipcss.width = tipWidth+"px";
|
|
||||||
tipcss.fontFamily = tipFontFamily;
|
|
||||||
tipcss.fontSize = tipFontSize;
|
|
||||||
tipcss.color = tipFontColor;
|
|
||||||
tipcss.backgroundColor = tipBgColor;
|
|
||||||
tipcss.borderColor = tipBorderColor;
|
|
||||||
tipcss.borderWidth = tipBorderWidth+"px";
|
|
||||||
tipcss.padding = tipPadding+"px";
|
|
||||||
tipcss.borderStyle = tipBorderStyle;
|
|
||||||
}
|
|
||||||
if (tooltip&&tipFollowMouse) {
|
|
||||||
if (ns4) document.captureEvents(Event.MOUSEMOVE);
|
|
||||||
document.onmousemove = trackMouse;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
window.onload = initTip;
|
|
||||||
|
|
||||||
var t1,t2; // for setTimeouts
|
|
||||||
var tipOn = false; // check if over tooltip link
|
|
||||||
function doTooltip(evt,num) {
|
|
||||||
|
|
||||||
if (!tooltip) return;
|
|
||||||
if (t1) clearTimeout(t1); if (t2) clearTimeout(t2);
|
|
||||||
tipOn = true;
|
|
||||||
// set colors if included in messages array
|
|
||||||
if (messages[num][2]) var curBgColor = messages[num][2];
|
|
||||||
else curBgColor = tipBgColor;
|
|
||||||
if (messages[num][3]) var curFontColor = messages[num][3];
|
|
||||||
else curFontColor = tipFontColor;
|
|
||||||
if (ns4) {
|
|
||||||
var tip = '<table bgcolor="' + tipBorderColor + '" width="' + tipWidth + '" cellspacing="0" cellpadding="' + tipBorderWidth + '" border="0"><tr><td><table bgcolor="' + curBgColor + '" width="100%" cellspacing="0" cellpadding="' + tipPadding + '" border="0"><tr><td>'+ startStr + messages[num][0] + midStr + '<span style="font-family:' + tipFontFamily + '; font-size:' + tipFontSize + '; color:' + curFontColor + ';">' + messages[num][1] + '</span>' + endStr + '</td></tr></table></td></tr></table>';
|
|
||||||
tooltip.write(tip);
|
|
||||||
tooltip.close();
|
|
||||||
} else if (ie4||ie5||ns5) {
|
|
||||||
var tip = startStr + messages[num][0] + midStr + '<span style="font-family:' + tipFontFamily + '; font-size:' + tipFontSize + '; color:' + curFontColor + ';">' + messages[num][1] + '</span>' + endStr;
|
|
||||||
tipcss.backgroundColor = curBgColor;
|
|
||||||
tooltip.innerHTML = tip;
|
|
||||||
}
|
|
||||||
if (!tipFollowMouse) positionTip(evt);
|
|
||||||
else t1=setTimeout("tipcss.visibility='visible'",100);
|
|
||||||
}
|
|
||||||
|
|
||||||
var mouseX, mouseY;
|
|
||||||
function trackMouse(evt) {
|
|
||||||
mouseX = (ns4||ns5)? evt.pageX: window.event.clientX + document.body.scrollLeft;
|
|
||||||
mouseY = (ns4||ns5)? evt.pageY: window.event.clientY + document.body.scrollTop;
|
|
||||||
if (tipOn) positionTip(evt);
|
|
||||||
}
|
|
||||||
|
|
||||||
function positionTip(evt) {
|
|
||||||
if (!tipFollowMouse) {
|
|
||||||
mouseX = (ns4||ns5)? evt.pageX: window.event.clientX + document.body.scrollLeft;
|
|
||||||
mouseY = (ns4||ns5)? evt.pageY: window.event.clientY + document.body.scrollTop;
|
|
||||||
}
|
|
||||||
// tooltip width and height
|
|
||||||
var tpWd = (ns4)? tooltip.width: (ie4||ie5)? tooltip.clientWidth: tooltip.offsetWidth;
|
|
||||||
var tpHt = (ns4)? tooltip.height: (ie4||ie5)? tooltip.clientHeight: tooltip.offsetHeight;
|
|
||||||
// document area in view (subtract scrollbar width for ns)
|
|
||||||
var winWd = (ns4||ns5)? window.innerWidth-20+window.pageXOffset: document.body.clientWidth+document.body.scrollLeft;
|
|
||||||
var winHt = (ns4||ns5)? window.innerHeight-20+window.pageYOffset: document.body.clientHeight+document.body.scrollTop;
|
|
||||||
// check mouse position against tip and window dimensions
|
|
||||||
// and position the tooltip
|
|
||||||
if ((mouseX+offX+tpWd)>winWd)
|
|
||||||
tipcss.left = (ns4)? mouseX-(tpWd+offX): mouseX-(tpWd+offX)+"px";
|
|
||||||
else tipcss.left = (ns4)? mouseX+offX: mouseX+offX+"px";
|
|
||||||
if ((mouseY+offY+tpHt)>winHt)
|
|
||||||
tipcss.top = (ns4)? winHt-(tpHt+offY): winHt-(tpHt+offY)+"px";
|
|
||||||
else tipcss.top = (ns4)? mouseY+offY: mouseY+offY+"px";
|
|
||||||
if (!tipFollowMouse) t1=setTimeout("tipcss.visibility='visible'",100);
|
|
||||||
}
|
|
||||||
|
|
||||||
function hideTip() {
|
|
||||||
if (!tooltip) return;
|
|
||||||
t2=setTimeout("tipcss.visibility='hidden'",100);
|
|
||||||
tipOn = false;
|
|
||||||
}
|
|
||||||
|
|
BIN
schemas/database_ER.png
Normal file
BIN
schemas/database_ER.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 22 KiB |
Loading…
Reference in a new issue